-- 135_scrape_schedules_seed_house_dedup_merge.sql
-- Scheduler seed for the recurring house-deduplication merge (#1772).
--
-- WHAT (source='house_dedup_merge'):
--   trigger_house_dedup_merge_run (scheduler.py) → run_house_dedup_merge
--   (services/house_dedup_merge.py) → merge_duplicate_houses. Recurring, idempotent,
--   collision-safe merge of duplicate `houses` rows:
--     1. Cluster houses by EXACT address (cadastral_number is 100% NULL on prod — confirmed
--        in migration 040 — so address is the real building key). Only addresses shared by
--        >1 house_id form a cluster.
--     2. Pick one canonical keeper per cluster: geom NOT NULL → most linked listings →
--        most-populated fields → min(id).
--     3. Re-point every FK child of houses(id) onto the keeper with UNIQUE-collision handling
--        (reuses migration 108's proven cluster→canonical→re-point→delete pattern). The 11
--        children + their constraints (listings, house_placement_history, house_reviews,
--        house_reliability_checks, external_valuations, house_sources, house_address_aliases,
--        houses_price_dynamics [LIVE 6-col UNIQUE per migration 029], house_imv_evaluations,
--        house_suggestions, address_mismatch_audit).
--     4. DELETE the loser house rows; backfill house_sources + house_address_aliases onto the
--        keeper so the matching pipeline (Tier-1/2) finds the keeper next scrape (reduces
--        recurrence). ALL in ONE transaction.
--   Idempotent: a clean table yields an empty mapping → every statement is a 0-row no-op.
--   dry_run param computes the same counts then ROLLBACKs (no writes).
--
-- WHY RECURRING (not a one-shot migration):
--   Migration 108 did a ONE-TIME merge, but duplicates RECUR — the matching pipeline keeps
--   creating them (Tier-3 geo-jitter + per-source ext_id INSERTs). A migration cannot fix a
--   steady-state inflow; this schedule re-runs and is a no-op when there is nothing to merge.
--
-- *** enabled=false (DORMANT) — DEPLOY MUST BE NEUTRAL ***
--   This is an auto-recurring DESTRUCTIVE merge (it DELETEs duplicate house rows). The deploy
--   ships it DISABLED so nothing fires automatically. The orchestrator dry-runs it
--   (default_params.dry_run=true on a manual run) + does ONE validated manual run, then flips
--   enabled=true deliberately:
--       UPDATE scrape_schedules SET enabled = true WHERE source = 'house_dedup_merge';
--
-- Window 04:00-05:00 UTC (07:00-08:00 MSK):
--   - Quiet hour: after the overnight scraper/sweep block and before the morning Avito block
--     (city_sweep 06-07, detail_backfill 09-12). Pure internal DB op — no scraper/proxy
--     contention. interval_days=7 → weekly cadence (default_params).
--   - next_run_at = tomorrow 04:00 UTC (NOT NULL — follows the seed convention; harmless while
--     enabled=false, since get_due_schedules filters enabled=true first).
--
-- default_params:
--   dry_run       -- false: actually merge. The orchestrator overrides to true on a manual run
--                    to preview counts without writing.
--   interval_days -- 7: weekly cadence (compute_next_run_at reads this).
--
-- DEPENDENCIES: 052_scrape_schedules.sql (table + UNIQUE(source)),
--   108_merge_duplicate_houses.sql (the proven collision-safe pattern this reuses),
--   029_extend_matching_valuation_dynamics.sql (LIVE 6-col houses_price_dynamics UNIQUE).
-- Idempotent: ON CONFLICT (source) DO NOTHING.
-- Runner applies migrations WITHOUT --single-transaction, so wrap in explicit BEGIN/COMMIT.

BEGIN;

INSERT INTO scrape_schedules (
    source,
    enabled,
    window_start_hour,
    window_end_hour,
    next_run_at,
    default_params
)
VALUES
(
    'house_dedup_merge',
    false,
    4,
    5,
    ((CURRENT_DATE + INTERVAL '1 day') + make_interval(hours => 4)) AT TIME ZONE 'UTC',
    '{"dry_run": false, "interval_days": 7}'::jsonb
)
ON CONFLICT (source) DO NOTHING;

COMMENT ON TABLE scrape_schedules IS
    'In-app scheduler config (replaces cron-script setup). Sources: avito_city_sweep, yandex_city_sweep (dormant, #561), cian_history_backfill, rosreestr_dkp_import, listing_source_snapshot (#570), asking_to_sold_ratio_refresh (#648), refresh_search_matview (#769), yandex_address_backfill (#855, EKB pilot), sber_index_pull (#887, monthly), rosreestr_quarter_poll (#888, monthly), cian_city_sweep (dormant, #973), yandex_newbuilding_sweep (dormant, #974), geocode_missing_listings (#1: listings geom backfill, all sources), avito_detail_backfill (#1551: nightly detail-enrichment backfill for legacy avito listings), house_imv_backfill (#854: nightly bulk Avito IMV at house level → house_imv_evaluations), house_dedup_merge (#1772: recurring collision-safe merge of duplicate houses by exact address — DORMANT enabled=false, DESTRUCTIVE, enable deliberately after a validated dry-run + manual run).';

COMMIT;
