from __future__ import annotations

from dataclasses import dataclass
from typing import Any

POLICY_NAME = "authorized_related_lines"
POLICY_DESCRIPTION = (
    "Permite outra linha somente quando ela é resolvida univocamente entre "
    "linhas devolvidas pelo serviço autorizado consultar_linhas_autorizadas."
)


def _digits(value: Any) -> str:
    return "".join(ch for ch in str(value or "") if ch.isdigit())


def _looks_like_msisdn(value: Any) -> bool:
    size = len(_digits(value))
    return 10 <= size <= 13


def _authorized_lines(args: dict[str, Any], authenticated: str) -> list[str]:
    """Retorna apenas linhas autorizadas pela integração explícita.

    Não colhe MSISDNs de billing/invoice/LLM. A presença de uma linha em uma
    fatura não equivale, por si só, a autorização operacional.
    """
    found: set[str] = {authenticated} if authenticated else set()
    evidence = args.get("authorized_lines_evidence")
    if not isinstance(evidence, dict) or evidence.get("success") is not True:
        return sorted(found)

    for value in evidence.get("authorized_msisdns") or []:
        candidate = _digits(value)
        if _looks_like_msisdn(candidate):
            found.add(candidate)

    for item in evidence.get("authorized_lines") or []:
        if not isinstance(item, dict):
            continue
        if item.get("authorized", True) is not True:
            continue
        if str(item.get("status") or "ACTIVE").upper() != "ACTIVE":
            continue
        candidate = _digits(item.get("msisdn"))
        if _looks_like_msisdn(candidate):
            found.add(candidate)
    return sorted(found)


@dataclass(frozen=True)
class LinePolicyDecision:
    allowed: bool
    effective_msisdn: str
    reason: str = ""
    user_message: str = ""
    requested_reference: dict[str, Any] | None = None
    authorized_lines: tuple[str, ...] = ()


def apply_line_policy(tool_name: str, args: dict[str, Any]) -> LinePolicyDecision:
    authenticated = _digits(args.get("msisdn"))
    reference = args.get("requested_line_reference")
    authorized = _authorized_lines(args, authenticated)
    if not authenticated or not isinstance(reference, dict):
        return LinePolicyDecision(True, authenticated or str(args.get("msisdn") or ""), authorized_lines=tuple(authorized))

    kind = str(reference.get("kind") or "").strip().lower()
    requested = _digits(reference.get("value"))
    if kind == "full" and requested:
        matches = [line for line in authorized if line == requested or line.endswith(requested) or requested.endswith(line)]
    elif kind == "suffix" and requested:
        matches = [line for line in authorized if line.endswith(requested)]
    else:
        return LinePolicyDecision(True, authenticated, requested_reference=reference, authorized_lines=tuple(authorized))

    unique = sorted(set(matches))
    if len(unique) == 1:
        return LinePolicyDecision(True, unique[0], requested_reference=reference, authorized_lines=tuple(authorized))
    if len(unique) > 1:
        return LinePolicyDecision(
            False, authenticated, reason="other_line_ambiguous",
            user_message="Encontrei mais de uma linha autorizada compatível com a referência informada. Confirme qual linha deseja usar.",
            requested_reference=reference, authorized_lines=tuple(authorized),
        )
    return LinePolicyDecision(
        False, authenticated, reason="other_line_not_authorized_or_not_resolved",
        user_message=(
            "Não consegui confirmar a linha informada entre as linhas autorizadas deste atendimento. "
            "Confirme a linha ou utilize a linha identificada na chamada."
        ),
        requested_reference=reference, authorized_lines=tuple(authorized),
    )
