from __future__ import annotations

import unittest

from app.plugins.base import PluginRegistry
from app.schemas.chat import ChatRequest
from app.schemas.debug import IntentCandidate, MatcherStageDebug, RoutingDebug
from app.schemas.intent import IntentDefinition
from app.services.agent_service import AgentService
from app.services.intent_registry import IntentRegistry
from app.services.planner import PlanningResult
from app.services.session_store import InMemorySessionStore


class _RouteToCloudRouter:
    def route(self, text: str):
        _ = text
        return type(
            "RouteResult",
            (),
            {
                "intent": None,
                "debug": RoutingDebug(
                    selected_intent="cabin_nav_to",
                    matched_stage="fusion",
                    decision="route_to_cloud",
                    decision_reason="local signal is not stable enough, routing to cloud planner",
                    confidence_grade="low",
                    stages=[
                        MatcherStageDebug(
                            stage="fusion",
                            accepted=False,
                            selected_intent="cabin_nav_to",
                            score=0.88,
                            reason="route to cloud",
                            candidates=[
                                IntentCandidate(intent_id="cabin_nav_to", score=0.88, reason="fusion", model_name="fusion"),
                                IntentCandidate(intent_id="cabin_play_music", score=0.75, reason="fusion", model_name="fusion"),
                            ],
                        )
                    ],
                ),
            },
        )()

    def extract_slots(self, text: str, intent: IntentDefinition) -> dict[str, object]:
        _ = (text, intent)
        return {}


class _PlannerRejects:
    def plan(self, text: str, intents: list[IntentDefinition], context: dict[str, object] | None = None) -> PlanningResult:
        _ = (text, intents, context)
        return PlanningResult(
            accepted=False,
            workflow_type="single",
            model_name="qwen3.5-plus",
            backend="dashscope",
            reason="cloud planner could not produce a stable executable step",
        )


class _PlannerOutOfScope:
    def plan(self, text: str, intents: list[IntentDefinition], context: dict[str, object] | None = None) -> PlanningResult:
        _ = (text, intents, context)
        return PlanningResult(
            accepted=False,
            workflow_type="single",
            model_name="qwen3.5-plus",
            backend="dashscope",
            reason="The provided intent catalog only contains cabin and service actions. There is no matching intent for ordering food via a third-party app action.",
        )


def _intent(intent_id: str) -> IntentDefinition:
    return IntentDefinition(
        intent_id=intent_id,
        plugin_id=f"mock.{intent_id}",
        domain="cabin",
        keywords=[],
        examples=[],
    )


class AgentCloudRouteTests(unittest.TestCase):
    def test_route_to_cloud_returns_explicit_clarify_feedback_when_planner_does_not_accept(self) -> None:
        service = AgentService(
            intent_registry=IntentRegistry([_intent("cabin_nav_to"), _intent("cabin_play_music")]),
            router=_RouteToCloudRouter(),
            plugins=PluginRegistry(),
            session_store=InMemorySessionStore(),
            planner=_PlannerRejects(),
        )

        response = service.handle_chat(
            ChatRequest(
                session_id="sess_cloud_route",
                user_id="user_1",
                input_text="带我过去",
            )
        )

        self.assertEqual(response.decision, "route_to_cloud")
        self.assertEqual(response.reply_type, "clarify")
        self.assertEqual(response.status, "route_to_cloud")
        self.assertIn("请确认一下", response.reply_text)

    def test_route_to_cloud_rejects_when_planner_marks_request_out_of_scope(self) -> None:
        service = AgentService(
            intent_registry=IntentRegistry([_intent("cabin_nav_to"), _intent("cabin_play_music")]),
            router=_RouteToCloudRouter(),
            plugins=PluginRegistry(),
            session_store=InMemorySessionStore(),
            planner=_PlannerOutOfScope(),
        )

        response = service.handle_chat(
            ChatRequest(
                session_id="sess_cloud_route_reject",
                user_id="user_1",
                input_text="去美团叫个外卖",
            )
        )

        self.assertEqual(response.reply_type, "reject")
        self.assertEqual(response.decision, "reject")
        self.assertEqual(response.status, "rejected")
        self.assertIn("做不了", response.reply_text)


if __name__ == "__main__":
    unittest.main()
