"""Тесты parcel_ird_overlaps (#1067 D9) — ИРД-overlay lookup для analyze."""

from __future__ import annotations

from typing import Any

import pytest
from sqlalchemy.exc import DataError, OperationalError, ProgrammingError

from app.services.site_finder.ird_overlay_lookup import parcel_ird_overlaps


class _Result:
    def __init__(self, rows: list[dict[str, Any]]) -> None:
        self._rows = rows

    def mappings(self) -> _Result:
        return self

    def all(self) -> list[dict[str, Any]]:
        return self._rows


class _FakeDB:
    def __init__(
        self, rows: list[dict[str, Any]] | None = None, raise_exc: Exception | None = None
    ) -> None:
        self._rows = rows or []
        self._raise = raise_exc

    def execute(self, sql: Any, params: dict[str, Any] | None = None) -> _Result:
        if self._raise is not None:
            raise self._raise
        return _Result(self._rows)


_WKT = "POLYGON((60.5 56.8, 60.6 56.8, 60.6 56.9, 60.5 56.9, 60.5 56.8))"


def test_groups_overlaps_by_kind() -> None:
    rows = [
        {
            "layer_kind": "zouit_okn",
            "reg_numb_border": "66:41-6.41",
            "category": 36940,
            "subcategory": 20,
            "zone_index": None,
            "zone_type_name": None,
            "content": None,
        },
        {
            "layer_kind": "zouit_okn",
            "reg_numb_border": "66:41-6.42",
            "category": 36940,
            "subcategory": 20,
            "zone_index": None,
            "zone_type_name": None,
            "content": None,
        },
        {
            "layer_kind": "territorial_zones",
            "reg_numb_border": "66:41-7.10",
            "category": 472819,
            "subcategory": 1,
            "zone_index": "Ц-1",
            "zone_type_name": None,
            "content": None,
        },
    ]
    res = parcel_ird_overlaps(_FakeDB(rows), _WKT)
    assert len(res["ird_overlaps"]) == 3
    assert res["ird_by_kind"] == {"zouit_okn": 2, "territorial_zones": 1}
    tz = next(o for o in res["ird_overlaps"] if o["layer_kind"] == "territorial_zones")
    assert tz["reg_numb_border"] == "66:41-7.10"
    assert tz["zone_index"] == "Ц-1"


def test_content_passthrough() -> None:
    """content из gknspecial_harvest пробрасывается в каждый overlap-dict."""
    content_val = {"restrictions": "запрещена жилая застройка", "zone_state": "Действующий"}
    rows = [
        {
            "layer_kind": "water_protection",
            "reg_numb_border": "66:41-6.4125",
            "category": None,
            "subcategory": None,
            "zone_index": None,
            "zone_type_name": "Водоохранная зона р. Исеть",
            "content": content_val,
        },
    ]
    res = parcel_ird_overlaps(_FakeDB(rows), _WKT)
    assert res["ird_overlaps"][0]["content"] == content_val


def test_empty_when_no_wkt() -> None:
    res = parcel_ird_overlaps(_FakeDB([{"layer_kind": "x"}]), None)
    assert res == {"ird_overlaps": [], "ird_by_kind": {}}


def test_empty_when_no_overlap() -> None:
    res = parcel_ird_overlaps(_FakeDB([]), _WKT)
    assert res == {"ird_overlaps": [], "ird_by_kind": {}}


@pytest.mark.parametrize(
    ("exc", "case"),
    [
        (
            OperationalError("stmt", {}, Exception("no such table")),
            "operational-error: connection drop / БД недоступна",
        ),
        (
            ProgrammingError("stmt", {}, Exception("relation \"ird_overlays\" does not exist")),
            "programming-error: UndefinedTable — pre-migration / D9b не задеплоен",
        ),
        (
            DataError("stmt", {}, Exception("parse error - invalid geometry")),
            "data-error: malformed WKT → PostGIS ST_GeomFromText ERROR",
        ),
    ],
)
def test_graceful_when_db_fails(exc: Exception, case: str) -> None:
    """ird_overlays недоступна / malformed WKT → пусто, analyze не падает.

    Покрывает:
    - OperationalError — БД недоступна.
    - ProgrammingError — таблица ещё не задеплоена (реальный класс при UndefinedTable).
    - DataError — malformed parcel_wkt (PostGIS ST_GeomFromText бросает ERROR,
      SQLAlchemy конвертит в DataError).
    """
    db = _FakeDB(raise_exc=exc)
    res = parcel_ird_overlaps(db, _WKT)
    assert res == {"ird_overlaps": [], "ird_by_kind": {}}, case
