"""Тесты РИАСУРТ Свердл client (#108) — get_riasurt_sverdl_in_bbox + topic-классификация.

Сеть не дёргается: мокаем get_features_in_bbox_grid на инстансе NSPDClient. Проверяем
mapping layerId → features, классификацию topic, graceful-skip упавшего слоя.
"""

from __future__ import annotations

from typing import Any

import pytest

from app.services.scrapers.nspd_client import (
    RIASURT_SVERDL_LAYERS,
    NSPDClient,
    NSPDFeature,
    NspdLiteWafError,
    riasurt_layer_topic,
)


def test_riasurt_catalog_has_14_key_layers() -> None:
    """Каталог содержит ровно 14 ключевых layerId из issue #108."""
    expected = {
        845274,
        846381,
        844759,
        844774,
        845298,
        846365,
        846369,
        845392,
        846373,
        845425,
        846378,
        844795,
        844478,
        846379,
    }
    assert set(RIASURT_SVERDL_LAYERS) == expected
    assert len(RIASURT_SVERDL_LAYERS) == 14


def test_riasurt_layer_topic_known() -> None:
    """topic корректно резолвится по layerId."""
    assert riasurt_layer_topic(845274) == "territorial_zone"
    assert riasurt_layer_topic(846381) == "functional_zone"
    assert riasurt_layer_topic(844759) == "red_lines"
    assert riasurt_layer_topic(846365) == "szz"
    assert riasurt_layer_topic(845392) == "szo"
    assert riasurt_layer_topic(845425) == "flood_zone"
    assert riasurt_layer_topic(844478) == "krt"
    assert riasurt_layer_topic(846379) == "oez"


def test_riasurt_layer_topic_unknown_is_other() -> None:
    """Неизвестный layerId → 'other' (graceful)."""
    assert riasurt_layer_topic(999999) == "other"


def _feat(layer_id: int) -> NSPDFeature:
    return NSPDFeature.from_raw(
        {
            "id": str(layer_id),
            "geometry": {"type": "Polygon", "coordinates": [[[1, 1], [2, 1], [2, 2], [1, 1]]]},
            "properties": {"label": f"zone-{layer_id}"},
        }
    )


def test_get_riasurt_sverdl_in_bbox_maps_layers(monkeypatch: pytest.MonkeyPatch) -> None:
    """Каждый запрошенный layerId → его features; форма dict[int, list]."""
    client = NSPDClient()
    calls: list[int] = []

    def fake_grid(layer_id: int, bbox: Any, **kw: Any) -> list[NSPDFeature]:
        calls.append(layer_id)
        return [_feat(layer_id)]

    monkeypatch.setattr(client, "get_features_in_bbox_grid", fake_grid)

    bbox = (6770000.0, 7710000.0, 6782000.0, 7722000.0)
    result = client.get_riasurt_sverdl_in_bbox(bbox, [845274, 844478])

    assert set(result) == {845274, 844478}
    assert len(result[845274]) == 1
    assert result[845274][0].feature_id == "845274"
    assert calls == [845274, 844478]


def test_get_riasurt_sverdl_in_bbox_default_all_14(monkeypatch: pytest.MonkeyPatch) -> None:
    """layers=None → все 14 ключевых слоёв."""
    client = NSPDClient()
    monkeypatch.setattr(client, "get_features_in_bbox_grid", lambda lid, bbox, **kw: [_feat(lid)])
    result = client.get_riasurt_sverdl_in_bbox((0.0, 0.0, 100.0, 100.0))
    assert set(result) == set(RIASURT_SVERDL_LAYERS)


def test_get_riasurt_sverdl_in_bbox_skips_failed_layer(monkeypatch: pytest.MonkeyPatch) -> None:
    """Упавший слой (WAF) → его ключ = [], остальные продолжают."""
    client = NSPDClient()

    def fake_grid(layer_id: int, bbox: Any, **kw: Any) -> list[NSPDFeature]:
        if layer_id == 846365:
            raise NspdLiteWafError("HTTP 429")
        return [_feat(layer_id)]

    monkeypatch.setattr(client, "get_features_in_bbox_grid", fake_grid)
    result = client.get_riasurt_sverdl_in_bbox((0.0, 0.0, 100.0, 100.0), [845274, 846365, 844478])

    assert result[846365] == []
    assert len(result[845274]) == 1
    assert len(result[844478]) == 1
