-- 016_listings_snapshots.sql
-- CREATE TABLE listings_snapshots — append-only daily price/status history
--
-- Dependencies:
--   002_core_tables.sql (listings table — FK listing_id)
--   015_scrape_runs.sql (scrape_runs table — FK run_id)
--
-- Apply after: 015_scrape_runs.sql
-- Apply before: 017_house_placement_history.sql
--
-- Source: decisions/Schema_Avito_Houses_Listings_History.md sec 4.4
-- Pattern: аналог objective_lots_history из основной GenDesign БД.
--
-- ON CONFLICT DO UPDATE: берём последний snapshot за день (если за сутки несколько run'ов).
-- Cleanup policy: хранить вечно (data moat). Partitioning отложить на 1-2 года.
--
-- Идемпотентно: безопасно запускать повторно.

BEGIN;

CREATE TABLE IF NOT EXISTS listings_snapshots (
    listing_id        bigint NOT NULL REFERENCES listings(id) ON DELETE CASCADE,
    snapshot_date     date NOT NULL DEFAULT CURRENT_DATE,
    run_id            bigint REFERENCES scrape_runs(id),

    -- Snapshot изменяющихся полей
    price_rub         bigint NOT NULL,
    price_per_m2      int,
    position_in_serp  int,                               -- 1..60 — позиция в поисковой выдаче
    status            text,                              -- 'active' / 'closed' / null (unknown)

    observed_at       timestamptz NOT NULL DEFAULT NOW(),

    -- 1 snapshot в день максимум (ON CONFLICT DO UPDATE в scrapers)
    PRIMARY KEY (listing_id, snapshot_date)
);

CREATE INDEX IF NOT EXISTS listings_snapshots_run_idx          ON listings_snapshots (run_id);
CREATE INDEX IF NOT EXISTS listings_snapshots_listing_date_idx ON listings_snapshots (listing_id, snapshot_date DESC);
-- Для "что нового/изменилось сегодня" запросов
CREATE INDEX IF NOT EXISTS listings_snapshots_date_idx         ON listings_snapshots (snapshot_date DESC);

COMMENT ON TABLE listings_snapshots IS
    'Append-only ежедневные снэпшоты listings. PRIMARY KEY (listing_id, snapshot_date) = max 1/день. '
    'Pattern: objective_lots_history. ON CONFLICT DO UPDATE — берём последний за день.';
COMMENT ON COLUMN listings_snapshots.position_in_serp IS
    'Позиция в поисковой выдаче (1-60). NULL для snapshot''ов из non-search sources.';
COMMENT ON COLUMN listings_snapshots.status IS
    '''active'' = видели в run, ''closed'' = не нашли (пропало). NULL = неизвестно.';

COMMIT;
