"""Тесты контракта suggest→ФИАС (feat/tradein-fias-tier-matching).

Покрывают:
  1. geocoder._dadata_suggest — fias_id прокидывается ТОЛЬКО у house-level
     кандидата (DaData kind='house' ⇔ fias_level 8/9); у street/city/plot None.
  2. SuggestItem — сериализует fias_id (house-тир) и None у не-DaData тиров.
  3. TradeInEstimateInput — принимает target_fias_id и дефолтит None при отсутствии.
"""

import os

# Settings требует DATABASE_URL на импорте — ставим dummy DSN до app-импортов.
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test")

from unittest.mock import AsyncMock, patch

from app.api.v1.geocode import SuggestItem
from app.schemas.trade_in import TradeInEstimateInput
from app.services.dadata import DadataSuggestion
from app.services.geocoder import GeocodeSuggestion, _dadata_suggest


def _sugg(kind: str, fias_id: str | None) -> DadataSuggestion:
    return DadataSuggestion(
        value=f"тест {kind}",
        unrestricted_value=f"г Екатеринбург, тест {kind}",
        lat=56.84,
        lon=60.60,
        fias_id=fias_id,
        house="1" if kind == "house" else None,
        street="Тестовая",
        city="Екатеринбург",
        kind=kind,
    )


# ── 1. _dadata_suggest: fias_id только у house-тира ──────────────────────────
async def test_dadata_suggest_fias_only_for_house_kind():
    raw = [
        _sugg("house", "0a1b2c3d-0000-4000-8000-00000000aaaa"),
        _sugg("street", "0a1b2c3d-0000-4000-8000-00000000bbbb"),
        _sugg("city", "0a1b2c3d-0000-4000-8000-00000000cccc"),
        _sugg("plot", "0a1b2c3d-0000-4000-8000-00000000dddd"),
    ]
    with patch(
        "app.services.geocoder.dadata.suggest_addresses",
        new=AsyncMock(return_value=raw),
    ):
        out = await _dadata_suggest("тест", limit=8)

    assert len(out) == 4
    house = next(s for s in out if s.kind == "house")
    assert house.fias_id == "0a1b2c3d-0000-4000-8000-00000000aaaa"
    # У всех НЕ-house тиров fias_id обнулён, даже если DaData его прислал.
    for s in out:
        if s.kind != "house":
            assert s.fias_id is None


async def test_dadata_suggest_house_without_fias_stays_none():
    """house-кандидат без fias у DaData → fias_id None (не падаем)."""
    with patch(
        "app.services.geocoder.dadata.suggest_addresses",
        new=AsyncMock(return_value=[_sugg("house", None)]),
    ):
        out = await _dadata_suggest("тест", limit=8)
    assert len(out) == 1
    assert out[0].fias_id is None


# ── 2. SuggestItem сериализация ──────────────────────────────────────────────
def test_suggest_item_serializes_fias_id():
    item = SuggestItem(
        label="ул Малышева, д 30",
        full_address="г Екатеринбург, ул Малышева, д 30",
        lat=56.84,
        lon=60.60,
        kind="house",
        fias_id="0a1b2c3d-0000-4000-8000-00000000aaaa",
    )
    dumped = item.model_dump()
    assert dumped["fias_id"] == "0a1b2c3d-0000-4000-8000-00000000aaaa"


def test_suggest_item_fias_id_defaults_none_for_non_dadata_tier():
    """Не-DaData тир (Yandex/Nominatim/cadastral) не передаёт fias_id → None."""
    gs = GeocodeSuggestion(
        label="Малышева 30",
        full_address="г Екатеринбург, ул Малышева, д 30",
        lat=56.84,
        lon=60.60,
        kind="house",
    )
    assert gs.fias_id is None
    item = SuggestItem(
        label=gs.label,
        full_address=gs.full_address,
        lat=gs.lat,
        lon=gs.lon,
        kind=gs.kind,
        fias_id=gs.fias_id,
    )
    assert item.model_dump()["fias_id"] is None


# ── 3. TradeInEstimateInput.target_fias_id ───────────────────────────────────
def test_estimate_input_accepts_target_fias_id():
    payload = TradeInEstimateInput(
        address="ул Малышева 30, Екатеринбург",
        area_m2=50.0,
        rooms=2,
        target_fias_id="0a1b2c3d-0000-4000-8000-00000000aaaa",
    )
    assert payload.target_fias_id == "0a1b2c3d-0000-4000-8000-00000000aaaa"


def test_estimate_input_target_fias_id_defaults_none():
    payload = TradeInEstimateInput(
        address="ул Малышева 30, Екатеринбург",
        area_m2=50.0,
        rooms=2,
    )
    assert payload.target_fias_id is None
