"""ИРД-overlay lookup для analyze_parcel (#1067 D9).

Читает ``ird_overlays`` (м.132, наполняется harvest-task #1067 B5) и отдаёт ИРД-ограничения,
пересекающие участок: ЗОУИТ / ПЗЗ-границы / ОКН / ООПТ-леса-вода — с reg_numb_border и (когда
резолвлено, #1067 C8/D9-content) читаемым типом/индексом зоны.

Отличие от ``quarter_dump_lookup`` (nspd_quarter_dumps blob-кеш): тот отдаёт per-quarter дамп
ЗОУИТ/zoning из NSPD QuarterDump; ``ird_overlays`` — выделенный per-feature ИРД-store с
reg_numb_border + content-колонками (для геопортал-резолва ВРИ/типа). Комплементарно: канонический
ИРД-слой «волшебной таблицы».

Graceful: если таблица ``ird_overlays`` ещё не задеплоена (pre-migration) или БД-ошибка — возвращает
пустой результат (analyze не падает). Wiring в analyze — flag-gated (D9b).
"""

from __future__ import annotations

import logging
from typing import Any

from sqlalchemy import text
from sqlalchemy.exc import DataError, OperationalError, ProgrammingError
from sqlalchemy.orm import Session

logger = logging.getLogger(__name__)

# Пустой результат — sentinel для analyze try/except (НЕ мутировать).
IRD_EMPTY_RESULT: dict[str, Any] = {"ird_overlaps": [], "ird_by_kind": {}}

# ИРД-overlay по участку: ST_Intersects через GIST idx_ird_overlays_geom. geom уже EPSG:4326
# (harvest стор ST_Transform 3857→4326). Участок передаётся как WKT в 4326. CAST psycopg v3.
# content добавлен для геопортальных ЗОУИТ-слоёв (gknspecial_harvest #1063/#1064/#1065/#1066).
_IRD_OVERLAP_SQL = text(
    """
    SELECT layer_kind, reg_numb_border, category, subcategory,
           zone_index, zone_type_name, content
    FROM ird_overlays
    WHERE ST_Intersects(geom, ST_GeomFromText(CAST(:parcel_wkt AS text), 4326))
    ORDER BY layer_kind, reg_numb_border
    """
)


def parcel_ird_overlaps(db: Session, parcel_wkt: str | None) -> dict[str, Any]:
    """ИРД-ограничения, пересекающие участок.

    Args:
        db: сессия.
        parcel_wkt: геометрия участка в WKT (EPSG:4326). None → пустой результат.

    Returns:
        {'ird_overlaps': [{layer_kind, reg_numb_border, category, subcategory,
        zone_index, zone_type_name, content}], 'ird_by_kind': {layer_kind: count}}.
        content — JSONB-dict с ограничениями/реквизитами зоны (геопортальные слои:
        gknspecial_harvest #1063/#1064/#1065/#1066); None для НСПД-слоёв до резолва D9.
        Пусто при отсутствии участка/таблицы/пересечений (analyze не падает).
    """
    if not parcel_wkt:
        return {"ird_overlaps": [], "ird_by_kind": {}}
    try:
        rows = db.execute(_IRD_OVERLAP_SQL, {"parcel_wkt": parcel_wkt}).mappings().all()
    except (OperationalError, ProgrammingError, DataError) as exc:
        # OperationalError — БД недоступна / connection drop.
        # ProgrammingError — ird_overlays ещё не задеплоена (UndefinedTable, pre-migration).
        # DataError — malformed WKT в ST_GeomFromText (PostGIS ERROR пробрасывает SQLAlchemy
        # как DataError/InternalError). parcel_wkt системно-генерируемый, но при D9b-wiring
        # в analyze graceful-degrade — единственная корректная стратегия (analyze не падает).
        logger.warning("parcel_ird_overlaps: ird_overlays недоступна, skip: %s", exc)
        return {"ird_overlaps": [], "ird_by_kind": {}}

    overlaps: list[dict[str, Any]] = []
    by_kind: dict[str, int] = {}
    for r in rows:
        kind = r["layer_kind"]
        overlaps.append(
            {
                "layer_kind": kind,
                "reg_numb_border": r["reg_numb_border"],
                "category": r["category"],
                "subcategory": r["subcategory"],
                "zone_index": r["zone_index"],
                "zone_type_name": r["zone_type_name"],
                "content": r["content"],
            }
        )
        by_kind[kind] = by_kind.get(kind, 0) + 1
    return {"ird_overlaps": overlaps, "ird_by_kind": by_kind}


__all__ = ["IRD_EMPTY_RESULT", "parcel_ird_overlaps"]
