-- 125_scrape_schedules_seed_cadastral_geo_match.sql
-- Scheduler seed for the geo-nearest cadastral building matcher (combined refresh + match).
--
-- WHAT (source='cadastral_geo_match'):
--   trigger_cadastral_geo_match_run (scheduler.py) → run_cadastral_geo_match
--   (tasks/cadastral_geo_match.py). One combined nightly job:
--     1. REFRESH: TRUNCATE cad_buildings_local; bulk INSERT from gendesign_cad_buildings FDW
--        (single FDW scan, ~36.7k EKB rows, builds Point geom).
--     2. MATCH:   set-based LATERAL KNN UPDATE — fills listings.building_cadastral_number
--        from the nearest cad_buildings_local within threshold_m (default 50m).
--   Refresh-then-match in ONE run guarantees the match always reads a fresh mirror.
--
--   The match is GEO-NEAREST (approximate): a street-level-geocoded listing matches the
--   nearest building, not necessarily its exact cadastral building. Deliberate first
--   increment; exact cadastral + parcel-containment deferred (cad_parcels FDW not exposed).
--
-- Pure internal DB op (one FDW read + local UPDATE) — no external HTTP, no anti-bot.
--   SAFE to enable by default (enabled=true), like listing_source_snapshot / refresh_search_matview.
--
-- Window 09:00-10:00 UTC (12:00-13:00 MSK):
--   - After geocode_missing_listings (06:00-09:00 UTC) → listings have fresh lat/lon/geom.
--   - Before/independent of avito_detail_backfill proxy work; pure-DB so no contention.
--
-- default_params:
--   threshold_m   -- max nearest-building distance to accept a match (metres). 50 = balance
--                    of coverage vs precision for street-level geocodes (see PR EXPLAIN evidence).
--   batch_size    -- listings updated per LATERAL UPDATE statement (chunked to bound lock/WAL).
--   only_missing  -- if true (default) only fills WHERE building_cadastral_number IS NULL
--                    (idempotent: a re-run is a no-op once filled). false = re-match all.
--
-- next_run_at = tomorrow 09:00 UTC (NOT NULL — avoid deploy-time fire, follow avito/cian seed
--   convention; NULL would make get_due_schedules pick it up on the very next tick).
--
-- DEPENDENCIES: 052_scrape_schedules.sql (table + UNIQUE(source)), 124_cad_buildings_local.sql.
-- Idempotent: ON CONFLICT (source) DO NOTHING.

BEGIN;

INSERT INTO scrape_schedules (
    source,
    enabled,
    window_start_hour,
    window_end_hour,
    next_run_at,
    default_params
)
VALUES
(
    'cadastral_geo_match',
    true,
    9,
    10,
    ((CURRENT_DATE + INTERVAL '1 day') + make_interval(hours => 9)) AT TIME ZONE 'UTC',
    '{"threshold_m": 50, "batch_size": 5000, "only_missing": true}'::jsonb
)
ON CONFLICT (source) DO NOTHING;

COMMIT;
