-- 135_newbuilding_listings.sql
-- #975 (SF-v2 #950 EPIC 6 «3-слойный склад», future-ЖК слой карты B4 / GG-форсайт).
--
-- На gendesign НЕТ таблицы под листинги новостроек (house-grain). Источник данных — tradein-БД
-- таблица `houses` (cian/yandex_newbuilding скраперы): building-grain, ~13k строк. `objective_lots`
-- на gendesign — LOT-grain (квартиры/лоты), зерно НЕ совпадает → переиспользовать нельзя.
--
-- РЕШЕНИЕ (objective_lots-reuse vs new, зафиксировано здесь по DoD #975): **новая house-grain
-- таблица**. objective_lots = лот (квартира), houses/newbuilding = дом/ЖК-корпус — разное зерно,
-- разные ключи, разные потребители (lots → market/velocity; newbuilding → future-supply карта).
-- Смешивать = grain-mismatch. Держим раздельно.
--
-- Зеркалит КЛЮЧЕВЫЕ колонки tradein.houses (не все 60 — только нужное SF future-ЖК слою + cross-ref):
--   идентификация/гео, класс/застройщик/рейтинг, очередность (houses_by_turn), кадастр, source-ids.
-- Наполняется cross-load ETL (#976 950-E5) идемпотентным upsert по uq (source, ext_house_id).
--
-- Зерно (grain): одна строка = один дом/корпус новостройки (house-grain). Дедуп-ключ —
--   (source, ext_house_id): ext_house_id — id дома в источнике (cian/yandex). re-load UPSERT-ит
--   (latest wins): crossloaded_at = freshness переноса.
--
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN). Idempotent:
--   CREATE TABLE/INDEX IF NOT EXISTS + guarded DO для UNIQUE (прецедент м.132/133/134).
--   НИКАКИХ строк здесь не вставляется (данные — из ETL #976).

BEGIN;

-- ── 1. Таблица newbuilding_listings ────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS newbuilding_listings (
    id                  BIGSERIAL PRIMARY KEY,
    source              TEXT NOT NULL,            -- 'cian' | 'yandex' | ... (источник дома)
    ext_house_id        TEXT NOT NULL,            -- id дома в источнике (houses.ext_house_id) — дедуп
    -- ── идентификация / гео ──
    url                 TEXT,                     -- ссылка ЖК/дома (cian_zhk_url / listing url)
    slug                TEXT,
    address             TEXT,
    full_address        TEXT,
    lat                 DOUBLE PRECISION,
    lon                 DOUBLE PRECISION,
    geom                geometry(Point, 4326),    -- точка дома (для future-ЖК слоя карты B4)
    -- ── класс / застройщик / характеристики ──
    house_class         TEXT,                     -- класс ЖК (houses.house_class)
    developer_name      TEXT,
    developer_key       TEXT,
    year_built          INTEGER,
    commission_year     INTEGER,                  -- год ввода (план/факт)
    total_floors        INTEGER,
    total_units         INTEGER,
    -- ── рейтинг / очередность / кадастр ──
    rating              NUMERIC,
    reviews_count       INTEGER,
    houses_by_turn      JSONB,                    -- очередность строительства (houses.houses_by_turn)
    cadastral_number    TEXT,
    -- ── cross-ref на источники ──
    cian_internal_house_id BIGINT,
    yandex_jk_id        TEXT,
    raw_payload         JSONB,                    -- полный houses.raw_payload (forward-compat)
    source_last_scraped_at timestamptz,           -- houses.last_scraped_at (свежесть источника)
    crossloaded_at      timestamptz NOT NULL DEFAULT now(),  -- когда ETL #976 перенёс (freshness)
    CONSTRAINT newbuilding_listings_source_chk CHECK (length(source) > 0),
    CONSTRAINT newbuilding_listings_ext_id_chk CHECK (length(ext_house_id) > 0)
);

COMMENT ON TABLE newbuilding_listings IS
    'Листинги новостроек (house-grain, #975 SF-v2 EPIC 6). Зеркало ключевых колонок tradein.houses '
    '(cian/yandex_newbuilding) для future-ЖК слоя карты SF (B4). 1 строка = 1 дом/корпус. UPSERT '
    'cross-load ETL (#976) по uq_newbuilding_listings (source, ext_house_id). НЕ objective_lots '
    '(тот lot-grain) — отдельное зерно. analyze/карта читают будущее предложение через эту таблицу.';
COMMENT ON COLUMN newbuilding_listings.ext_house_id IS 'id дома в источнике (tradein.houses.ext_house_id); дедуп-ключ внутри source';
COMMENT ON COLUMN newbuilding_listings.houses_by_turn IS 'Очередность строительства (JSONB из houses.houses_by_turn) — для future-supply прогноза';

-- ── 2. Дедуп/UPSERT-ключ (source, ext_house_id) ────────────────────────────────
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint WHERE conname = 'uq_newbuilding_listings'
    ) THEN
        ALTER TABLE newbuilding_listings
            ADD CONSTRAINT uq_newbuilding_listings
            UNIQUE (source, ext_house_id);
    END IF;
END
$$;

-- ── 3. Индексы ─────────────────────────────────────────────────────────────────
-- Главный read-path future-ЖК слоя: spatial (карта в bbox / overlap участка).
CREATE INDEX IF NOT EXISTS idx_newbuilding_listings_geom
    ON newbuilding_listings USING GIST (geom);
-- Фильтры аналитики: по застройщику / классу.
CREATE INDEX IF NOT EXISTS idx_newbuilding_listings_developer
    ON newbuilding_listings (developer_key) WHERE developer_key IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_newbuilding_listings_class
    ON newbuilding_listings (house_class) WHERE house_class IS NOT NULL;

COMMIT;
