-- 140_ekb_krt_geometry.sql
-- #1130 (Site Finder v2 / GG-форсайт) — КРТ-геометрии геопортала ЕКБ в БД.
--
-- Слой portal_geo_oks_krt («Здания в границах КРТ») → ~48 WFS-фич с Polygon-геометриями.
-- Harvest-воркер (krt_geometry_sync.py) раз в неделю UPSERT-ит сюда все фичи одним bbox-запросом.
-- analyze читает _krt_at через ST_Intersects(geom, point) — без живого WFS-вызова в hot-пути.
--
-- UNIQUE-ключ: feature_id — стабильный строковый id WFS-фичи GeoServer
-- (вида «portal_geo_oks_krt.NNN»; trailing-int выделяется для numeric lookup).
-- Выбор обоснован: GeoServer feature_id стабилен между запросами одного слоя (это PK GeoServer),
-- не зависит от изменяемых атрибутов (num_oks_krt/status/area) и присутствует у каждой фичи.
-- Альтернатива (num_oks_krt+MD5(geom)) нестабильна при минимальных правках геометрии → излишний
-- DELETE+INSERT вместо UPDATE; feature_id надёжнее.
--
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN).
-- Idempotent (CREATE TABLE/INDEX IF NOT EXISTS + guarded DO-блок для UNIQUE).
-- Зеркалит pattern м.132 (ird_overlays) и м.137 (ekb_krt_sites).
-- Без INSERT — данные приходят из Celery-воркера krt_geometry_sync.

BEGIN;

-- ── 1. Таблица ekb_krt_geometry ──────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS ekb_krt_geometry (
    id           BIGSERIAL PRIMARY KEY,
    feature_id   TEXT NOT NULL,               -- GeoServer WFS feature id («portal_geo_oks_krt.7»)
    num_oks_krt  INTEGER,                     -- порядковый номер КРТ-площадки
    full_name    TEXT,                        -- полное наименование (из свойств слоя)
    status       TEXT,                        -- статус КРТ («В работе», «Завершён» и т.п.)
    geom         geometry(Geometry, 4326) NOT NULL,  -- полигон КРТ-территории, EPSG:4326
    area         NUMERIC,                    -- площадь из свойств (га или кв. м — как в слое)
    raw_props    JSONB,                       -- полный properties-объект WFS-фичи (forward-compat)
    fetched_at   TIMESTAMPTZ NOT NULL DEFAULT now()
);

COMMENT ON TABLE ekb_krt_geometry IS
    'Геометрия КРТ-территорий ЕКБ (#1130, GG-форсайт). '
    'Источник: WFS-слой portal_geo_oks_krt геопортала ЕКБ (~48 фич). '
    'Harvest — Celery krt_geometry_sync раз в неделю (bbox ЕКБ-агломерации). '
    'analyze._krt_at читает ST_Intersects(geom, point) вместо живого WFS-вызова.';

COMMENT ON COLUMN ekb_krt_geometry.feature_id IS
    'Стабильный GeoServer WFS feature id слоя («portal_geo_oks_krt.7»). UNIQUE ON CONFLICT target.';
COMMENT ON COLUMN ekb_krt_geometry.num_oks_krt IS
    'Порядковый номер КРТ-площадки из свойств WFS-фичи (num_oks_krt). NULL если не задан.';
COMMENT ON COLUMN ekb_krt_geometry.geom IS
    'Polygon/MultiPolygon КРТ-территории в EPSG:4326 (WFS GeoServer отдаёт в 4326 напрямую).';

-- ── 2. UNIQUE по feature_id (ON CONFLICT target для UPSERT) ─────────────────
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint WHERE conname = 'uq_ekb_krt_geometry_feature_id'
    ) THEN
        ALTER TABLE ekb_krt_geometry
            ADD CONSTRAINT uq_ekb_krt_geometry_feature_id
            UNIQUE (feature_id);
    END IF;
END
$$;

-- ── 3. Индексы ───────────────────────────────────────────────────────────────
-- ГЛАВНЫЙ read-path: ST_Intersects(geom, point) из _krt_at в analyze hot-пути.
CREATE INDEX IF NOT EXISTS idx_ekb_krt_geometry_geom
    ON ekb_krt_geometry USING GIST (geom);

-- Lookup по порядковому номеру (JOIN к ekb_krt_sites по num_oks_krt).
CREATE INDEX IF NOT EXISTS idx_ekb_krt_geometry_num_oks_krt
    ON ekb_krt_geometry (num_oks_krt)
    WHERE num_oks_krt IS NOT NULL;

-- Мониторинг свежести данных.
CREATE INDEX IF NOT EXISTS idx_ekb_krt_geometry_fetched_at
    ON ekb_krt_geometry (fetched_at DESC);

COMMIT;
