"""Тесты для _utility_characteristics (#2111 §3 «Сети и точки подключения»).

Покрывает гуманизацию OSM tags инженерных сетей в одну RU-строку для попапов:
напряжение (multi/кВ/В), оператор, диаметр трубопровода, материал, цепи, фильтр
junk-значений. Хелпер module-private — импортируем напрямую.
"""

from __future__ import annotations

from app.services.site_finder.utility_infrastructure_loader import (
    _format_diameter,
    _format_voltage,
    _utility_characteristics,
)

# ── _format_voltage ───────────────────────────────────────────────────────────


def test_format_voltage_kv_single() -> None:
    assert _format_voltage("110000") == "110 кВ"


def test_format_voltage_volts_below_1000() -> None:
    assert _format_voltage("400") == "400 В"


def test_format_voltage_multi_mixed() -> None:
    # «110000;10000» → оба ≥1000 → кВ, join через «/».
    assert _format_voltage("110000;10000") == "110 кВ/10 кВ"


def test_format_voltage_multi_kv_and_volts() -> None:
    assert _format_voltage("10000;400") == "10 кВ/400 В"


def test_format_voltage_fractional_kv() -> None:
    # 400 В → «400 В»; 6600 → «6.6 кВ» (без хвостового нуля).
    assert _format_voltage("6600") == "6.6 кВ"


def test_format_voltage_skips_non_numeric() -> None:
    assert _format_voltage("110000;junk;10000") == "110 кВ/10 кВ"


def test_format_voltage_all_junk_returns_none() -> None:
    assert _format_voltage("abc;;def") is None


# ── _format_diameter ──────────────────────────────────────────────────────────


def test_format_diameter_plain_digits() -> None:
    assert _format_diameter("500") == "⌀ 500 мм"


def test_format_diameter_strips_mm_suffix() -> None:
    assert _format_diameter("500mm") == "⌀ 500 мм"
    assert _format_diameter("300 мм") == "⌀ 300 мм"


def test_format_diameter_no_digits_returns_none() -> None:
    assert _format_diameter("large") is None


def test_format_diameter_multidim_takes_first_run() -> None:
    # «500x300» (прямоугольный короб) → берём первый числовой run, не склеиваем.
    assert _format_diameter("500x300") == "⌀ 500 мм"
    assert _format_diameter("DN500") == "⌀ 500 мм"


# ── _utility_characteristics ──────────────────────────────────────────────────


def test_characteristics_power_voltage_and_operator() -> None:
    out = _utility_characteristics("power", {"voltage": "110000;10000", "operator": "МРСК Урала"})
    assert out == "110 кВ/10 кВ · МРСК Урала"


def test_characteristics_pipeline_diameter_and_material() -> None:
    # material переводится на RU («человеческим языком»): steel → сталь.
    out = _utility_characteristics("gas", {"diameter": "500mm", "material": "steel"})
    assert out == "⌀ 500 мм · сталь"


def test_characteristics_material_ru_and_unknown_passthrough() -> None:
    # known → RU; неизвестный материал остаётся сырым (лучше сырое, чем потерять).
    assert _utility_characteristics("power", {"material": "metal"}) == "металл"
    assert _utility_characteristics("power", {"material": "Concrete"}) == "бетон"
    assert _utility_characteristics("gas", {"material": "unobtanium"}) == "unobtanium"


def test_characteristics_single_voltage_volts() -> None:
    assert _utility_characteristics("power", {"voltage": "400"}) == "400 В"


def test_characteristics_circuits_when_numeric() -> None:
    out = _utility_characteristics("power", {"voltage": "10000", "circuits": "2"})
    assert out == "10 кВ · 2 цеп."


def test_characteristics_cables_fallback_for_circuits() -> None:
    out = _utility_characteristics("power", {"cables": "3"})
    assert out == "3 цеп."


def test_characteristics_non_numeric_circuits_skipped() -> None:
    # circuits=«single» не число → пропускаем; остаётся только напряжение.
    assert _utility_characteristics("power", {"voltage": "400", "circuits": "single"}) == "400 В"


def test_characteristics_junk_voltage_filtered() -> None:
    # voltage=yes (junk) → пропуск; ничего больше → None.
    assert _utility_characteristics("power", {"voltage": "yes"}) is None


def test_characteristics_filters_empty_and_no() -> None:
    assert _utility_characteristics("water", {"operator": "  ", "material": "no"}) is None


def test_characteristics_none_tags_returns_none() -> None:
    assert _utility_characteristics("power", None) is None


def test_characteristics_empty_dict_returns_none() -> None:
    assert _utility_characteristics("power", {}) is None


def test_characteristics_not_a_dict_returns_none() -> None:
    # Защитный guard: tags из БД мог прийти не dict (broken JSONB) → None, не падаем.
    assert _utility_characteristics("power", "not-a-dict") is None  # type: ignore[arg-type]


def test_characteristics_full_order() -> None:
    # Порядок частей: напряжение · оператор · диаметр · материал · цепи.
    out = _utility_characteristics(
        "power",
        {
            "voltage": "10000",
            "operator": "Облкоммунэнерго",
            "diameter": "200",
            "material": "медь",
            "circuits": "2",
        },
    )
    assert out == "10 кВ · Облкоммунэнерго · ⌀ 200 мм · медь · 2 цеп."


# ── теплотрассы (kind=heat, #2119) ────────────────────────────────────────────


def test_characteristics_heat_hot_water_substance() -> None:
    # Теплоноситель — первым: «горячая вода», затем диаметр.
    out = _utility_characteristics("heat", {"substance": "hot_water", "diameter": "200"})
    assert out == "горячая вода · ⌀ 200 мм"


def test_characteristics_heat_steam_substance() -> None:
    out = _utility_characteristics("heat", {"substance": "steam"})
    assert out == "пар"


def test_characteristics_heat_generic_substance_no_label() -> None:
    # substance=heat (обобщённо) не уточняем — фронт и так покажет «Теплотрасса».
    # Диаметр остаётся, теплоноситель-подписи нет.
    assert _utility_characteristics("heat", {"substance": "heat", "diameter": "300"}) == "⌀ 300 мм"
    # heat без каких-либо характеристик → None (одного вида довольно для попапа).
    assert _utility_characteristics("heat", {"substance": "heat"}) is None


def test_characteristics_heat_substance_only_on_heat_kind() -> None:
    # substance-подпись только для kind=heat; для gas/water теплоноситель не лезет.
    assert _utility_characteristics("gas", {"substance": "hot_water"}) is None
