-- Соединение всех источников с canonical complexes (Phase A.2 продолжение).
-- Применено в проде через mcp postgres 2026-05-11.
-- Идемпотентно через ADD COLUMN IF NOT EXISTS / FK с REFERENCES.

-- ── 1. complexes.cad_quarter / cad_building_num: связь с rosreestr/NSPD ─────
ALTER TABLE complexes
  ADD COLUMN IF NOT EXISTS cad_quarter TEXT,
  ADD COLUMN IF NOT EXISTS cad_building_num TEXT;
CREATE INDEX IF NOT EXISTS complexes_cad_quarter_idx
    ON complexes(cad_quarter) WHERE cad_quarter IS NOT NULL;
CREATE INDEX IF NOT EXISTS complexes_cad_building_idx
    ON complexes(cad_building_num) WHERE cad_building_num IS NOT NULL;

-- Backfill: any non-null snapshot
WITH best_kn AS (
    SELECT obj_id,
           (array_agg(cad_quarter ORDER BY snapshot_date DESC NULLS LAST)
              FILTER (WHERE cad_quarter IS NOT NULL))[1] AS cad_quarter,
           (array_agg(cad_building_num ORDER BY snapshot_date DESC NULLS LAST)
              FILTER (WHERE cad_building_num IS NOT NULL))[1] AS cad_building_num
      FROM domrf_kn_objects GROUP BY obj_id
)
UPDATE complexes c
   SET cad_quarter = COALESCE(c.cad_quarter, bk.cad_quarter),
       cad_building_num = COALESCE(c.cad_building_num, bk.cad_building_num),
       updated_at = NOW()
  FROM complex_sources cs
  JOIN best_kn bk ON bk.obj_id::text = cs.source_id
 WHERE cs.complex_id = c.id AND cs.source = 'domrf_kn';
-- Эффект: cad_quarter заполнено у 551 из 1740 ЖК (32%).
-- cad_building_num = 0 (бaг kn-API: не парсит здание-уровень).

-- ── 2. objective_lots.complex_id (FK на complexes) ──────────────────────────
ALTER TABLE objective_lots
  ADD COLUMN IF NOT EXISTS complex_id BIGINT REFERENCES complexes(id) ON DELETE SET NULL;
ALTER TABLE objective_corpus_room_month
  ADD COLUMN IF NOT EXISTS complex_id BIGINT REFERENCES complexes(id) ON DELETE SET NULL;
ALTER TABLE objective_lots_history
  ADD COLUMN IF NOT EXISTS complex_id BIGINT REFERENCES complexes(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS objective_lots_complex_idx
  ON objective_lots(complex_id) WHERE complex_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS objective_crm_complex_idx
  ON objective_corpus_room_month(complex_id) WHERE complex_id IS NOT NULL;

UPDATE objective_lots ol
   SET complex_id = cs.complex_id
  FROM complex_sources cs
 WHERE cs.source = 'objective' AND cs.source_id = ol.project_name
   AND ol.complex_id IS NULL;

UPDATE objective_corpus_room_month ocrm
   SET complex_id = cs.complex_id
  FROM complex_sources cs
 WHERE cs.source = 'objective' AND cs.source_id = ocrm.project_name
   AND ocrm.complex_id IS NULL;
-- Эффект: 303 677 lots / 19 738 crm — 100% покрытие (все Objective lots
-- теперь напрямую JOIN'ятся с complex без двойного хопа через source_id).

-- ── 3. cad_buildings.complex_id (spatial join 50м) ──────────────────────────
ALTER TABLE cad_buildings
  ADD COLUMN IF NOT EXISTS complex_id BIGINT REFERENCES complexes(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS cad_buildings_complex_idx
  ON cad_buildings(complex_id) WHERE complex_id IS NOT NULL;

WITH bld_complex AS (
    SELECT cb.cad_num, c.complex_id_match
      FROM cad_buildings cb
      CROSS JOIN LATERAL (
        SELECT c2.id AS complex_id_match
          FROM complexes c2
         WHERE c2.geom IS NOT NULL
           AND ST_DWithin(c2.geom::geography, cb.geom::geography, 50)
         ORDER BY c2.geom <-> cb.geom LIMIT 1
      ) c
     WHERE cb.geom IS NOT NULL AND cb.complex_id IS NULL
)
UPDATE cad_buildings cb
   SET complex_id = bc.complex_id_match
  FROM bld_complex bc WHERE cb.cad_num = bc.cad_num;
-- Эффект: 716 buildings / 10590 (~7%) связаны с 436 уникальными ЖК.
-- Низкое покрытие т.к. большинство cad_buildings — частные дома в кадастровых
-- кварталах, не относящиеся к ЖК. Радиус 50м консервативный.

-- ── 4. Auto-create stub complex для 283 orphan obj_id из kn_flats ───────────
WITH orphan_obj_ids AS (
    SELECT DISTINCT obj_id FROM domrf_kn_flats f
     WHERE NOT EXISTS (
        SELECT 1 FROM complex_sources cs
         WHERE cs.source='domrf_kn' AND cs.source_id = f.obj_id::text
     )
),
inserted AS (
    INSERT INTO complexes (canonical_name, region_id, primary_source)
    SELECT 'orphan-kn-' || obj_id, 66, 'domrf_kn_flat_orphan' FROM orphan_obj_ids
    RETURNING id, canonical_name
)
INSERT INTO complex_sources (
    complex_id, source, source_id, source_external_id,
    match_method, match_score, is_reviewed, note
)
SELECT i.id, 'domrf_kn', oo.obj_id::text, oo.obj_id, 'orphan_flats_only', 0.0, FALSE,
       'auto-created stub: flats existed but kn-objects entry deleted/missing'
  FROM orphan_obj_ids oo
  JOIN inserted i ON i.canonical_name = 'orphan-kn-' || oo.obj_id;
-- Эффект: complexes 1740 → 2023 (+283 stub).

-- ── 5. v_complex_full v2: правильные counts с многокорпусными ЖК ────────────
DROP VIEW IF EXISTS v_complex_full;
CREATE VIEW v_complex_full AS
SELECT
    c.id AS complex_id,
    c.canonical_name, c.developer_name, c.region_id, c.district_name,
    c.obj_class, c.address, c.latitude, c.longitude,
    c.geom IS NOT NULL AS has_geom,
    c.flat_count, c.square_living, c.site_status,
    c.cad_quarter, c.cad_building_num,
    (SELECT array_agg(DISTINCT source ORDER BY source)
       FROM complex_sources WHERE complex_id = c.id) AS sources,
    (SELECT COUNT(*) FROM complex_sources WHERE complex_id = c.id) AS source_links_n,
    (SELECT COUNT(DISTINCT source) FROM complex_sources WHERE complex_id = c.id) AS source_kinds_n,
    (SELECT array_agg(source_external_id ORDER BY source_external_id)
       FROM complex_sources WHERE complex_id = c.id AND source = 'domrf_kn') AS domrf_obj_ids,
    (SELECT source_id FROM complex_sources
       WHERE complex_id = c.id AND source = 'objective' LIMIT 1) AS objective_project_name,
    (SELECT COUNT(*) FROM domrf_kn_flats f
        WHERE f.obj_id IN (SELECT source_external_id FROM complex_sources
                            WHERE complex_id = c.id AND source = 'domrf_kn'
                              AND source_external_id IS NOT NULL)) AS kn_flats_n,
    (SELECT COUNT(*) FROM objective_lots WHERE complex_id = c.id) AS objective_lots_n,
    (SELECT COUNT(*) FROM cad_buildings WHERE complex_id = c.id) AS cad_buildings_n,
    c.primary_source, c.created_at, c.updated_at
  FROM complexes c;

COMMENT ON VIEW v_complex_full IS
    'Карточка ЖК с агрегатами по всем источникам. multi-corpus ЖК (один project '
    'в Objective = N obj_id в kn) корректно объединены: kn_flats_n считает все '
    'корпуса. source_links_n включает дубликаты по корпусам, source_kinds_n — '
    'unique источники.';

-- ── 6. ANALYZE для актуализации статистики ──────────────────────────────────
ANALYZE complexes;
ANALYZE complex_sources;
ANALYZE objective_lots;
ANALYZE objective_corpus_room_month;
ANALYZE cad_buildings;
ANALYZE domrf_kn_objects;
ANALYZE domrf_kn_flats;
