from app.agents.schemas import AgentEvent, AgentTask, TaskResult
from app.agents.schemas.task import CollaborationBudget, InterruptRecord, RecoveryRecord
from app.agents.state import initial_state
from app.agents.verifier import apply_verification_verdict, normalize_task_result, verify_task_result


def test_agent_task_supports_day3_interrupt_recovery_and_budget_fields():
    interrupt = InterruptRecord(interrupt_id="interrupt-1", reason="user_cancel")
    recovery = RecoveryRecord(recovery_id="recovery-1", source_interrupt_id="interrupt-1", resumed_from_task_id="task-1")
    budget = CollaborationBudget(
        mode="collaboration",
        max_parallel_tasks=3,
        remaining_parallel_tasks=2,
        max_tool_calls=6,
        remaining_tool_calls=4,
        metadata={"phase": "day3"},
    )

    task = AgentTask(
        task_id="task-1",
        title="Recover interrupted collaboration task",
        owner_agent_id="analyst",
        role="analyst",
        parent_task_id="parent-1",
        child_task_ids=["child-1"],
        thread_id="thread-1",
        message_id="message-1",
        message_index=3,
        interrupt_records=[interrupt],
        recovery_records=[recovery],
        collaboration_budget=budget,
    )

    payload = task.model_dump(mode="json")

    assert payload["parent_task_id"] == "parent-1"
    assert payload["child_task_ids"] == ["child-1"]
    assert payload["thread_id"] == "thread-1"
    assert payload["message_id"] == "message-1"
    assert payload["message_index"] == 3
    assert payload["interrupt_records"][0]["interrupt_id"] == "interrupt-1"
    assert payload["recovery_records"][0]["recovery_id"] == "recovery-1"
    assert payload["collaboration_budget"]["mode"] == "collaboration"
    assert payload["collaboration_budget"]["remaining_tool_calls"] == 4


def test_agent_event_supports_day3_thread_interrupt_and_recovery_metadata():
    event = AgentEvent(
        event_id="evt-1",
        event_type="agent.task.recovered",
        conversation_id="conv-1",
        agent_id="executor",
        task_id="task-1",
        parent_task_id="parent-1",
        child_task_id="child-1",
        thread_id="thread-1",
        message_id="message-1",
        interrupt_id="interrupt-1",
        recovery_id="recovery-1",
        severity="warning",
        payload={"status": "resumed"},
    )

    payload = event.model_dump(mode="json")

    assert payload["event_type"] == "agent.task.recovered"
    assert payload["parent_task_id"] == "parent-1"
    assert payload["child_task_id"] == "child-1"
    assert payload["thread_id"] == "thread-1"
    assert payload["message_id"] == "message-1"
    assert payload["interrupt_id"] == "interrupt-1"
    assert payload["recovery_id"] == "recovery-1"
    assert payload["severity"] == "warning"


def test_normalize_task_result_preserves_day3_metadata_fields():
    result = normalize_task_result(
        {
            "task_id": "task-1",
            "status": "completed",
            "summary": "Recovered successfully.",
            "owner_agent_id": "executor",
            "parent_task_id": "parent-1",
            "child_task_ids": ["child-1"],
            "thread_id": "thread-1",
            "message_id": "message-1",
            "message_index": 2,
            "interrupt_records": [{"interrupt_id": "interrupt-1", "reason": "user_pause"}],
            "recovery_records": [{"recovery_id": "recovery-1", "source_interrupt_id": "interrupt-1"}],
            "budget_snapshot": {"mode": "collaboration", "max_parallel_tasks": 4},
            "next_action": "notify_user",
            "output_data": {"ok": True},
        }
    )

    assert result.parent_task_id == "parent-1"
    assert result.child_task_ids == ["child-1"]
    assert result.thread_id == "thread-1"
    assert result.message_id == "message-1"
    assert result.message_index == 2
    assert result.interrupt_records[0].interrupt_id == "interrupt-1"
    assert result.recovery_records[0].recovery_id == "recovery-1"
    assert result.budget_snapshot.mode == "collaboration"
    assert result.budget_snapshot.max_parallel_tasks == 4
    assert result.next_action == "notify_user"
    assert result.output_data == {"ok": True}


def test_apply_verification_verdict_updates_state_with_recovery_evidence():
    state = initial_state("u1", "c1")

    verdict = verify_task_result(
        status="passed",
        summary="Interrupt and recovery chain verified.",
        evidence=[
            {
                "task_id": "task-1",
                "thread_id": "thread-1",
                "interrupt_id": "interrupt-1",
                "recovery_id": "recovery-1",
            }
        ],
    )
    updated_state = apply_verification_verdict(state, verdict)

    assert updated_state["verification_status"] == "passed"
    assert updated_state["verification_summary"] == "Interrupt and recovery chain verified."
    assert updated_state["verification_evidence"] == [
        {
            "task_id": "task-1",
            "thread_id": "thread-1",
            "interrupt_id": "interrupt-1",
            "recovery_id": "recovery-1",
        }
    ]
