"""Paridade do compositor determinístico com o prompt
``fluxo_vas_cancelamento_resposta_cliente`` (regras 1.1, 2–8).

Os goldens de sucesso/erro/SMS vêm dos próprios exemplos do prompt em
``builtin/prompts/vas_cancellation_response.yaml``.
"""

from __future__ import annotations

from app.domain.contas.vas_cancellation_message import (
    compose_vas_cancellation_message,
)

PRT = "PRT475D8F1C1F"


def test_regra_3_sucesso_com_sms_singular() -> None:
    # Exemplo do prompt: "Exemplo (sucesso com SMS)".
    msg = compose_vas_cancellation_message(
        {
            "contested_items": [{"itemName": "Tamboro Mensal"}],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": True,
            "sms_not_send_error": False,
            "msisdn": "11999999999",
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O cancelamento foi concluído com sucesso. O valor contestado foi retirado "
        "da sua fatura. Enviamos um SMS com o novo código de barras e o valor "
        "atualizado. O prazo para pagamento é de 4 dias. "
        f"Seu número de protocolo é {PRT}."
    )


def test_regra_3_e_6_2_falha_no_sms_plural() -> None:
    # Exemplo do prompt: "Exemplo (sucesso com falha no SMS)".
    msg = compose_vas_cancellation_message(
        {
            "contested_items": [
                {"itemName": "Tamboro Mensal"},
                {"itemName": "TIM Fashion"},
            ],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": True,
            "sms_not_send_error": True,
            "msisdn": "11999999999",
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O cancelamento dos itens foi concluído com sucesso. O valor total de "
        "R$ 22,00 foi retirado da sua fatura. Identificamos uma instabilidade no "
        "envio do SMS com o novo código para pagamento. Você pode consultar o "
        "código atualizado e o prazo de pagamento diretamente no app Meu TIM. "
        f"Seu número de protocolo é {PRT}."
    )


def test_regra_2_credito_plural_com_regra_5() -> None:
    # Baseado no "Exemplo (crédito em fatura)" do prompt; o conector "No entanto,"
    # era floreio do LLM — a forma determinística segue o template literal da regra 5.
    msg = compose_vas_cancellation_message(
        {
            "contested_items": [
                {"itemName": "Aluguel de Série 1"},
                {"itemName": "Aluguel de Série 2"},
            ],
            "not_contested_items": [{"itemName": "Tamboro Mensal"}],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": False,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O cancelamento dos itens foi feito com sucesso. O crédito no valor total "
        "de R$ 22,00 ficou registrado como crédito para sua próxima fatura. "
        "Não foi possível contestar o item Tamboro Mensal. "
        f"Seu número de protocolo é {PRT}."
    )


def test_regra_2_credito_singular() -> None:
    msg = compose_vas_cancellation_message(
        {
            "contested_items": [{"itemName": "Tamboro Mensal"}],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": False,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O cancelamento do item Tamboro Mensal no valor de R$ 22,00 foi concluído "
        "com sucesso. O valor contestado ficou registrado como crédito para sua "
        f"próxima fatura. Seu número de protocolo é {PRT}."
    )


def test_regra_8_erro_terminal_copia_literal_e_protocolo() -> None:
    # Exemplo do prompt: "Exemplo (falha, usando um dos textos de ...)".
    erro = (
        "Verifiquei aqui que este item já foi contestado anteriormente, por isso "
        "não consigo seguir com uma nova contestação. Peço que aguarde um instante."
    )
    msg = compose_vas_cancellation_message(
        {
            "contestation_error_description": erro,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == f"{erro} Seu número de protocolo é {PRT}."


def test_regra_8_adiciona_ponto_quando_texto_nao_termina_em_pontuacao() -> None:
    msg = compose_vas_cancellation_message(
        {
            "contestation_error_description": "Não foi possível processar",
            "contestacao_protocol": PRT,
        }
    )
    assert msg == f"Não foi possível processar. Seu número de protocolo é {PRT}."


def test_regra_8_item_ja_contestado_informa_cancelamentos_realizados() -> None:
    msg = compose_vas_cancellation_message(
        {
            "cancelados": [{"servico": "A"}, {"servico": "B"}],
            "contestation_error_description": (
                "Verifiquei aqui que estes itens já foram contestados anteriormente, "
                "por isso não consigo seguir com uma nova contestação."
            ),
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O cancelamento dos itens A e B foi concluído com sucesso. "
        "Verifiquei aqui que estes itens já foram contestados anteriormente, "
        "por isso não consigo seguir com uma nova contestação. "
        f"Seu número de protocolo é {PRT}."
    )


def test_regra_1_1_misto_credito() -> None:
    msg = compose_vas_cancellation_message(
        {
            "itens_ja_contestados": ["Tamboro Mensal"],
            "contested_items": [{"itemName": "TIM Fashion"}],
            "contested_invoice_amount_open": "10,00",
            "sms_sent": False,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "Identifiquei que o item Tamboro Mensal já havia sido contestado "
        "anteriormente e, por esse motivo, não é possível registrar uma nova "
        "contestação para ele. Já a contestação do item TIM Fashion no valor de "
        "R$ 10,00 foi concluída com sucesso. O valor contestado ficou registrado "
        f"como crédito para sua próxima fatura. Seu número de protocolo é {PRT}."
    )


def test_regra_1_1_misto_com_sms_aplica_regra_6() -> None:
    msg = compose_vas_cancellation_message(
        {
            "itens_ja_contestados": ["A", "B"],
            "contested_items": [{"itemName": "C"}, {"itemName": "D"}],
            "contested_invoice_amount_open": "30,00",
            "sms_sent": True,
            "sms_not_send_error": False,
            "msisdn": "11988887777",
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O cancelamento foi concluído com sucesso. O valor contestado foi retirado "
        "da sua fatura. Enviamos um SMS com o novo código de barras e o valor "
        "atualizado. O prazo para pagamento é de 4 dias. "
        f"Seu número de protocolo é {PRT}."
    )


def test_sms_enviado_prevalece_quando_contested_items_esta_vazio() -> None:
    # Regressão do trace 6ae8bd24: SMS efetivamente enviado nunca vira crédito.
    msg = compose_vas_cancellation_message(
        {
            "itens_ja_contestados": ["Tamboro Mensal"],
            "contested_items": [],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": True,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O cancelamento foi concluído com sucesso. O valor contestado foi retirado "
        "da sua fatura. Enviamos um SMS com o novo código de barras e o valor "
        "atualizado. O prazo para pagamento é de 4 dias. "
        f"Seu número de protocolo é {PRT}."
    )
    assert "próxima fatura" not in msg


def test_regra_7_protocolos_multiplos() -> None:
    msg = compose_vas_cancellation_message(
        {
            "contested_items": [{"itemName": "Tamboro Mensal"}],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": False,
            "contestacao_protocols": ["PRTAAA", "PRTBBB"],
        }
    )
    assert msg.endswith("Seus números de protocolo são PRTAAA e PRTBBB.")


def test_no_match_credito_todos_nao_encontrados_singular() -> None:
    # Cenário 2 (crédito): serviço não localizado na plataforma; valor contestado.
    msg = compose_vas_cancellation_message(
        {
            "success": True,
            "contested_items": [{"itemName": "Tamboro Mensal"}],
            "nao_encontrados": [{"servico": "Tamboro Mensal"}],
            "cancelados": [],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": False,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O valor total de R$ 22,00 ficou registrado como crédito para sua próxima "
        "fatura. Sobre o cancelamento do serviço Tamboro Mensal, não consegui "
        "realizar por aqui. Você pode cancelar pelo App Meu TIM, na opção "
        f"Gerenciar Benefícios. Seu número de protocolo é {PRT}."
    )


def test_no_match_sms_todos_nao_encontrados() -> None:
    # Cenário 2 (SMS/boleto): valor retirado + SMS + no-match.
    msg = compose_vas_cancellation_message(
        {
            "success": True,
            "contested_items": [{"itemName": "Tamboro Mensal"}],
            "nao_encontrados": [{"servico": "Tamboro Mensal"}],
            "cancelados": [],
            "contested_invoice_amount_open": "22,00",
            "sms_sent": True,
            "sms_not_send_error": False,
            "msisdn": "11999999999",
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O valor total de R$ 22,00 foi retirado da sua fatura. Enviamos um SMS com "
        "o novo código de barras e o valor atualizado. O prazo para pagamento é de "
        "4 dias. Sobre o cancelamento do serviço Tamboro "
        "Mensal, não consegui realizar por aqui. Você pode cancelar pelo App Meu "
        f"TIM, na opção Gerenciar Benefícios. Seu número de protocolo é {PRT}."
    )


def test_no_match_misto_credito() -> None:
    # Cenário 3 (crédito): A,B,C cancelados; D,E,F no-match.
    msg = compose_vas_cancellation_message(
        {
            "success": True,
            "contested_items": [{"itemName": x} for x in ("A", "B", "C", "D", "E", "F")],
            "cancelados": [{"servico": x} for x in ("A", "B", "C")],
            "nao_encontrados": [{"servico": x} for x in ("D", "E", "F")],
            "contested_invoice_amount_open": "60,00",
            "sms_sent": False,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O valor total de R$ 60,00 ficou registrado como crédito para sua próxima "
        "fatura. O cancelamento dos serviços A, B e C foram realizados com sucesso. "
        "Não consegui realizar por aqui o cancelamento dos serviços D, E e F. Você "
        "pode cancelá-los pelo App Meu TIM, na opção Gerenciar Benefícios. "
        f"Seu número de protocolo é {PRT}."
    )


def test_no_match_misto_sms() -> None:
    # Cenário 3 (SMS/boleto).
    msg = compose_vas_cancellation_message(
        {
            "success": True,
            "contested_items": [{"itemName": x} for x in ("A", "B", "C", "D", "E", "F")],
            "cancelados": [{"servico": x} for x in ("A", "B", "C")],
            "nao_encontrados": [{"servico": x} for x in ("D", "E", "F")],
            "contested_invoice_amount_open": "60,00",
            "sms_sent": True,
            "sms_not_send_error": False,
            "msisdn": "11988887777",
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O valor total de R$ 60,00 foi retirado da sua fatura. Enviamos um SMS com "
        "o novo código de barras e o valor atualizado. O prazo para pagamento é de "
        "4 dias. O cancelamento dos serviços A, B e C foram "
        "realizados com sucesso. Não consegui realizar por aqui o cancelamento dos "
        "serviços D, E e F. Você pode cancelá-los pelo App Meu TIM, na opção "
        f"Gerenciar Benefícios. Seu número de protocolo é {PRT}."
    )


def test_no_match_misto_singular_cada_lista() -> None:
    # Concordância: 1 cancelado + 1 no-match.
    msg = compose_vas_cancellation_message(
        {
            "success": True,
            "contested_items": [{"itemName": "A"}, {"itemName": "B"}],
            "cancelados": [{"servico": "A"}],
            "nao_encontrados": [{"servico": "B"}],
            "contested_invoice_amount_open": "20,00",
            "sms_sent": False,
            "contestacao_protocol": PRT,
        }
    )
    assert msg == (
        "O valor total de R$ 20,00 ficou registrado como crédito para sua próxima "
        "fatura. O cancelamento do serviço A foi realizado com sucesso. Não "
        "consegui realizar por aqui o cancelamento do serviço B. Você pode "
        f"cancelá-lo pelo App Meu TIM, na opção Gerenciar Benefícios. Seu número "
        f"de protocolo é {PRT}."
    )


def test_sucesso_sem_itens_detalhados_gera_confirmacao_generica() -> None:
    # Sem itens contestados/não contestados/já contestados, mas cancelamento OK:
    # confirmação neutra + protocolo (regra 7).
    msg = compose_vas_cancellation_message(
        {
            "success": True,
            "contested_items": [],
            "not_contested_items": [],
            "contestacao_protocol": PRT,
        }
    )
    assert msg == f"O cancelamento foi concluído com sucesso. Seu número de protocolo é {PRT}."


def test_sucesso_sem_itens_e_sem_protocolo_so_confirmacao() -> None:
    # Protocolo de cancelamento (não de contestação) é anexado pelo backend, não aqui.
    msg = compose_vas_cancellation_message({"success": True, "contested_items": []})
    assert msg == "O cancelamento foi concluído com sucesso."


def test_payload_nao_classificavel_sem_sucesso_retorna_vazio() -> None:
    assert compose_vas_cancellation_message({}) == ""
    assert compose_vas_cancellation_message({"success": False}) == ""
    assert compose_vas_cancellation_message("nao-mapping") == ""  # type: ignore[arg-type]
