"""Гуманизация «сетевых охранных зон» ЗОУИТ для §3 ПТИЦА (#2119 C3).

Позитив-разрез охранных зон инженерных сетей: рядом с участком физически ПРОХОДИТ
сеть (охранная зона = коридор сети) → «теплотрасса в 24 м — врезка дешёвая». Pure /
без БД: на вход ``type_zone`` + ``name_by_doc`` (детальные имена из cad_zouit), на
выход — уточнённый ``net_kind`` + человекочитаемый ``human_label`` для финдиректора.

Зачем отдельно от ``network_obremenenie.classify_network_zone``:
  - ``classify_network_zone`` смотрит ТОЛЬКО на ``type_zone`` (грубый вид: thermal /
    general / …). На проде (2026-07-03) большинство «Охранная зона инженерных
    коммуникаций» (``general``) — по ``name_by_doc`` РЕАЛЬНО теплосети/газопроводы
    («Трубопровод (тепловые сети) с кадастровым номером 66:41:…», «Газопровод
    низкого давления…»). Оставить их ``general`` = потерять решающий тепло-сигнал.
  - Поэтому здесь ``refine_net_kind`` дочищает ``general`` по ``name_by_doc``, а
    ``human_label`` вытаскивает кад.номер трубопровода / напряжение ВЛ / номер ТП
    regex-ами. Классификатор type_zone НЕ дублируем — переиспользуем как базу.
"""

from __future__ import annotations

import re

from app.services.site_finder.network_obremenenie import NetworkKind, classify_network_zone

# Кад.номер РФ: 2:2:до7цифр:до-длинная последняя секция (напр. 66:41:0108079:76).
# Последняя секция бывает с ведущими нулями («0036») — берём как есть, не нормализуем.
_CAD_NUM_RE = re.compile(r"\b\d{2}:\d{2}:\d{6,7}:\d+\b")

# «ВЛ 0,4 кВ» / «КЛ 10кВ» / «ВЛИ-0,4 кВ» — тип линии + напряжение. Запятая-десятичный
# разделитель (0,4) и точка (0.4) оба валидны; пробел перед «кВ» опционален.
_VL_KV_RE = re.compile(
    r"\b(ВЛИ|ВЛЗ|ВЛ|КЛ|КВЛ)\b[\s-]*?(\d+(?:[.,]\d+)?)\s*кВ",
    re.IGNORECASE,
)

# Номер ТП/РП/КТП: «ТП 3164», «ТП 32505», «ТП 3736-3747», «КТП №589». Берём первый
# «якорный» ТП (источник питания ввода). Номер — цифры, опционально с дефисом-диапазоном.
_TP_RE = re.compile(
    r"\b(ТП|РП|КТП|КТПН|БКТП|РТП)\b\s*(?:п/?№|№|N)?\s*(\d+(?:-\d+)?)",
    re.IGNORECASE,
)

# Маркеры «на самом деле тепло» в name_by_doc для general-зон (инженерные коммуникации).
_THERMAL_NEEDLES: tuple[str, ...] = (
    "теплоснабж",
    "тепловая сеть",
    "тепловые сети",
    "тепловых сетей",
    "теплосет",
    "теплотрасс",
)
# Маркеры «на самом деле газ» в name_by_doc для general-зон.
_GAS_NEEDLES: tuple[str, ...] = (
    "газопров",
    "газораспредел",
    "газоснаб",
    "догазифик",
)
# Маркеры электро (ВЛ/КЛ/электросет/подстанция) в name_by_doc для general-зон.
# «трансформаторная подстанция» / «распределительный пункт» — объект электросети без
# явного «ВЛ N кВ» (прод-кейс 66:41:0404019:333). ТП здесь = трансформаторная (электро),
# не путать с тепловой ТК (тепловая камера) — та ловится _THERMAL_NEEDLES раньше.
_ELECTRICITY_NEEDLES: tuple[str, ...] = (
    "электросет",
    "электроснабж",
    "электросетевого",
    "кабельн",
    "трансформаторн",
    "распределительн",
)


def refine_net_kind(type_zone: str | None, name_by_doc: str | None) -> NetworkKind | None:
    """Уточнить вид сети: база по ``type_zone``, дочистка ``general`` по ``name_by_doc``.

    Возвращает ``None``, если зона вообще не сетевая (как ``classify_network_zone``).
    Для ``general`` («инженерные коммуникации») пытается распознать реальный вид по
    детальному имени: тепло → thermal, газ → gas, электро → electricity. Если вид не
    распознан — остаётся ``general`` («вид не уточнён»).

    Специфичные type_zone (thermal / electricity / gas / …) НЕ переопределяем именем —
    для них type_zone уже точный, а name_by_doc лишь обогащает подпись.
    """
    base = classify_network_zone(type_zone)
    if base != "general":
        return base
    name = (name_by_doc or "").lower()
    if any(n in name for n in _THERMAL_NEEDLES):
        return "thermal"
    if any(n in name for n in _GAS_NEEDLES):
        return "gas"
    # ВЛ/КЛ N кВ в имени → электро (regex поймает даже без слова «электросеть»).
    if any(n in name for n in _ELECTRICITY_NEEDLES) or _VL_KV_RE.search(name_by_doc or ""):
        return "electricity"
    return "general"


def _fmt_voltage(raw: str) -> str:
    """«0,4» / «0.4» / «10» → нормализованная строка напряжения («0,4», «10»)."""
    return raw.replace(".", ",")


def _is_last_mile_voltage(raw: str) -> bool:
    """Напряжение ≤1 кВ (0,4 кВ и т.п.) — last-mile ввод, не магистраль."""
    try:
        return float(raw.replace(",", ".")) <= 1.0
    except ValueError:
        return False


def human_label(net_kind: NetworkKind | None, name_by_doc: str | None) -> str:
    """Человекочитаемая подпись сетевой зоны для §3 (финдиректор-facing).

    thermal      → «Тепловая сеть (по охранной зоне)» + кад.номер трубопровода, если есть.
    electricity  → «Ввод N кВ от ТП M (по охранной зоне)» (regex ВЛ/КЛ + ТП);
                   напряжение ≤1 кВ подаём как «(ввод 0,4 кВ, last-mile)» — второстепенно.
    gas/pipeline → «Трубопровод (газо-/нефтепровод) по охранной зоне».
    general      → «Инженерные коммуникации (вид не уточнён)».
    None         → «Охранная зона» (fallback, не должно доходить для сетевых).
    """
    name = name_by_doc or ""

    if net_kind == "thermal":
        cad = _CAD_NUM_RE.search(name)
        base = "Тепловая сеть (по охранной зоне)"
        if cad:
            return f"{base}, кад. № {cad.group(0)}"
        return base

    if net_kind == "electricity":
        vl = _VL_KV_RE.search(name)
        tp = _TP_RE.search(name)
        if vl:
            voltage = _fmt_voltage(vl.group(2))
            last_mile = _is_last_mile_voltage(vl.group(2))
            if tp:
                tp_num = tp.group(2)
                if last_mile:
                    # ≤1 кВ — last-mile, подаём как второстепенный факт (уточнение в скобках).
                    return f"Ввод от ТП {tp_num} (по охранной зоне, {voltage} кВ — last-mile)"
                return f"Ввод {voltage} кВ от ТП {tp_num} (по охранной зоне)"
            if last_mile:
                return f"Электроввод {voltage} кВ — last-mile (по охранной зоне)"
            return f"Ввод {voltage} кВ (по охранной зоне)"
        if tp:
            return f"Электросеть от ТП {tp.group(2)} (по охранной зоне)"
        return "Объект электросетевого хозяйства (по охранной зоне)"

    if net_kind in ("gas", "pipeline"):
        cad = _CAD_NUM_RE.search(name)
        base = "Трубопровод (газо-/нефтепровод) по охранной зоне"
        if cad:
            return f"{base}, кад. № {cad.group(0)}"
        return base

    if net_kind == "water":
        return "Сеть водоснабжения/водоотведения (по охранной зоне)"

    if net_kind == "communication":
        return "Линия связи (по охранной зоне)"

    if net_kind == "general":
        return "Инженерные коммуникации (вид не уточнён)"

    return "Охранная зона"


__all__ = ["human_label", "refine_net_kind"]
