-- 136_land_reservation.sql
-- #1091 / #1062 (ИРД-5, «GG-форсайт» #1067) — хранилище ЗУ под изъятие/резервирование.
--
-- Геометрии зон изъятия/резервирования НЕТ ни в одном spatial-источнике (НСПД/геопортал/ГИСОГД
-- проверены пусто, vault research 2026-06). Перечень ЗУ существует ТОЛЬКО текстом в постановлениях
-- (PDF, pravo.gov66.ru / ПАГЕ). Геометрию получаем join'ом кад-номера к cad_parcels.geom — это
-- покрывает read-side analyse без хранения геометрии здесь.
--
-- Что/зачем: per-parcel флаг «в действующем постановлении №X об изъятии/резервировании» + ссылка
-- на документ. Парсер текста постановлений (page_reservation_parser.py) извлекает кад-номера и
-- метаданные акта; ingest-task пишет сюда; reservation_lookup.py читает для analyze.
--
-- Grain: одна строка = один кад-номер в одном акте (cad_num, act_number — дедуп-ключ).
-- Источник: pravo.gov66.ru PDF-постановления (seed: 509-ПП Правительства СО, ул. Татищева ЕКБ).
--
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN). Idempotent
-- (ре-apply дважды чисто): CREATE TABLE/INDEX IF NOT EXISTS + guarded DO-блок для UNIQUE
-- (constraint нельзя добавить дважды → guard по pg_constraint, прецедент м.132).
-- НИКАКИХ строк здесь не вставляется (данные приходят из reservation_ingest task).

BEGIN;

-- ── 1. Таблица land_reservation ───────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS land_reservation (
    id               BIGSERIAL PRIMARY KEY,
    cad_num          TEXT NOT NULL,                    -- кадастровый номер ЗУ (66:41:XXXXXXX:NN)
    reservation_kind TEXT NOT NULL,                    -- 'изъятие' | 'резервирование'
    basis_act        TEXT NOT NULL,                    -- «Постановление Правительства СО № 509-ПП»
    act_number       TEXT,                             -- «509-ПП» (None если не распарсилось)
    act_date         DATE,                             -- дата акта (NULL если не распарсилось)
    purpose          TEXT,                             -- цель (реконструкция ул. Татищева, ...)
    doc_url          TEXT,                             -- ссылка на PDF/страницу
    source           TEXT NOT NULL DEFAULT 'page_pdf', -- источник: page_pdf | ...
    is_active        BOOLEAN NOT NULL DEFAULT true,    -- актуальное постановление
    raw_excerpt      TEXT,                             -- ±120 символов вокруг первого кад-номера
    fetched_at       timestamptz NOT NULL DEFAULT now()
);

COMMENT ON TABLE land_reservation IS
    'ЗУ под изъятие/резервирование (#1091/#1062, GG-форсайт #1067). 1 строка = 1 кад-номер '
    'в 1 постановлении. Геометрия не хранится — join к cad_parcels.geom на read-side. '
    'Парсер page_reservation_parser.py извлекает кад-номера из PDF-постановлений; '
    'reservation_lookup.py читает для analyze.';

COMMENT ON COLUMN land_reservation.cad_num IS 'Кадастровый номер ЗУ вида 66:41:XXXXXXX:NN';
COMMENT ON COLUMN land_reservation.reservation_kind IS 'изъятие | резервирование';
COMMENT ON COLUMN land_reservation.basis_act IS 'Читаемое описание акта-основания';
COMMENT ON COLUMN land_reservation.act_number IS 'Номер постановления (509-ПП, NNN-ПА и т.п.)';
COMMENT ON COLUMN land_reservation.raw_excerpt IS '±120 симв. вокруг первого кад-номера; debug/верификация';

-- ── 2. Дедуп/UPSERT-ключ (cad_num, act_number) ───────────────────────────────
-- Guard по pg_constraint → idempotent re-apply (constraint нельзя добавить дважды).
-- Прецедент: м.132 (uq_ird_overlays_feature).
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint WHERE conname = 'uq_land_reservation_cad_act'
    ) THEN
        ALTER TABLE land_reservation
            ADD CONSTRAINT uq_land_reservation_cad_act
            UNIQUE (cad_num, act_number);
    END IF;
END
$$;

-- ── 3. Индексы ────────────────────────────────────────────────────────────────
-- Основной read-path: lookup по кад-номеру (reservation_lookup.py → analyze).
CREATE INDEX IF NOT EXISTS idx_land_reservation_cad_num
    ON land_reservation (cad_num);

-- Фильтр активных постановлений (is_active=true — рабочий подмножество).
CREATE INDEX IF NOT EXISTS idx_land_reservation_active
    ON land_reservation (cad_num) WHERE is_active;

-- Lookup по номеру акта (cross-ref / ручные проверки).
CREATE INDEX IF NOT EXISTS idx_land_reservation_act_number
    ON land_reservation (act_number) WHERE act_number IS NOT NULL;

COMMIT;
