from __future__ import annotations

import re
import unicodedata
from typing import Any

_DIGIT_WORDS = {
    "zero": "0", "um": "1", "uma": "1", "dois": "2", "duas": "2",
    "tres": "3", "quatro": "4", "cinco": "5", "seis": "6", "sete": "7",
    "oito": "8", "nove": "9",
}


def _norm(text: Any) -> str:
    value = unicodedata.normalize("NFKD", str(text or "").casefold())
    value = "".join(ch for ch in value if not unicodedata.combining(ch))
    return re.sub(r"\s+", " ", value).strip()


def extract_requested_line_reference(text: Any) -> dict[str, str] | None:
    """Extrai somente uma referência explícita de linha citada pelo usuário.

    Não transforma a referência em identidade autorizada. Essa decisão pertence à
    política de linha ativa no domínio Contas.
    """
    raw = str(text or "").strip()
    if not raw:
        return None
    norm = _norm(raw)

    # Número completo explicitamente presente no texto (10 a 13 dígitos, com
    # separadores opcionais). Evita capturar valores monetários ou protocolos curtos.
    for match in re.finditer(r"(?<!\d)(?:\+?\d[\s().-]*){10,13}(?!\d)", raw):
        digits = "".join(ch for ch in match.group(0) if ch.isdigit())
        if 10 <= len(digits) <= 13:
            return {"kind": "full", "value": digits, "raw": match.group(0).strip()}

    # Referência por final da linha: "final 4321", "final quatro três dois um",
    # "termina em 4321". Só a referência é extraída; nunca é assumida como MSISDN.
    marker = re.search(r"\b(?:final|termina(?:ndo)?\s+em|terminado\s+em)\b(.{0,45})", norm)
    if marker:
        tail = marker.group(1)
        numeric = re.search(r"\b(\d{4})\b", tail)
        if numeric:
            return {"kind": "suffix", "value": numeric.group(1), "raw": numeric.group(1)}
        tokens = re.findall(r"[a-z]+", tail)
        digits: list[str] = []
        for token in tokens:
            if token in _DIGIT_WORDS:
                digits.append(_DIGIT_WORDS[token])
                if len(digits) == 4:
                    return {"kind": "suffix", "value": "".join(digits), "raw": " ".join(tokens[:4])}
            elif digits:
                break
    return None
