from __future__ import annotations

from types import SimpleNamespace

from app.schemas.steward import StewardActionExecuteRequest, StewardTask
from app.services.steward_query_executors import (
    build_travel_standard_query_steps,
    execute_travel_standard_query,
    resolve_travel_standard_snapshot,
)


def _build_current_user(grade: str = "P5") -> SimpleNamespace:
    return SimpleNamespace(
        username="test_user",
        name="测试员工",
        grade=grade,
        department_name="技术部",
        position="工程师",
        role_codes=["employee"],
        is_admin=False,
        employee_no="E00001",
        manager_name="李总",
    )


def _build_request(
    *,
    location: str = "武汉",
    employee_grade: str = "",
    standard_category: str = "",
    message: str = "我去武汉出差的住宿标准是多少",
) -> StewardActionExecuteRequest:
    ontology_fields: dict[str, str] = {}
    if location:
        ontology_fields["location"] = location
    if employee_grade:
        ontology_fields["employee_grade"] = employee_grade
    if standard_category:
        ontology_fields["standard_category"] = standard_category
    task = StewardTask(
        task_id="task_query_001",
        task_type="query_travel_standard",
        assigned_agent="policy_query_assistant",
        title="差旅标准查询",
        summary=message,
        ontology_fields=ontology_fields,
    )
    return StewardActionExecuteRequest(
        action_type="execute_travel_standard_query",
        message=message,
        task=task,
    )


def test_resolve_travel_standard_snapshot_returns_lodging_and_transport_for_known_city_and_grade():
    snapshot = resolve_travel_standard_snapshot(
        location="武汉",
        employee_grade="P5",
    )
    assert snapshot["location"] == "武汉"
    assert snapshot["city_tier"] == "tier_2"  # 武汉是二类城市
    assert snapshot["employee_grade"] == "P5"
    assert snapshot["lodging"] is not None
    assert snapshot["lodging"]["daily_cap"] == "480.00"  # P5 + tier_2
    assert snapshot["transport"] is not None
    assert snapshot["transport"]["flight_level"] == 1
    assert snapshot["matched_any"] is True


def test_resolve_travel_standard_snapshot_filters_by_standard_category():
    lodging_only = resolve_travel_standard_snapshot(
        location="北京",
        employee_grade="P7",
        standard_category="lodging",
    )
    assert lodging_only["lodging"] is not None
    assert lodging_only["lodging"]["daily_cap"] == "900.00"  # P7 + tier_1
    assert lodging_only["transport"] is None

    transport_only = resolve_travel_standard_snapshot(
        location="北京",
        employee_grade="P7",
        standard_category="transport",
    )
    assert transport_only["transport"] is not None
    assert transport_only["transport"]["flight_level"] == 3  # P7 飞机等级
    assert transport_only["lodging"] is None


def test_resolve_travel_standard_snapshot_normalizes_grade_variants():
    # "p5" 小写、未标准化写法应被归一为 "P5"
    snapshot = resolve_travel_standard_snapshot(
        location="武汉",
        employee_grade="p5",
    )
    assert snapshot["employee_grade"] == "P5"
    assert snapshot["lodging"]["daily_cap"] == "480.00"


def test_resolve_travel_standard_snapshot_handles_unknown_grade():
    snapshot = resolve_travel_standard_snapshot(
        location="武汉",
        employee_grade="",
    )
    # 无职级时无法匹配住宿标准(需要职级档位);补助为占位说明,不计入 matched_any
    assert snapshot["lodging"] is None
    assert snapshot["matched_any"] is False
    assert snapshot["allowance"] is not None  # 仍返回占位说明


def test_execute_travel_standard_query_returns_succeeded_with_answer_markdown():
    request = _build_request(location="武汉", employee_grade="P5")
    response = execute_travel_standard_query(
        executor=None,
        request=request,
        current_user=_build_current_user("P5"),
        trace=[],
    )
    assert response.status == "succeeded"
    assert response.action_type == "execute_travel_standard_query"
    assert "差旅标准查询结果" in response.message
    assert "480.00" in response.message  # 住宿标准
    assert response.result_payload["matched"] is True
    assert response.result_payload["standards"]["lodging"]["daily_cap"] == "480.00"


def test_execute_travel_standard_query_falls_back_to_current_user_grade_when_field_missing():
    request = _build_request(location="武汉", employee_grade="")
    response = execute_travel_standard_query(
        executor=None,
        request=request,
        current_user=_build_current_user("P5"),
        trace=[],
    )
    assert response.status == "succeeded"
    # 应回退到 current_user.grade = P5
    assert response.result_payload["standards"]["employee_grade"] == "P5"


def test_execute_travel_standard_query_returns_no_match_when_grade_and_city_unknown():
    request = _build_request(
        location="未知城市",
        employee_grade="",
        message="查差旅标准",
    )
    # ontology_fields 也没有 grade,current_user 也没有
    response = execute_travel_standard_query(
        executor=None,
        request=request,
        current_user=_build_current_user(""),
        trace=[],
    )
    assert response.status == "succeeded"
    assert response.result_payload["matched"] is False
    assert "未能匹配" in response.message


def test_build_travel_standard_query_steps_generates_single_executable_step():
    task = StewardTask(
        task_id="task_query_001",
        task_type="query_travel_standard",
        assigned_agent="policy_query_assistant",
        title="差旅标准查询",
        summary="查武汉住宿标准",
        ontology_fields={"location": "武汉", "employee_grade": "P5"},
    )
    steps = build_travel_standard_query_steps(task)
    assert len(steps) == 1
    assert steps[0].action_type == "execute_travel_standard_query"
    assert steps[0].requires_confirmation is False
    assert steps[0].payload["ontology_fields"]["location"] == "武汉"
