from __future__ import annotations

from app.core.agent.processes.v2.intent_router.models import QueryFeatures
from app.core.agent.utils.process_v2.models import V2Domain, V2Intent, V2RouteResult, V2ScopeType, V2Subintent


class V2FallbackRouter:
    def route_without_deterministic_signals(
        self,
        *,
        user_query: str,
        features: QueryFeatures,
        anchors,
        scope_type: str = V2ScopeType.UNKNOWN,
    ) -> V2RouteResult:
        return V2RouteResult(
            routing_domain=V2Domain.GENERAL,
            intent=V2Intent.GENERAL_QA,
            subintent=V2Subintent.SUMMARY,
            user_query=user_query,
            normalized_query=features.normalized_query,
            target_terms=features.target_terms,
            anchors=anchors,
            confidence=0.0,
            routing_mode="llm_fallback",
            llm_router_used=True,
            reason_short="llm route unresolved",
            scope_type=scope_type,
        )

    def route(
        self,
        *,
        user_query: str,
        features: QueryFeatures,
        anchors,
        llm_attempted: bool,
        scope_type: str = V2ScopeType.UNKNOWN,
    ) -> V2RouteResult:
        if features.file_markers:
            return self._build_docs_result(
                user_query=user_query,
                features=features,
                anchors=anchors,
                subintent=V2Subintent.FIND_FILES,
                llm_attempted=llm_attempted,
                reason="fallback file markers",
                scope_type=scope_type,
            )
        if self._has_docs_update_signal(features):
            return V2RouteResult(
                routing_domain=V2Domain.DOCS,
                intent=V2Intent.DOC_UPDATE,
                subintent=V2Subintent.FROM_FEATURE,
                user_query=user_query,
                normalized_query=features.normalized_query,
                target_terms=features.target_terms,
                anchors=anchors,
                confidence=0.0,
                routing_mode=self._routing_mode(llm_attempted),
                llm_router_used=llm_attempted,
                reason_short="fallback docs update from feature",
                scope_type=scope_type,
            )
        if self._has_api_exposed_signal(features):
            return self._build_docs_result(
                user_query=user_query,
                features=features,
                anchors=anchors,
                subintent=V2Subintent.API_EXPOSED,
                llm_attempted=llm_attempted,
                reason="fallback docs api exposed",
                scope_type=scope_type,
            )
        if self._has_docs_signal(features):
            return self._build_docs_result(
                user_query=user_query,
                features=features,
                anchors=anchors,
                subintent=V2Subintent.SUMMARY,
                llm_attempted=llm_attempted,
                reason="fallback docs summary",
                scope_type=scope_type,
            )
        return V2RouteResult(
            routing_domain=V2Domain.GENERAL,
            intent=V2Intent.GENERAL_QA,
            subintent=V2Subintent.SUMMARY,
            user_query=user_query,
            normalized_query=features.normalized_query,
            target_terms=features.target_terms,
            anchors=anchors,
            confidence=0.0,
            routing_mode=self._routing_mode(llm_attempted),
            llm_router_used=llm_attempted,
            reason_short="fallback general summary",
            scope_type=scope_type,
        )

    def _build_docs_result(
        self,
        *,
        user_query: str,
        features: QueryFeatures,
        anchors,
        subintent: str,
        llm_attempted: bool,
        reason: str,
        scope_type: str = V2ScopeType.UNKNOWN,
    ) -> V2RouteResult:
        return V2RouteResult(
            routing_domain=V2Domain.DOCS,
            intent=V2Intent.DOC_EXPLAIN,
            subintent=subintent,
            user_query=user_query,
            normalized_query=features.normalized_query,
            target_terms=features.target_terms,
            anchors=anchors,
            confidence=0.0,
            routing_mode=self._routing_mode(llm_attempted),
            llm_router_used=llm_attempted,
            reason_short=reason,
            scope_type=scope_type,
        )

    def _has_docs_signal(self, features: QueryFeatures) -> bool:
        return any(
            (
                features.endpoint_paths,
                features.target_doc_hints,
                features.endpoint_markers,
                features.architecture_markers,
                features.logic_markers,
                features.domain_markers,
                features.matched_aliases,
            )
        )

    def _has_api_exposed_signal(self, features: QueryFeatures) -> bool:
        query = features.normalized_query.lower()
        has_api = any(marker in query for marker in ("api", "эндпоинт", "endpoint", "роут", "route", "метод"))
        has_listing = any(marker in query for marker in ("какие", "список", "перечисли", "все", "available", "list"))
        return has_api and has_listing and not features.endpoint_paths and not features.file_markers

    def _has_docs_update_signal(self, features: QueryFeatures) -> bool:
        query = features.normalized_query.lower()
        has_update = any(
            marker in query
            for marker in (
                "обнов",
                "измен",
                "внести правк",
                "docs update",
                "update documentation",
                "документац",
            )
        )
        has_feature = any(
            marker in query
            for marker in ("системной аналитик", "feature", ".md", "confluence", "from feature")
        )
        return has_update and has_feature

    def _routing_mode(self, llm_attempted: bool) -> str:
        return "llm_fallback" if llm_attempted else "deterministic_fallback"
