import pytest

from agent_framework.runtime.agent_runtime import AgentRuntimeMixin
from agent_framework.workflows.models import WorkflowRunResult
import contas_mcp.servers.contas_mcp_server.main as mcp_main


class CapturingWorkflowRuntime:
    def __init__(self, result):
        self.result = result
        self.arun_calls = []
        self.aresume_calls = []

    async def arun(self, name, payload, version=None, execution_id=None):
        self.arun_calls.append({
            "name": name,
            "payload": dict(payload),
            "execution_id": execution_id,
        })
        return self.result

    async def aresume(self, name, execution_id, resume_value, version=None):
        self.aresume_calls.append({
            "name": name,
            "execution_id": execution_id,
            "resume_value": resume_value,
        })
        return self.result


def _result(execution_id="new-exec", name="invoice_explanation", status="COMPLETED"):
    return WorkflowRunResult(
        execution_id=execution_id,
        workflow_name=name,
        workflow_version=1,
        status=status,
        output={},
        state={"current_node": None},
        trace=[],
    )


@pytest.mark.asyncio
async def test_nova_execucao_workflow_ignora_id_residual_da_transacao_anterior(monkeypatch):
    runtime = CapturingWorkflowRuntime(_result())
    monkeypatch.setattr(mcp_main, "get_workflow_runtime", lambda: runtime)

    out = await mcp_main._run_workflow(
        "invoice_explanation",
        {
            "msisdn": "119",
            "workflow_execution_id": "exec-transacao-anterior",
        },
    )

    assert out["execution_id"] == "new-exec"
    assert runtime.arun_calls[0]["execution_id"] is None
    assert "workflow_execution_id" not in runtime.arun_calls[0]["payload"]


@pytest.mark.asyncio
async def test_novo_cancelamento_composto_ignora_workflow_id_residual(monkeypatch):
    runtime = CapturingWorkflowRuntime(
        _result(execution_id="cancel-new", name="cancelamento_vas_avulso", status="FAILED")
    )
    monkeypatch.setattr(mcp_main, "get_workflow_runtime", lambda: runtime)

    out = await mcp_main._run_cancelamento_com_contestacao({
        "msisdn": "119",
        "subject": "TIM Fashion Mensal",
        "workflow_execution_id": "cancel-old",
    })

    assert out["execution_id"] == "cancel-new"
    assert runtime.arun_calls[0]["execution_id"] is None
    assert "workflow_execution_id" not in runtime.arun_calls[0]["payload"]


@pytest.mark.asyncio
async def test_resume_e_unico_caminho_que_reutiliza_execution_id(monkeypatch):
    runtime = CapturingWorkflowRuntime(
        _result(execution_id="exec-paused", name="invoice_explanation", status="COMPLETED")
    )
    monkeypatch.setattr(mcp_main, "get_workflow_runtime", lambda: runtime)

    await mcp_main._invoke(
        "retomar_workflow",
        {
            "workflow_name": "invoice_explanation",
            "execution_id": "exec-paused",
            "resposta_usuario": "sim",
        },
    )

    assert runtime.aresume_calls[0]["execution_id"] == "exec-paused"
    assert runtime.arun_calls == []


class TransactionRuntime(AgentRuntimeMixin):
    pass


def test_nova_transacao_nao_herda_transaction_id_nem_workflow_execution_id_terminal():
    runtime = TransactionRuntime()
    state = {
        "transaction_status": "COMPLETED",
        "active_transaction": {
            "transaction_id": "tx-old",
            "tool_name": "tool-a",
            "arguments": {"workflow_execution_id": "wf-old"},
            "status": "COMPLETED",
        },
        "intent": "new-intent",
    }

    tx = runtime._set_active_transaction(
        state,
        tool_name="tool-a",
        arguments={"subject": "novo", "workflow_execution_id": "wf-old"},
        status="AWAITING_CONFIRMATION",
    )

    assert tx["transaction_id"] != "tx-old"
    assert "workflow_execution_id" not in tx["arguments"]
    assert state["transaction_status"] == "AWAITING_CONFIRMATION"
