-- Централизованная таблица настроек для всех Celery-job'ов.
--
-- Контекст:
--   До этой миграции конфиг был разбросан по трём местам:
--     • scrape_kn      — env-переменные SCRAPE_KN_CRON / SCRAPE_KN_DEFAULT_REGIONS
--     • nspd_geo       — per-row rate_ms в nspd_geo_jobs (нет global default)
--     • objective_etl  — hardcode в settings + env OBJECTIVE_ANTON_SQLITE_PATH
--     • objective_sync — уже в objective_sync_config (оставляем как deprecated fallback)
--
--   Цель: единая таблица job_settings — один UI /admin/jobs/settings для всех job'ов.
--
-- Зависимости:
--   Нет FK на другие таблицы. objective_sync_config НЕ дропается — она помечается
--   DEPRECATED и остаётся как fallback для уже задеплоенного backend-кода.
--
-- Порядок применения:
--   Применяется один раз на чистой или работающей БД.
--   Идемпотентно (CREATE IF NOT EXISTS + INSERT ON CONFLICT DO NOTHING).
--   Backend-код должен быть задеплоен ПОСЛЕ этой миграции.
--
-- Проверка после применения:
--   SELECT * FROM job_settings;  -- должна вернуть 4 строки
--   SELECT * FROM objective_sync_config;  -- должна по-прежнему работать

BEGIN;

-- ── Создание таблицы ─────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS job_settings (
    job_type        TEXT PRIMARY KEY,
    -- 'scrape_kn' | 'nspd_geo' | 'objective_etl' | 'objective_sync'
    enabled         BOOLEAN NOT NULL DEFAULT true,
    queue_name      TEXT    NOT NULL DEFAULT 'celery',
    -- celery (default) | scrape_kn | geo
    cron_schedule   TEXT,
    -- Стандартный crontab: 'minute hour dom month dow'. NULL = только ручной запуск.
    rate_ms         INTEGER,
    -- Пауза между API-запросами (мс). NULL/0 = не throttled.
    max_retries     SMALLINT NOT NULL DEFAULT 2,
    max_concurrency SMALLINT NOT NULL DEFAULT 1,
    -- Макс. параллельных task'ов этого типа.
    extra_config    JSONB    NOT NULL DEFAULT '{}'::jsonb,
    -- Job-specific: {"regions":[66], "groups_csv":"...", "sqlite_path":"..."}.
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_by      TEXT,
    description     TEXT
    -- Человеко-читаемое описание для UI.
);

COMMENT ON TABLE job_settings IS
    'Centralized settings for all Celery jobs. See /admin/jobs/settings UI. '
    'Replaces scattered env vars and per-table configs.';

COMMENT ON COLUMN job_settings.queue_name IS
    'Celery queue routing. Allows concurrency between job types within one worker container.';

COMMENT ON COLUMN job_settings.cron_schedule IS
    'Standard crontab string (5-field: minute hour dom month dow). '
    'NULL = manual trigger only. Beat re-reads on restart.';

COMMENT ON COLUMN job_settings.rate_ms IS
    'Delay between API calls in milliseconds (used by NSPD geo). NULL/0 for non-throttled jobs.';

COMMENT ON COLUMN job_settings.extra_config IS
    'Job-specific JSON config: e.g. {"regions":[66,77], "groups_csv":"Свердловская область,...", '
    '"sqlite_path":"/data/anton-sqlite/analysis.db"}.';

-- ── Seed данные ───────────────────────────────────────────────────────────────
-- ON CONFLICT DO NOTHING — безопасен при повторном запуске.
-- Defaults взяты из:
--   scrape_kn      → backend/app/core/config.py (scrape_kn_cron / scrape_kn_default_regions)
--   nspd_geo       → nspd_geo_jobs.rate_ms most common value (600) на проде
--   objective_etl  → backend/app/core/config.py (objective_anton_sqlite_path)
--   objective_sync → objective_sync_config.cron_schedule (prod value '0 6 * * tue')

INSERT INTO job_settings
    (job_type, enabled, queue_name, cron_schedule, rate_ms, max_retries,
     max_concurrency, extra_config, description)
VALUES
    (
        'scrape_kn',
        true,
        'scrape_kn',
        '15 4 * * mon',
        NULL,
        2,
        1,
        '{"default_regions": [66]}'::jsonb,
        'Скрейпинг КН (ЦИАН): загрузка объявлений по регионам. '
        'Расписание и регионы ранее задавались через env SCRAPE_KN_CRON / SCRAPE_KN_DEFAULT_REGIONS.'
    ),
    (
        'nspd_geo',
        true,
        'geo',
        NULL,
        600,
        2,
        1,
        '{}'::jsonb,
        'Геокодирование объектов через НСПД/rosreestr2coord. '
        'Запускается вручную по job-конфигурациям nspd_geo_jobs. rate_ms — глобальный дефолт.'
    ),
    (
        'objective_etl',
        true,
        'celery',
        NULL,
        NULL,
        2,
        1,
        '{"sqlite_path": "/data/anton-sqlite/analysis.db"}'::jsonb,
        'ETL: SQLite Антоновского → PG (objective_* таблицы). '
        'Запускается вручную. sqlite_path ранее задавался через env OBJECTIVE_ANTON_SQLITE_PATH.'
    ),
    (
        'objective_sync',
        true,
        'celery',
        '0 6 * * tue',
        NULL,
        2,
        1,
        '{
            "groups_csv":         "Свердловская область,Челябинск,Тюмень,Пермь",
            "use_ddu":            true,
            "use_dkp":            true,
            "period_months_back": 1,
            "inter_group_delay_s": 30,
            "rate_ms":            3000
        }'::jsonb,
        'Синхронизация DOM.РФ Objective (отчёты). '
        'Детальный конфиг дублирован в objective_sync_config (deprecated legacy fallback).'
    )
ON CONFLICT (job_type) DO NOTHING;

-- ── Пометить objective_sync_config как deprecated ─────────────────────────────
-- Таблица НЕ дропается: backend продолжает читать её как fallback до рефакторинга.
COMMENT ON TABLE objective_sync_config IS
    'DEPRECATED: use job_settings (job_type=''objective_sync'') for new config reads. '
    'Kept for backward compat until backend refactor. Do NOT drop until refactor is deployed.';

COMMIT;
