from __future__ import annotations

import pytest


class FakeRuntime:
    def __init__(self):
        self.calls = []

    async def arun(self, name, payload, execution_id=None):
        self.calls.append((name, payload, execution_id))
        if name == "cancelamento_vas_avulso":
            return {
                "execution_id": "exec-cancel",
                "workflow_name": name,
                "workflow_version": 1,
                "status": "COMPLETED",
                "output": {
                    "cancelar_vas_avulso": {
                        "success": True,
                        "results": [
                            {
                                "success": True,
                                "msisdn": "5511999999999",
                                "subject": "TIM Fashion Mensal",
                            }
                        ],
                        "contestation_candidates": [
                            {
                                "success": True,
                                "msisdn": "5511999999999",
                                "subject": "TIM Fashion Mensal",
                            }
                        ],
                    }
                },
                "state": {},
                "trace": [],
            }
        assert name == "contestacao_tool"
        return {
            "execution_id": "exec-cont",
            "workflow_name": name,
            "workflow_version": 2,
            "status": "COMPLETED",
            "output": {
                "registrar_protocolo": {"protocolo_id": "PRT-100"},
                "abrir_contestacao_cliente": {
                    "success": True,
                    "items_response": [
                        {
                            "correctAccountStatus": "CRIAR",
                            "itemName": "TIM Fashion Mensal",
                            "status": "INICIADA",
                        }
                    ],
                    "contested_invoice_amount_open": "14,99",
                },
            },
            "state": {},
            "trace": [],
        }


class FakeService:
    def consultar_faturas(self, *, msisdn: str):
        assert msisdn == "5511999999999"
        return {
            "billingProfile": {
                "customer": {
                    "document": "12345678901",
                    "customerId": "344575482",
                }
            },
            "paymentItems": [
                {
                    "invoiceId": "5536806781",
                    "dueDate": "2025-08-11",
                }
            ],
        }


@pytest.mark.asyncio
async def test_cancelamento_encadeia_contestacao_no_workflow_runtime(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    runtime = FakeRuntime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    monkeypatch.setattr(main, "service", FakeService())

    result = await main._run_cancelamento_com_contestacao(
        {
            "msisdn": "5511999999999",
            "subject": "TIM Fashion Mensal",
            "items": [
                {
                    "msisdn": "5511999999999",
                    "name": "TIM Fashion Mensal",
                    "value": "14,99",
                }
            ],
        }
    )

    assert [call[0] for call in runtime.calls] == [
        "cancelamento_vas_avulso",
        "contestacao_tool",
    ]
    contest_payload = runtime.calls[1][1]
    assert contest_payload["social_sec_no"] == "12345678901"
    assert contest_payload["customer_id"] == "344575482"
    assert contest_payload["current_invoice_number"] == "5536806781"
    assert contest_payload["items"][0]["itemName"] == "TIM Fashion Mensal"
    assert contest_payload["items"][0]["claimedAmount"] == "14,99"
    assert result["contestacao_protocol"] == "PRT-100"
    assert result["protocols_for_response"] == ["PRT-100"]
    assert result["requires_protocol_in_response"] is True
    assert result["metadata"]["composite_workflows"] == [
        "cancelamento_vas_avulso",
        "contestacao_tool",
    ]
    assert result["mensagem"].endswith("Seu número de protocolo é PRT-100.")


@pytest.mark.asyncio
async def test_cancelamento_sem_candidato_nao_abre_contestacao(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    class NoMatchRuntime(FakeRuntime):
        async def arun(self, name, payload, execution_id=None):
            self.calls.append((name, payload, execution_id))
            return {
                "execution_id": "exec-cancel",
                "workflow_name": name,
                "workflow_version": 1,
                "status": "COMPLETED",
                "output": {
                    "cancelar_vas_avulso": {
                        "success": False,
                        "results": [
                            {
                                "success": False,
                                "msisdn": payload["items"][0]["msisdn"],
                                "subject": payload["items"][0]["name"],
                                "error": "Serviço não encontrado entre os VAS ativos",
                            }
                        ],
                        "contestation_candidates": [],
                    }
                },
                "state": {},
                "trace": [],
            }

    runtime = NoMatchRuntime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    result = await main._run_cancelamento_com_contestacao(
        {"msisdn": "5511999999999", "subject": "Inexistente"}
    )
    assert [call[0] for call in runtime.calls] == ["cancelamento_vas_avulso"]
    assert result["metadata"]["composite_workflows"] == ["cancelamento_vas_avulso"]


@pytest.mark.asyncio
async def test_action_cancelamento_lote_aproveita_um_sucesso_entre_falhas():
    from app.domain.contas.workflow_actions import build_contas_workflow_actions

    class Service:
        def cancelar_vas_avulso(self, *, msisdn, subject, protocol=""):
            if subject == "OK":
                return {"success": True, "service": {"name": subject}}
            return {"success": False, "subject": subject, "reason": "service_not_found", "error": "não encontrado"}

    class Store:
        @staticmethod
        def canonical_key(*parts): return "|".join(map(str, parts))
        async def get(self, key): return None
        async def set(self, key, value, ttl_seconds=None): return None

    reg = build_contas_workflow_actions(Service(), idempotency_store=Store())  # type: ignore[arg-type]
    action = reg.get("cancelamento_vas_avulso_batch")
    result = await action(
        {"items": [
            {"msisdn": "119", "name": "FALHA1"},
            {"msisdn": "119", "name": "OK"},
            {"msisdn": "119", "name": "FALHA2"},
        ]},
        {"input": {}, "execution_id": "e1"},
    )
    assert result["success"] is True
    assert len(result["cancelados"]) == 1
    assert len(result["nao_encontrados"]) == 2
    assert len(result["itens_para_contestacao"]) == 1
    assert result["itens_para_contestacao"][0]["subject"] == "OK"

@pytest.mark.asyncio
async def test_plano_familia_mantem_titular_na_contestacao_e_dependente_no_cancelamento(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    class FamilyRuntime(FakeRuntime):
        async def arun(self, name, payload, execution_id=None):
            self.calls.append((name, payload, execution_id))
            if name == "cancelamento_vas_avulso":
                return {
                    "execution_id": "exec-cancel",
                    "workflow_name": name,
                    "workflow_version": 1,
                    "status": "COMPLETED",
                    "output": {"cancelar_vas_avulso": {
                        "success": True,
                        "results": [{"success": True, "msisdn": "5511999999999", "subject": "TIM Fashion Mensal"}],
                        "contestation_candidates": [{"success": True, "msisdn": "5511999999999", "subject": "TIM Fashion Mensal"}],
                    }},
                    "state": {}, "trace": [],
                }
            assert name == "contestacao_tool"
            return {
                "execution_id": "exec-cont", "workflow_name": name, "workflow_version": 2,
                "status": "COMPLETED",
                "output": {"registrar_protocolo": {"protocolo_id": "PRT-FAM"}, "abrir_contestacao_cliente": {"success": True}},
                "state": {}, "trace": [],
            }

    runtime = FamilyRuntime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    monkeypatch.setattr(main, "service", FakeService())
    prefetch = {"billingProfile": {"customer": {"document": "12345678901", "customerId": "344575482"}}, "paymentItems": [{"invoiceId": "5536806781"}]}
    result = await main._run_cancelamento_com_contestacao({
        "msisdn": "5511888880000",  # titular
        "items": [{"msisdn": "5511999999999", "name": "TIM Fashion Mensal", "value": "14,99"}],
        "complete_invoices_payload": prefetch,
    })
    assert result["contestacao_protocol"] == "PRT-FAM"
    cancel_payload = runtime.calls[0][1]
    assert cancel_payload["msisdn"] == "5511888880000"
    assert cancel_payload["items"][0]["msisdn"] == "5511999999999"
    contest_payload = runtime.calls[1][1]
    assert contest_payload["msisdn"] == "5511888880000"
    assert contest_payload["item_msisdn"] == "5511888880000"
    assert contest_payload["dependent_invoice_item"] is True
    assert contest_payload["complete_invoices_payload"] == prefetch


@pytest.mark.asyncio
async def test_invoice_detail_corrige_linha_do_item_antes_do_cancelamento(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    class Runtime(FakeRuntime):
        async def arun(self, name, payload, execution_id=None):
            self.calls.append((name, payload, execution_id))
            return {
                "execution_id": "exec-cancel", "workflow_name": name, "workflow_version": 1,
                "status": "COMPLETED",
                "output": {"cancelar_vas_avulso": {"success": True, "results": [], "contestation_candidates": []}},
                "state": {}, "trace": [],
            }

    runtime = Runtime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    await main._run_cancelamento_com_contestacao({
        "msisdn": "11964460192",
        "items": [
            {"msisdn": "11964460192", "name": "Aluguel de Filme 2", "value": 19.9},
            {"msisdn": "11964460192", "name": "Aluguel de Filme 3", "value": 19.9},
        ],
        "invoice_detail": {
            "11964460192": {"SVA Detalhe Total": [{"desc": "Aluguel de Filme 2", "value": 19.9, "msisdn": "11964460192"}]},
            "11964490143": {"SVA Detalhe Total": [{"desc": "Aluguel de Filme 3", "value": 19.9, "msisdn": "11964490143"}]},
        },
    })
    items = runtime.calls[0][1]["items"]
    assert items[0]["msisdn"] == "11964460192"
    assert items[1]["msisdn"] == "11964490143"

@pytest.mark.asyncio
async def test_cancelamento_propaga_bloqueio_da_contestacao_sem_mascarar_sucesso(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    class Runtime(FakeRuntime):
        async def arun(self, name, payload, execution_id=None):
            self.calls.append((name, payload, execution_id))
            if name == "cancelamento_vas_avulso":
                return {
                    "execution_id": "c", "workflow_name": name, "workflow_version": 1, "status": "COMPLETED",
                    "output": {"cancelar_vas_avulso": {"success": True, "results": [{"success": True, "msisdn": payload["msisdn"], "subject": "Disney"}], "contestation_candidates": [{"success": True, "msisdn": payload["msisdn"], "subject": "Disney"}]}},
                    "state": {}, "trace": [],
                }
            return {
                "execution_id": "x", "workflow_name": name, "workflow_version": 2, "status": "COMPLETED",
                "output": {"abrir_contestacao_cliente": {"success": False, "blocked": True, "guardrail_code": "CVAL", "guardrail_reason": "VAS estratégico não pode ser ajustado"}},
                "state": {}, "trace": [],
            }

    runtime = Runtime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    monkeypatch.setattr(main, "service", FakeService())
    result = await main._run_cancelamento_com_contestacao({"msisdn": "5511999999999", "subject": "Disney", "valor": 10})
    assert result["success"] is False
    assert result["erro_sistemico"] is True
    assert result["mensagem"] == "VAS estratégico não pode ser ajustado"

@pytest.mark.asyncio
async def test_cancelamento_lote_nao_executa_side_effect_se_protocolo_por_linha_falhar():
    from app.domain.contas.workflow_actions import build_contas_workflow_actions

    class Client:
        def abrir_protocolo(self, payload):
            return {}

    class Service:
        client = Client()
        def __init__(self): self.cancel_calls = 0
        def cancelar_vas_avulso(self, *, msisdn, subject, protocol=""):
            self.cancel_calls += 1
            return {"success": True}

    class Store:
        @staticmethod
        def canonical_key(*parts): return "|".join(map(str, parts))
        async def get(self, key): return None
        async def set(self, key, value, ttl_seconds=None): return None

    service = Service()
    reg = build_contas_workflow_actions(service, idempotency_store=Store())  # type: ignore[arg-type]
    result = await reg.get("cancelamento_vas_avulso_batch")(
        {"items": [{"msisdn": "119", "name": "VAS A"}], "message_id": "m1"},
        {"input": {}, "execution_id": "e1"},
    )
    assert result["success"] is False
    assert result["nao_cancelados"][0]["reason"] == "protocol_registration_failed"
    assert service.cancel_calls == 0


@pytest.mark.asyncio
async def test_cancelamento_lote_limita_concorrencia_a_cinco(monkeypatch):
    import threading
    import time
    from app.domain.contas.workflow_actions import build_contas_workflow_actions

    monkeypatch.setenv("TIM_CANCELAMENTO_BATCH_CONCURRENCY", "5")

    class Service:
        def __init__(self):
            self.lock = threading.Lock()
            self.active = 0
            self.max_active = 0
        def cancelar_vas_avulso(self, *, msisdn, subject, protocol=""):
            with self.lock:
                self.active += 1
                self.max_active = max(self.max_active, self.active)
            time.sleep(0.03)
            with self.lock:
                self.active -= 1
            return {"success": True, "service": {"name": subject}}

    class Store:
        @staticmethod
        def canonical_key(*parts): return "|".join(map(str, parts))
        async def get(self, key): return None
        async def set(self, key, value, ttl_seconds=None): return None

    service = Service()
    reg = build_contas_workflow_actions(service, idempotency_store=Store())  # type: ignore[arg-type]
    items = [{"msisdn": "119", "name": f"VAS {i}", "protocol": f"P{i}"} for i in range(10)]
    result = await reg.get("cancelamento_vas_avulso_batch")(
        {"items": items}, {"input": {}, "execution_id": "e1"}
    )
    assert result["success"] is True
    assert len(result["cancelados"]) == 10
    assert service.max_active == 5

@pytest.mark.asyncio
async def test_falha_de_bloqueio_permanece_candidata_a_contestacao():
    from app.domain.contas.workflow_actions import build_contas_workflow_actions

    class Client:
        def consultar_vas(self, msisdn):
            return {"products": [{"name": "TIM Fashion Mensal", "canCancel": True, "appId": "1", "cspId": "740"}]}
        def historico_vas(self, msisdn): return {"products": []}
        def bloquear_vas(self, msisdn, service): raise RuntimeError("Timeout no bloqueio")
        def cancelar_vas(self, msisdn, service, protocol=""):
            raise AssertionError("cancelamento não deve ocorrer após falha de bloqueio")

    class Service:
        client = Client()
        def cancelar_vas_avulso(self, *, msisdn, subject, protocol=""):
            from app.domain.contas.service import ContasDomainService
            return ContasDomainService(self.client).cancelar_vas_avulso(msisdn=msisdn, subject=subject, protocol=protocol)

    class Store:
        @staticmethod
        def canonical_key(*parts): return "|".join(map(str, parts))
        async def get(self, key): return None
        async def set(self, key, value, ttl_seconds=None): return None

    # Pass a pre-existing protocol so this unit test isolates the VAS side effect.
    reg = build_contas_workflow_actions(Service(), idempotency_store=Store())  # type: ignore[arg-type]
    result = await reg.get("cancelamento_vas_avulso_batch")(
        {"items": [{"msisdn": "5511999999999", "name": "TIM Fashion Mensal", "protocol": "PRT-1"}]},
        {"input": {}, "execution_id": "e-block"},
    )
    assert result["success"] is False
    assert result["results"][0]["reason"] == "block_vas_failed"
    assert result["results"][0]["eligible_for_contestation"] is True
    assert len(result["itens_para_contestacao"]) == 1


@pytest.mark.asyncio
async def test_resposta_composta_preserva_protocolos_cancelamento_e_contestacao(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    class Runtime(FakeRuntime):
        async def arun(self, name, payload, execution_id=None):
            self.calls.append((name, payload, execution_id))
            if name == "cancelamento_vas_avulso":
                return {
                    "execution_id": "cancel", "workflow_name": name, "workflow_version": 1, "status": "COMPLETED",
                    "output": {"cancelar_vas_avulso": {
                        "success": True,
                        "results": [{"success": True, "msisdn": "5511999999999", "subject": "Tamboro Mensal"}],
                        "contestation_candidates": [{"success": True, "msisdn": "5511999999999", "subject": "Tamboro Mensal"}],
                        "protocolos_por_linha": [{"msisdn": "5511999999999", "protocolo_id": "PRT-CANCEL-1"}],
                    }}, "state": {}, "trace": [],
                }
            return {
                "execution_id": "cont", "workflow_name": name, "workflow_version": 2, "status": "COMPLETED",
                "output": {
                    "registrar_protocolo": {"protocolo_id": "PRT-CONTEST-1", "protocol_closed": True},
                    "abrir_contestacao_cliente": {"success": True, "items_response": []},
                }, "state": {}, "trace": [],
            }

    runtime = Runtime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    monkeypatch.setattr(main, "service", FakeService())
    result = await main._run_cancelamento_com_contestacao({
        "msisdn": "5511999999999", "subject": "Tamboro Mensal", "valor": "14,99",
    })
    assert result["success"] is True
    assert result["recomenda_finalizacao"] is True
    assert result["status_finalizacao_sugerido"] == "resolvido"
    assert result["protocols_for_response"] == ["PRT-CANCEL-1", "PRT-CONTEST-1"]
    assert result["requires_protocol_in_response"] is True
    assert result["protocol_closed"] is True

@pytest.mark.asyncio
async def test_cancelamento_dependente_resolve_cpf_da_linha_antes_do_protocolo(monkeypatch):
    from app.domain.contas.workflow_actions import build_contas_workflow_actions

    recorded = {}
    class Client:
        def line_info(self, msisdn):
            assert msisdn == "5511999999999"
            return {"social_sec_no": "CPF-DEPENDENTE"}
        def abrir_protocolo(self, payload):
            recorded.update(payload)
            return {"protocol": "PRT-DEP"}

    class Service:
        client = Client()
        def cancelar_vas_avulso(self, *, msisdn, subject, protocol=""):
            return {"success": True, "service": {"name": subject}}

    class Store:
        @staticmethod
        def canonical_key(*parts): return "|".join(map(str, parts))
        async def get(self, key): return None
        async def set(self, key, value, ttl_seconds=None): return None

    reg = build_contas_workflow_actions(Service(), idempotency_store=Store())  # type: ignore[arg-type]
    result = await reg.get("cancelamento_vas_avulso_batch")(
        {
            "msisdn": "5511888880000",
            "social_sec_no": "CPF-TITULAR",
            "items": [{"msisdn": "5511999999999", "name": "TIM Fashion Mensal"}],
        },
        {"input": {}, "execution_id": "e-family"},
    )
    assert result["success"] is True
    assert recorded["socialSecNo"] == "CPF-DEPENDENTE"
    assert recorded["msisdn"] == "5511999999999"


def test_result_payload_invoice_explanation_recomenda_finalizacao_por_last_node():
    import contas_mcp.servers.contas_mcp_server.main as main

    accepted = main._result_payload({
        "execution_id": "ie-1",
        "workflow_name": "invoice_explanation",
        "workflow_version": 2,
        "status": "COMPLETED",
        "output": {},
        "state": {},
        "trace": [{"node": "registrar_protocolo_aceite"}],
        "error_details": {},
    }, workflow_name="invoice_explanation")
    assert accepted["recomenda_finalizacao"] is True
    assert accepted["status_finalizacao_sugerido"] == "resolvido"

    refused = main._result_payload({
        "execution_id": "ie-2",
        "workflow_name": "invoice_explanation",
        "workflow_version": 2,
        "status": "COMPLETED",
        "output": {},
        "state": {},
        "trace": [{"node": "finalizar_nao_resolvido"}],
        "error_details": {},
    }, workflow_name="invoice_explanation")
    assert refused["recomenda_finalizacao"] is True
    assert refused["status_finalizacao_sugerido"] == "nao_resolvido"

    vas_branch = main._result_payload({
        "execution_id": "ie-3",
        "workflow_name": "invoice_explanation",
        "workflow_version": 2,
        "status": "COMPLETED",
        "output": {},
        "state": {},
        "trace": [{"node": "checar_vas_variacao"}],
        "error_details": {},
    }, workflow_name="invoice_explanation")
    assert "recomenda_finalizacao" not in vas_branch


def test_result_payload_pro_rata_recomenda_finalizacao_somente_nos_ramos_finais():
    import contas_mcp.servers.contas_mcp_server.main as main

    for node in ("registrar_aceitou", "registrar_nao_controle"):
        result = main._result_payload({
            "execution_id": f"pr-{node}",
            "workflow_name": "pro_rata",
            "workflow_version": 3,
            "status": "COMPLETED",
            "output": {},
            "state": {},
            "trace": [{"node": node}],
            "error_details": {},
        }, workflow_name="pro_rata")
        assert result["recomenda_finalizacao"] is True
        assert result["status_finalizacao_sugerido"] == "resolvido"

    unresolved = main._result_payload({
        "execution_id": "pr-no",
        "workflow_name": "pro_rata",
        "workflow_version": 3,
        "status": "COMPLETED",
        "output": {},
        "state": {},
        "trace": [{"node": "devolver_orquestrador"}],
        "error_details": {},
    }, workflow_name="pro_rata")
    assert "recomenda_finalizacao" not in unresolved


@pytest.mark.asyncio
async def test_cancelamento_redireciona_item_estrategico_para_workflow_correto(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main
    from types import SimpleNamespace

    resolved = SimpleNamespace(
        canonical_name="Paramount+ Mensal",
        msisdn="5511999999999",
        charge_date=None,
        value=12.34,
        tool_category="vas_estrategico",
        item_type="estrategico",
    )
    outcome = SimpleNamespace(ambiguous=[], resolved=[resolved], out_of_scope=[])
    monkeypatch.setattr(main.invoice_resolver, "resolve", lambda *_args, **_kwargs: outcome)
    monkeypatch.setattr(main.service.client, "billing_analysis", lambda _msisdn: {"currentInvoice": {}})
    monkeypatch.setattr(main, "_enrich_invoice_context", lambda *args, **kwargs: __import__('asyncio').sleep(0))

    class Runtime:
        async def arun(self, name, payload, execution_id=None):
            assert name == "vas_estrategico"
            assert payload["items"] == [{
                "type": "estrategico",
                "msisdn": "5511999999999",
                "name": "Paramount+ Mensal",
            }]
            return {
                "execution_id": "exec-vas",
                "workflow_name": name,
                "workflow_version": 3,
                "status": "COMPLETED",
                "output": {},
                "state": {},
                "trace": [{"node": "registrar_atendimento"}],
                "error_details": {},
            }
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: Runtime())

    result = await main._invoke("cancelar_vas_avulso", {
        "msisdn": "5511999999999",
        "subject": "Paramount+ Mensal",
        "billing_analysis": {"currentInvoice": {}},
        "complete_invoices_payload": {},
    })
    assert result["metadata"]["domain_redirect_from"] == "cancelar_vas_avulso"
    assert result["metadata"]["domain_redirect_to"] == "tratar_vas_estrategico"

@pytest.mark.asyncio
async def test_cancelamento_usa_valor_vas_validado_quando_usuario_nao_informa_valor(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    class Runtime(FakeRuntime):
        async def arun(self, name, payload, execution_id=None):
            self.calls.append((name, payload, execution_id))
            if name == "cancelamento_vas_avulso":
                return {
                    "execution_id": "cancel-valor", "workflow_name": name, "workflow_version": 1, "status": "COMPLETED",
                    "output": {"cancelar_vas_avulso": {
                        "success": True,
                        "results": [{"success": True, "msisdn": "5511999999999", "subject": "Tamboro Mensal",
                                     "service": {"name": "Tamboro Mensal", "details": {"valor": "14,99"}}}],
                        "contestation_candidates": [{"success": True, "msisdn": "5511999999999", "subject": "Tamboro Mensal",
                                                      "service": {"name": "Tamboro Mensal", "details": {"valor": "14,99"}}}],
                    }}, "state": {}, "trace": [],
                }
            return {
                "execution_id": "cont-valor", "workflow_name": name, "workflow_version": 2, "status": "COMPLETED",
                "output": {"registrar_protocolo": {"protocolo_id": "PRT-V"}, "abrir_contestacao_cliente": {"success": True, "items_response": []}},
                "state": {}, "trace": [],
            }

    runtime = Runtime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    monkeypatch.setattr(main, "service", FakeService())
    await main._run_cancelamento_com_contestacao({"msisdn": "5511999999999", "subject": "Tamboro Mensal"})
    item = runtime.calls[1][1]["items"][0]
    assert item["claimedAmount"] == "14,99"
    assert item["validatedAmount"] == "14,99"


@pytest.mark.asyncio
async def test_cancelamento_preserva_valor_informado_e_valor_vas_como_evidencias_distintas(monkeypatch):
    import contas_mcp.servers.contas_mcp_server.main as main

    class Runtime(FakeRuntime):
        async def arun(self, name, payload, execution_id=None):
            self.calls.append((name, payload, execution_id))
            if name == "cancelamento_vas_avulso":
                return {
                    "execution_id": "cancel-div", "workflow_name": name, "workflow_version": 1, "status": "COMPLETED",
                    "output": {"cancelar_vas_avulso": {
                        "success": True,
                        "results": [{"success": True, "msisdn": "5511999999999", "subject": "Tamboro Mensal",
                                     "service": {"name": "Tamboro Mensal", "details": {"valor": "14,99"}}}],
                        "contestation_candidates": [{"success": True, "msisdn": "5511999999999", "subject": "Tamboro Mensal",
                                                      "service": {"name": "Tamboro Mensal", "details": {"valor": "14,99"}}}],
                    }}, "state": {}, "trace": [],
                }
            return {
                "execution_id": "cont-div", "workflow_name": name, "workflow_version": 2, "status": "COMPLETED",
                "output": {"registrar_protocolo": {"protocolo_id": "PRT-D"}, "abrir_contestacao_cliente": {"success": True, "items_response": []}},
                "state": {}, "trace": [],
            }

    runtime = Runtime()
    monkeypatch.setattr(main, "get_workflow_runtime", lambda: runtime)
    monkeypatch.setattr(main, "service", FakeService())
    await main._run_cancelamento_com_contestacao({
        "msisdn": "5511999999999", "subject": "Tamboro Mensal", "valor": "29,98",
    })
    item = runtime.calls[1][1]["items"][0]
    assert item["claimedAmount"] == "29,98"
    assert item["validatedAmount"] == "14,99"
