-- 015_scrape_runs.sql
-- CREATE TABLE scrape_runs — логирование scrape-сессий с heartbeat + lifecycle
--
-- Dependencies: нет (независимая таблица)
-- Apply after: 014_house_reviews.sql
-- Apply before: 016_listings_snapshots.sql
--
-- Source: decisions/Schema_Avito_Houses_Listings_History.md sec 4.3
-- Status enum: running / done / failed / zombie / skipped / banned
--
-- Паттерн совпадает с objective_scrape_runs из основной GenDesign БД.
-- Zombie detection: cron каждые 5 мин помечает runs где heartbeat_at < NOW() - 30 min.
--
-- Идемпотентно: безопасно запускать повторно.

BEGIN;

CREATE TABLE IF NOT EXISTS scrape_runs (
    id               bigserial PRIMARY KEY,
    source           text NOT NULL,                      -- 'avito' / 'cian' / ...
    run_type         text NOT NULL,                      -- 'search' / 'house_catalog' / 'detail' / 'imv'

    -- Scope (для search runs — геометрия поиска)
    anchor_lat       double precision,
    anchor_lon       double precision,
    radius_m         int,
    segment          text,                               -- 'vtorichka' / 'novostroyki'

    -- Scope (для house_catalog/detail runs)
    target_ext_id    text,                               -- house_id или item_id

    -- Lifecycle
    started_at       timestamptz NOT NULL DEFAULT NOW(),
    heartbeat_at     timestamptz NOT NULL DEFAULT NOW(),  -- обновляется каждые N сек в process loop
    finished_at      timestamptz,
    status           text NOT NULL DEFAULT 'running'
                         CHECK (status IN ('running','done','failed','zombie','skipped','banned')),
    error_text       text,

    -- Counters (для аналитики и debugging)
    total_seen        int DEFAULT 0,                     -- кол-во объявлений в выдаче
    new_count         int DEFAULT 0,                     -- новых (не было в БД)
    returning_count   int DEFAULT 0,                     -- видели → пропали → снова видим
    disappeared_count int DEFAULT 0,                     -- пропали (last_seen > cutoff после run)

    -- HTTP stats (для мониторинга rate limits)
    http_requests     int DEFAULT 0,
    http_errors       int DEFAULT 0
);

CREATE INDEX IF NOT EXISTS scrape_runs_source_started_idx ON scrape_runs (source, started_at DESC);
-- Partial index для zombie detection (только 'running' статус)
CREATE INDEX IF NOT EXISTS scrape_runs_zombies_idx        ON scrape_runs (status, heartbeat_at)
    WHERE status = 'running';

COMMENT ON TABLE scrape_runs IS
    'Лог scrape-сессий. Heartbeat обновляется в process loop. '
    'Zombie: status=running AND heartbeat_at < NOW() - 30 min — помечается cron.';
COMMENT ON COLUMN scrape_runs.status IS
    'Enum: running=активен, done=успех, failed=ошибка, zombie=heartbeat устарел, '
    'skipped=нет новых данных, banned=Avito вернул 403/captcha.';
COMMENT ON COLUMN scrape_runs.returning_count IS
    'Объявления которые пропадали (is_active=false) и снова появились в выдаче.';

COMMIT;
