from __future__ import annotations

from app.domain.contas.service import ContasDomainService
from app.domain.contas.workflow_actions import build_contas_workflow_actions


class _Client:
    def __init__(self, *, protocol="INFO-123", fail=False):
        self.protocol = protocol
        self.fail = fail
        self.protocol_calls = []
        self.status_calls = []
    def abrir_protocolo(self, payload):
        self.protocol_calls.append(dict(payload))
        if self.fail:
            raise RuntimeError("falha protocolo")
        return {"interactionProtocol": self.protocol}
    def status_sr(self, payload):
        self.status_calls.append(dict(payload)); return {"ok": True}


def _action(client):
    service = ContasDomainService(client=client)
    reg = build_contas_workflow_actions(service)
    return reg.get("finalizar_atendimento_action")


def _codes(result):
    return [x["code"] for x in result.get("business_events") or []]


def test_invoice_explanation_finalization_orders_events_and_returns_alias():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "Atendimento concluído.",
        "msisdn": "11999999999", "social_sec_no": "123", "message_id": "m1",
        "business_workflows_executed": ["invoice_explanation"],
        "invoice_explanation_base": "Explicação dos valores da fatura.",
    }, {"input": {}})
    assert result["finalizacao_protocol"] == "INFO-123"
    assert _codes(result) == ["CVN.008", "RCT.085", "CVN.010", "MPI.006", "SAD.001"]


def test_invoice_explanation_negative_emits_cvn009_mpi005_without_protocol_when_no_notes():
    client = _Client()
    result = _action(client)({
        "status": "nao_resolvido", "summary": "Cliente não concordou.",
        "business_workflows_executed": ["invoice_explanation"],
    }, {"input": {}})
    assert client.protocol_calls == []
    assert _codes(result) == ["CVN.009", "MPI.005", "SAD.001"]


def test_handoff_suppression_emits_only_sad001():
    client = _Client()
    result = _action(client)({
        "status": "nao_resolvido", "summary": "ATH",
        "business_workflows_executed": ["invoice_explanation"],
        "invoice_explanation_base": "Explicação.",
        "suppress_cvn_009_on_finalize": True,
        "suppress_cvn_lookup_on_finalize": True,
        "suppress_informational_protocol_on_finalize": True,
    }, {"input": {}})
    assert client.protocol_calls == []
    assert _codes(result) == ["SAD.001"]


def test_protocol_failure_does_not_fail_finalization_and_emits_negative_events():
    client = _Client(fail=True)
    result = _action(client)({
        "status": "resolvido", "summary": "ok", "msisdn": "119",
        "business_workflows_executed": ["invoice_explanation"],
        "invoice_explanation_base": "Explicação da fatura.",
    }, {"input": {}})
    assert result["success"] is True
    assert "finalizacao_protocol" not in result
    assert _codes(result) == ["CVN.008", "RCT.086", "CVN.011", "MPI.006", "SAD.001"]


def test_transactional_workflow_does_not_emit_informational_acceptance():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "concluído", "protocol_closed": True,
        "protocol_number": "PRT-1", "business_workflows_executed": ["contestacao_tool"],
    }, {"input": {}})
    assert _codes(result) == ["SAD.001"]


def test_sad_decision_tree_handoff_second_time():
    client = _Client()
    result = _action(client)({
        "status": "nao_resolvido", "summary": "ATH",
        "sad_exit_decision_enabled": True, "human_handoff": True, "ath_first_time": False,
    }, {"input": {}})
    assert _codes(result) == ["SAD.001", "SAD.003", "SAD.004", "SAD.006"]

def test_invoice_explanation_uses_canonical_notes_not_free_text():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "ok", "msisdn": "119",
        "business_workflows_executed": ["invoice_explanation"],
        "invoice_explanation_base": "Resumo qualquer vindo do prefetch e do LLM.",
    }, {"input": {}})
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação dos valores da fatura"
    assert result["finalizacao_protocol"] == "INFO-123"


def test_strategic_partner_is_classified_without_invoice_detail():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "ok", "msisdn": "119",
        "informational_service_names": ["Paramount+ Mensal"],
    }, {"input": {}})
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Estratégico"
    assert result["finalizacao_protocol"] == "INFO-123"


def test_known_avulso_is_classified_without_invoice_detail():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "ok", "msisdn": "119",
        "informational_service_names": ["TIM Fashion Mensal"],
    }, {"input": {}})
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Avulso"
    assert result["finalizacao_protocol"] == "INFO-123"


def test_prefetch_invoice_context_guarantees_lookup_and_rt15_without_latched_workflow():
    client = _Client()
    result = _action(client)({
        "status": "resolvido_outros_assuntos",
        "summary": "Encerramento realizado pelo agente.",
        "msisdn": "11999999999",
        "invoice_id": "3000131181",
        "invoice_explanation_base": "Resumo da fatura carregado no prefetch.",
    }, {"input": {}})
    assert result["finalizacao_protocol"] == "INFO-123"
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação dos valores da fatura"
    assert _codes(result) == ["CVN.002", "CVN.006", "CVN.008", "RCT.085", "CVN.010", "MPI.006", "SAD.001"]


def test_unresolved_transition_does_not_reemit_positive_cvn_or_mpi():
    client = _Client()
    result = _action(client)({
        "status": "resolvido",
        "summary": "Cliente aceitou no fluxo de negócio.",
        "invoice_id": "3000131182",
        "conversation_unresolved_transition_emitted": True,
        "invoice_explanation_base": "Resumo da fatura.",
    }, {"input": {}})
    assert _codes(result) == ["SAD.001"]


def test_terminal_veb_resolution_suppresses_cvn_mpi_and_duplicate_rt15():
    client = _Client()
    result = _action(client)({
        "status": "resolvido",
        "summary": "Cliente aceitou a explicação.",
        "protocol_number": "VEB-123",
        "protocol_closed": True,
        "conversation_explanation_resolved": True,
        "suppress_cvn_protocol_ic": True,
        "informational_vas_types": ["bundle"],
        "informational_service_names": ["Pacote Europa Promocional"],
    }, {"input": {}})
    assert client.protocol_calls == []
    assert result["protocol_number"] == "VEB-123"
    assert _codes(result) == ["SAD.001"]


def test_invoice_detail_conflict_overrides_saved_informational_type():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "ok", "msisdn": "119",
        "informational_service_names": ["TIM Fashion Mensal"],
        "informational_vas_types": ["bundle"],
        "invoice_detail": {"119": {"SVA Detalhe Total": [{"desc": "TIM Fashion Mensal", "value": 19.9, "classe": "avulso"}]}},
    }, {"input": {}})
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Avulso"
    assert result["finalizacao_protocol"] == "INFO-123"


def test_invoice_detail_without_match_ignores_saved_type_and_does_not_create_protocol():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "ok", "msisdn": "119",
        "informational_service_names": ["Serviço que não consta"],
        "informational_vas_types": ["bundle"],
        "invoice_detail": {"119": {"Serviços Bundle Inclusos": [{"desc": "Outro serviço", "value": 0}]}},
    }, {"input": {}})
    assert client.protocol_calls == []
    assert "finalizacao_protocol" not in result


def test_rag_saved_type_is_used_when_invoice_detail_is_absent():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "ok", "msisdn": "119",
        "informational_service_names": ["Serviço explicado pelo RAG"],
        "informational_rag_vas_types": ["bundle"],
    }, {"input": {}})
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle"
    assert result["finalizacao_protocol"] == "INFO-123"


def test_partial_invoice_inference_merges_saved_avulso_type():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "Cliente entendeu a explicação e agradeceu.", "msisdn": "119",
        "informational_service_names": ["Pacote Europa Promocional", "YouTube Premium Mensal", "Aluguel de Filme 3"],
        "informational_vas_types": ["avulso"],
        "invoice_detail": {"119": {
            "Serviços Bundle Inclusos": [{"desc": "Pacote Europa Promocional", "value": 0}],
            "Serviços Contratados de Terceiros": [{"desc": "YouTube Premium Mensal", "value": 24.9, "classe": "estrategico"}],
        }},
    }, {"input": {}})
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle, VAS Estratégico, VAS Avulso"
    assert result["finalizacao_protocol"] == "INFO-123"


def test_existing_session_protocol_prevents_duplicate_informational_rt15():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "Cliente entendeu a explicação.",
        "customer_protocols": [{"number": "PRT-EXISTENTE"}],
        "informational_service_names": ["Paramount+ Mensal"],
    }, {"input": {}})
    assert client.protocol_calls == []
    assert "finalizacao_protocol" not in result


def test_cpf_alias_is_forwarded_to_informational_protocol():
    client = _Client()
    _action(client)({
        "status": "resolvido", "summary": "Cliente entendeu a explicação.",
        "msisdn": "11999999999", "cpf": "12345678901",
        "informational_service_names": ["Paramount+ Mensal"],
    }, {"input": {}})
    assert client.protocol_calls[0]["socialSecNo"] == "12345678901"


def test_three_informational_vas_types_have_canonical_order():
    client = _Client()
    _action(client)({
        "status": "resolvido", "summary": "Cliente entendeu.", "msisdn": "119",
        "informational_vas_types": ["avulso", "bundle", "estrategico"],
    }, {"input": {}})
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle, VAS Estratégico, VAS Avulso"


def test_free_customer_phrase_without_evidence_does_not_create_protocol():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "Cliente entendeu a explicação.",
        "customer_message": "o que é incluído no plano, mas está sendo cobrado?",
    }, {"input": {}})
    assert client.protocol_calls == []
    assert "finalizacao_protocol" not in result


def test_legacy_final_alias_normalizes_to_resolved_without_spurious_protocol():
    client = _Client()
    result = _action(client)({"status": "final", "summary": ""}, {"input": {}})
    assert result["status"] == "resolvido"
    assert client.protocol_calls == []


def test_transactional_cancel_finalization_does_not_emit_cvn_or_mpi_even_with_summary():
    client = _Client()
    result = _action(client)({
        "status": "resolvido", "summary": "Cancelamento concluído.",
        "business_workflows_executed": ["cancelamento_vas_avulso"],
        "protocol_number": "CAN-123", "protocol_closed": True,
    }, {"input": {}})
    assert _codes(result) == ["SAD.001"]


def test_strategic_notes_take_priority_over_prior_invoice_explanation_notes():
    client = _Client()
    result = _action(client)({
        "status": "resolvido",
        "summary": "Cliente entendeu a explicação e agradeceu.",
        "msisdn": "11999999999",
        "business_workflows_executed": ["invoice_explanation"],
        "invoice_explanation_base": "Explicação dos valores da fatura.",
        "informational_service_names": ["YouTube Premium Mensal"],
        "informational_vas_types": ["estrategico"],
    }, {"input": {}})
    assert result["finalizacao_protocol"] == "INFO-123"
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Estratégico"


def test_deferred_bundle_and_strategic_items_create_combined_rt15_without_workflow_latch():
    client = _Client()
    result = _action(client)({
        "status": "resolvido",
        "summary": "Cliente entendeu a explicação e agradeceu.",
        "msisdn": "11999999999",
        "protocol_deferred_to_finalization": True,
        "informational_service_names": ["Pacote Europa Promocional", "YouTube Premium Mensal"],
        "informational_vas_types": ["bundle", "estrategico"],
        "invoice_detail": {
            "11999999999": {
                "Serviços Bundle Inclusos": [{"desc": "Pacote Europa Promocional", "value": 0}],
                "Serviços Contratados de Terceiros": [{"desc": "YouTube Premium Mensal", "value": 24.9, "classe": "estrategico"}],
            }
        },
    }, {"input": {}})
    assert result["finalizacao_protocol"] == "INFO-123"
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle, VAS Estratégico"


def test_invoice_explanation_only_registers_protocol_at_finalization():
    client = _Client()
    result = _action(client)({
        "status": "resolvido",
        "summary": "Cliente aceitou a explicação.",
        "msisdn": "11999999999",
        "business_workflows_executed": ["invoice_explanation"],
        "invoice_explanation_base": "Explicação dos valores da fatura.",
    }, {"input": {}})
    assert len(client.protocol_calls) == 1
    assert result["finalizacao_protocol"] == "INFO-123"
    assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação dos valores da fatura"
