from app.schemas.steward import StewardRuntimeDecisionRequest
from app.services.steward_runtime_decision_agent import (
    STEWARD_RUNTIME_DECISION_FUNCTION_NAME,
    StewardRuntimeDecisionAgent,
)


class _FakeToolCall:
    def __init__(self, name, arguments):
        self.name = name
        self.arguments = arguments


class _FakeRuntimeResult:
    def __init__(self, tool_call=None):
        self.tool_call = tool_call

    def calls_as_dicts(self):
        return [{"tool": self.tool_call.name if self.tool_call else ""}]


class _FakeRuntime:
    def __init__(self, payload):
        self.payload = payload
        self.last_messages = []
        self.last_tools = []
        self.last_tool_choice = None

    def complete_with_tool_call(self, messages, tools, tool_choice, **kwargs):
        self.last_messages = messages
        self.last_tools = tools
        self.last_tool_choice = tool_choice
        if self.payload is None:
            return _FakeRuntimeResult()
        return _FakeRuntimeResult(_FakeToolCall(STEWARD_RUNTIME_DECISION_FUNCTION_NAME, self.payload))


def test_steward_runtime_decision_uses_function_calling_context():
    runtime = _FakeRuntime(
        {
            "next_action": "submit_current_application",
            "target_task_id": "task-application-beijing",
            "target_message_id": "msg-application-preview",
            "field_key": "",
            "field_value": "",
            "confirmation_required": False,
            "question": "",
            "response_text": "",
            "rationale": "用户确认当前申请核对表无误。",
        }
    )

    result = StewardRuntimeDecisionAgent(runtime).decide(
        StewardRuntimeDecisionRequest(
            user_message="确认",
            runtime_state={
                "waiting_for": "application_submit_confirmation",
                "pending_application": {
                    "message_id": "msg-application-preview",
                    "task_id": "task-application-beijing",
                    "ready_to_submit": True,
                },
                "remaining_tasks": [
                    {"task_id": "task-reimbursement-meal", "task_type": "reimbursement"}
                ],
            },
        )
    )

    assert result.decision_source == "llm_function_call"
    assert result.next_action == "submit_current_application"
    assert result.target_message_id == "msg-application-preview"
    assert result.target_task_id == "task-application-beijing"
    assert runtime.last_tool_choice["function"]["name"] == STEWARD_RUNTIME_DECISION_FUNCTION_NAME
    assert "runtime_state" in runtime.last_messages[-1]["content"]


def test_steward_runtime_decision_fallback_keeps_current_context():
    runtime = _FakeRuntime(None)

    result = StewardRuntimeDecisionAgent(runtime).decide(
        StewardRuntimeDecisionRequest(
            user_message="确认",
            runtime_state={
                "pending_steward_action": {
                    "message_id": "msg-next-task",
                    "target_task_id": "task-reimbursement-meal",
                }
            },
        )
    )

    assert result.decision_source == "rule_fallback"
    assert result.next_action == "continue_next_task"
    assert result.target_message_id == "msg-next-task"
    assert result.target_task_id == "task-reimbursement-meal"


def test_steward_runtime_decision_fallback_reads_persisted_steward_state():
    runtime = _FakeRuntime(None)

    result = StewardRuntimeDecisionAgent(runtime).decide(
        StewardRuntimeDecisionRequest(
            user_message="我坐高铁",
            runtime_state={},
            context_json={
                "conversation_state": {
                    "steward_state": {
                        "active_flow": "travel_application",
                        "flows": {
                            "travel_application": {
                                "flow_id": "travel_application",
                                "intent": "travel_application_create",
                                "fields": {
                                    "expense_type": "travel",
                                    "time_range": "2026-07-02",
                                    "location": "北京",
                                    "reason": "客户现场支撑",
                                },
                                "missing_fields": ["transport_mode"],
                            }
                        },
                    }
                }
            },
        )
    )

    assert result.decision_source == "rule_fallback"
    assert result.next_action == "fill_current_slot"
    assert result.target_task_id == "travel_application"
    assert result.field_key == "transport_mode"
    assert result.field_value == "我坐高铁"
    assert result.steward_state["flows"]["travel_application"]["fields"]["transport_mode"] == "我坐高铁"
    assert result.steward_state["flows"]["travel_application"]["missing_fields"] == []


def test_steward_runtime_decision_fallback_confirms_selected_flow():
    runtime = _FakeRuntime(None)

    result = StewardRuntimeDecisionAgent(runtime).decide(
        StewardRuntimeDecisionRequest(
            user_message="补办出差申请",
            runtime_state={},
            context_json={
                "conversation_state": {
                    "steward_state": {
                        "version": "steward.flow_state.v2",
                        "active_flow": "",
                        "pending_flow_confirmation": {
                            "status": "pending",
                            "source_message": "2月20-23日去上海出差辅助国网仿生产环境部署",
                            "reason": "缺少申请或报销动作词。",
                            "candidate_flows": [
                                {
                                    "flow_id": "travel_application",
                                    "label": "补办出差申请",
                                    "confidence": 0.52,
                                },
                                {
                                    "flow_id": "travel_reimbursement",
                                    "label": "发起费用报销",
                                    "confidence": 0.48,
                                },
                            ],
                        },
                        "flows": {
                            "travel_application": {
                                "flow_id": "travel_application",
                                "intent": "travel_application_create",
                                "status": "pending_flow_confirmation",
                                "fields": {
                                    "time_range": "2026-02-20",
                                    "location": "上海",
                                    "expense_type": "travel",
                                    "reason": "辅助国网仿生产环境部署",
                                },
                                "missing_fields": ["transport_mode"],
                            },
                            "travel_reimbursement": {
                                "flow_id": "travel_reimbursement",
                                "intent": "travel_reimbursement_draft",
                                "status": "pending_flow_confirmation",
                                "fields": {
                                    "time_range": "2026-02-20",
                                    "location": "上海",
                                    "expense_type": "travel",
                                    "reason": "辅助国网仿生产环境部署",
                                },
                                "missing_fields": [],
                            },
                        },
                    }
                }
            },
        )
    )

    assert result.decision_source == "rule_fallback"
    assert result.next_action == "continue_selected_flow"
    assert result.target_task_id == "travel_application"
    assert result.steward_state["active_flow"] == "travel_application"
    assert result.steward_state["pending_flow_confirmation"]["status"] == "confirmed"
    assert result.steward_state["flows"]["travel_application"]["status"] == "collecting"


def test_steward_runtime_decision_fallback_confirms_reimbursement_flow():
    runtime = _FakeRuntime(None)

    result = StewardRuntimeDecisionAgent(runtime).decide(
        StewardRuntimeDecisionRequest(
            user_message="发起费用报销",
            runtime_state={
                "steward_state": {
                    "version": "steward.flow_state.v2",
                    "active_flow": "",
                    "pending_flow_confirmation": {
                        "status": "pending",
                        "candidate_flows": [
                            {"flow_id": "travel_application", "label": "补办出差申请"},
                            {"flow_id": "travel_reimbursement", "label": "发起费用报销"},
                        ],
                    },
                    "flows": {
                        "travel_reimbursement": {
                            "flow_id": "travel_reimbursement",
                            "intent": "travel_reimbursement_draft",
                            "status": "pending_flow_confirmation",
                            "fields": {
                                "time_range": "2026-02-20",
                                "location": "上海",
                                "expense_type": "travel",
                                "reason": "辅助国网仿生产环境部署",
                            },
                            "missing_fields": [],
                        }
                    },
                }
            },
        )
    )

    assert result.decision_source == "rule_fallback"
    assert result.next_action == "continue_selected_flow"
    assert result.target_task_id == "travel_reimbursement"
    assert result.steward_state["active_flow"] == "travel_reimbursement"
    assert result.steward_state["pending_flow_confirmation"]["status"] == "confirmed"
