from __future__ import annotations

import json

from app.core.agent.processes.v2 import V2IntentRouter


class FakeLlm:
    def __init__(self, response: str, *, fail: bool = False) -> None:
        self.response = response
        self.fail = fail
        self.calls: list[tuple[str, str]] = []

    def generate(self, prompt_name: str, user_input: str, **_kwargs) -> str:
        self.calls.append((prompt_name, user_input))
        if self.fail:
            raise RuntimeError("llm unavailable")
        return self.response


def _llm_response(domain: str, intent: str, subintent: str, *, confidence: float = 0.9, reason: str = "ok") -> str:
    return json.dumps(
        {
            "routing_domain": domain,
            "intent": intent,
            "subintent": subintent,
            "confidence": confidence,
            "reason_short": reason,
        },
        ensure_ascii=False,
    )


def test_router_uses_llm_as_default_selector() -> None:
    llm = FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "FIND_FILES", reason="file request"))

    result = V2IntentRouter(llm=llm).route("В каком файле описан RuntimeHealth?")

    assert result.subintent == "FIND_FILES"
    assert result.routing_mode == "llm_default"
    assert result.llm_router_used is True
    assert result.confidence > 0.8
    assert len(llm.calls) == 1


def test_router_falls_back_when_llm_returns_invalid_enum() -> None:
    llm = FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "MADE_UP"))

    result = V2IntentRouter(llm=llm).route("В каком документе описан runtime health?")

    assert result.routing_domain == "DOCS"
    assert result.subintent == "FIND_FILES"
    assert result.routing_mode == "llm_fallback"
    assert result.llm_router_used is True


def test_router_falls_back_to_general_summary_when_llm_fails() -> None:
    result = V2IntentRouter(llm=FakeLlm("{}", fail=True)).route("Расскажи что важно")

    assert result.subintent == "SUMMARY"
    assert result.routing_mode == "llm_fallback"
    assert result.llm_router_used is True
    assert result.intent == "GENERAL_QA"


def test_router_keeps_endpoint_anchor_and_excludes_it_from_file_names() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "SUMMARY"))).route(
        "Что делает endpoint /send?"
    )

    assert result.anchors.endpoint_paths == ["/send"]
    assert "/send" not in result.anchors.file_names


def test_router_cleans_target_terms_with_lowercase_rules() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "FIND_FILES"))).route(
        "Покажи где описан RuntimeHealth и /health"
    )

    assert "покажи" not in result.target_terms
    assert "где" not in result.target_terms
    assert "runtimehealth" in result.target_terms
    assert "/health" in result.target_terms


def test_router_detects_doc_like_file_names_only() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "FIND_FILES"))).route(
        "Покажи document docs/architecture/overview.md и runtime_health"
    )

    assert "docs/architecture/overview.md" in result.anchors.file_names
    assert "runtime_health" not in result.anchors.file_names


def test_router_reduces_confidence_for_short_vague_query() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("GENERAL", "GENERAL_QA", "SUMMARY", confidence=0.8))).route("Что это?")

    assert result.confidence < 0.8


def test_router_routes_doc_path_to_find_files() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "SUMMARY"))).route("docs/api/health-endpoint.md")

    assert result.subintent == "FIND_FILES"
    assert result.anchors.file_names == ["docs/api/health-endpoint.md"]
    assert result.anchors.endpoint_paths == []


def test_router_routes_file_token_to_find_files() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "SUMMARY"))).route("health-endpoint.md")

    assert result.subintent == "FIND_FILES"
    assert result.anchors.file_names == ["health-endpoint.md"]
    assert result.anchors.endpoint_paths == []


def test_router_promotes_api_method_query_to_endpoint_specific_docs_summary() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "SUMMARY"))).route("Как работает метод health?")

    assert result.intent == "DOC_EXPLAIN"
    assert result.subintent == "SUMMARY"
    assert result.anchors.endpoint_paths == ["/health"]
    assert "docs/api/health-endpoint.md" in result.anchors.target_doc_hints


def test_router_keeps_short_api_like_token_as_strong_hint_without_explicit_path() -> None:
    result = V2IntentRouter(llm=FakeLlm(_llm_response("DOCS", "DOC_EXPLAIN", "SUMMARY"))).route("Что делает health?")

    assert result.intent == "DOC_EXPLAIN"
    assert result.subintent == "SUMMARY"
    assert result.anchors.endpoint_paths == []
    assert "health endpoint" in result.anchors.target_doc_hints
    assert "health" in result.target_terms
