from __future__ import annotations

from app.core.agent.utils.process_v2.models import V2Intent, V2RouteResult, V2Subintent
from app.core.rag.contracts.enums import RagLayer
from app.core.rag.retrieval.session_retriever import RetrievalPlan


class DocExplainApiExposedRetrievalPolicy:
    _LAYERS = [RagLayer.DOCS_DOCUMENT_CATALOG]
    _API_PREFIXES = ["docs/api/", "docs/endpoints/", "docs/methods/", "api/", "endpoints/", "methods/"]

    def supports(self, route: V2RouteResult) -> bool:
        return route.intent == V2Intent.DOC_EXPLAIN and route.subintent == V2Subintent.API_EXPOSED

    def resolve(self, route: V2RouteResult) -> RetrievalPlan:
        return RetrievalPlan(
            profile="api_exposed",
            layers=list(self._LAYERS),
            limit=400,
            filters=self._filters(route),
        )

    def _filters(self, route: V2RouteResult) -> dict[str, object]:
        query_signals = self._query_signals(route)
        filters: dict[str, object] = {
            "metadata.type": "api_method",
            "prefer_path_prefixes": list(self._API_PREFIXES),
            "target_doc_hints": list(route.anchors.target_doc_hints),
            "prefer_like_patterns": self._like_patterns(route),
        }
        if query_signals:
            filters["query_signals"] = query_signals
        if route.anchors.process_domain:
            filters["metadata.domain"] = route.anchors.process_domain
        if route.anchors.process_subdomain:
            filters["metadata.subdomain"] = route.anchors.process_subdomain
        return filters

    def _like_patterns(self, route: V2RouteResult) -> list[str]:
        raw: list[str] = ["api", "endpoint", "method", "эндпоинт", "метод"]
        raw.extend(route.target_terms)
        raw.extend(route.anchors.endpoint_paths)
        raw.extend(route.anchors.target_doc_hints)
        raw.extend(candidate.value for candidate in route.anchors.candidate_apis)
        return [f"%{item.lower()}%" for item in _unique(raw)]

    def _query_signals(self, route: V2RouteResult) -> list[str]:
        raw: list[str] = []
        raw.extend(route.target_terms)
        raw.extend(route.anchors.endpoint_paths)
        blocked = {"api", "endpoint", "method", "эндпоинт", "метод"}
        return [item for item in _unique(raw) if item.lower() not in blocked]


def _unique(items: list[str]) -> list[str]:
    out: list[str] = []
    seen: set[str] = set()
    for item in items:
        value = str(item or "").strip()
        if not value or value in seen:
            continue
        seen.add(value)
        out.append(value)
    return out
