import os

import pytest

os.environ.setdefault("USE_MOCK_LLM", "true")

from agent_framework.guardrails.calibrated import apply_output_rails, compliance_anatel
from agent_framework.guardrails.calibrated._compat import RailResult


# ---------------------------------------------------------------------------
# Testes unitários diretos em compliance_anatel
# ---------------------------------------------------------------------------

def test_fluxo_nao_ajuste_passa_sem_verificar():
    """Quando o fluxo não exige protocolo, o rail não deve bloquear."""
    r = compliance_anatel("Sua fatura está disponível.", context={})
    assert isinstance(r, RailResult)
    assert r.allowed is True
    assert r.code == "CMP"
    assert r.mechanism == "regex"


def test_fluxo_ajuste_com_protocolo_passa():
    r = compliance_anatel(
        "O ajuste foi realizado. Protocolo: 123456.",
        context={"tipo_fluxo": "ajuste"},
    )
    assert r.allowed is True
    assert r.code == "CMP"


def test_fluxo_ajuste_sem_protocolo_bloqueia():
    r = compliance_anatel(
        "O ajuste foi realizado com sucesso.",
        context={"tipo_fluxo": "ajuste"},
    )
    assert r.allowed is False
    assert r.code == "CMP"
    assert "protocolo" in r.reason.lower()


def test_requer_protocolo_true_com_protocolo_passa():
    r = compliance_anatel(
        "Cancelamento efetuado. Protocolo: 9876543.",
        context={"requer_protocolo": True},
    )
    assert r.allowed is True


def test_requer_protocolo_true_sem_protocolo_bloqueia():
    r = compliance_anatel(
        "Cancelamento efetuado com sucesso.",
        context={"requer_protocolo": True},
    )
    assert r.allowed is False


@pytest.mark.parametrize("text", [
    "Protocolo: 123456",
    "protocolo - 9876543",
    "PROTOCOLO: 1000001",
    "Seu protocolo é 200001.",
    "O número de protocolo: 654321 foi registrado.",
])
def test_formatos_de_protocolo_aceitos(text):
    r = compliance_anatel(text, context={"tipo_fluxo": "ajuste"})
    assert r.allowed is True


@pytest.mark.parametrize("text", [
    "O ajuste foi feito.",
    "Tudo certo com sua solicitação.",
    "Protocolo: 12345",       # apenas 5 dígitos — insuficiente
    "protocolo ABC123",       # não começa com dígitos
])
def test_formatos_invalidos_ou_ausentes_bloqueiam(text):
    r = compliance_anatel(text, context={"tipo_fluxo": "ajuste"})
    assert r.allowed is False


# ---------------------------------------------------------------------------
# Testes de integração via apply_output_rails
# ---------------------------------------------------------------------------

def test_pipeline_ajuste_sem_protocolo_nao_bloqueia_cmp():
    d = apply_output_rails(
        text="O ajuste foi realizado com sucesso.",
        user_text="O ajuste foi realizado com sucesso.",
        tool_calls=None,
        context={"tipo_fluxo": "ajuste"},
    )
    assert d.allowed is True
    assert d.code is None
    assert all(r.code != "CMP" for r in d.results)


def test_pipeline_ajuste_com_protocolo_passa():
    d = apply_output_rails(
        text="Ajuste concluído. Protocolo: 123456.",
        user_text="Ajuste concluído. Protocolo: 123456.",
        tool_calls=None,
        context={"tipo_fluxo": "ajuste"},
    )
    assert d.allowed is True


def test_pipeline_sem_context_nao_exige_protocolo():
    """Sem context, CMP não deve bloquear — fluxo não é de ajuste."""
    d = apply_output_rails(
        text="O ajuste foi realizado.",
        user_text="O ajuste foi realizado.",
        tool_calls=None,
    )
    assert d.allowed is True
    assert all(r.code != "CMP" for r in d.results)


def test_pipeline_cmp_nao_entra_nos_results():
    """CMP roda no fallback determinístico do agente, fora do output rail."""
    d = apply_output_rails(
        text="Posso te ajudar com mais alguma coisa?",
        user_text="Posso te ajudar com mais alguma coisa?",
        tool_calls=None,
        context={"tipo_fluxo": "consulta"},
    )
    assert all(r.code != "CMP" for r in d.results)
