"""ПАТ-lookup для site-finder analyze (#1065 / #1067).

Читает pat_subzones и возвращает подзоны ПАТ, пересекающие переданный участок.
Graceful: если таблица ещё не задеплоена или БД недоступна — возвращает пустой список.
Wiring в analyze_parcel — follow-up (не в этом PR).
"""

from __future__ import annotations

import logging
from typing import Any

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

logger = logging.getLogger(__name__)

# ST_Intersects к pat_subzones, GIST idx_pat_subzones_geom.
# Исключаем subzone_no=0 (aggregate_outline) — клиент получает конкретные подзоны 1..6.
_PAT_INTERSECTS_SQL = text(
    """
    SELECT subzone_no, name, restriction, aerodrome
    FROM pat_subzones
    WHERE subzone_no > 0
      AND ST_Intersects(geom, ST_GeomFromText(CAST(:parcel_wkt AS text), 4326))
    ORDER BY subzone_no
    """
)


def parcel_pat_subzones(db: Session, parcel_wkt: str | None) -> list[dict[str, Any]]:
    """Подзоны ПАТ, пересекающие участок.

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

    Returns:
        Список dict [{subzone_no, name, restriction, aerodrome}] отсортированный
        по subzone_no. Пустой список при отсутствии пересечений, ошибке БД
        или недеплоенной таблице.
    """
    if not parcel_wkt:
        return []

    try:
        # SAVEPOINT — db shared с caller (analyze_parcel, shared request-scoped Session).
        # Голый db.rollback() orphan'ит outer SessionTransaction (см. velocity.py:170) —
        # begin_nested откатывает только эту savepoint, не мешая persist_analysis_run
        # и прочим db.execute дальше по /analyze (#2464 cluster A finding 7).
        with db.begin_nested():
            rows = db.execute(_PAT_INTERSECTS_SQL, {"parcel_wkt": parcel_wkt}).mappings().all()
    except (OperationalError, ProgrammingError) as exc:
        # Таблица ещё не задеплоена / структура изменилась — graceful degrade.
        logger.warning("parcel_pat_subzones: pat_subzones недоступна, skip: %s", exc)
        return []

    return [
        {
            "subzone_no": r["subzone_no"],
            "name": r["name"],
            "restriction": r["restriction"],
            "aerodrome": r["aerodrome"],
        }
        for r in rows
    ]


__all__ = ["parcel_pat_subzones"]
