from __future__ import annotations

from app.modules.agent.runtime.docs_qa_pipeline.doc_identity import DocsCanonicalDocIdResolver


class DocsAnchorSelector:
    def __init__(self, resolver: DocsCanonicalDocIdResolver | None = None) -> None:
        self._resolver = resolver or DocsCanonicalDocIdResolver()

    def select(self, *, sub_intent: str, anchor_type: str, anchor_value: str | None, rows: list[dict]) -> dict[str, object]:
        if sub_intent != "RELATED_DOCS_EXPLAIN":
            return {"anchor_candidates": [], "selected_anchor": None, "anchor_selection_reason": "", "anchor_match_type": ""}
        scored = self._scored_candidates(anchor_type=anchor_type, anchor_value=anchor_value, rows=rows)
        if not scored:
            return {"anchor_candidates": [], "selected_anchor": None, "anchor_selection_reason": "", "anchor_match_type": ""}
        selected = scored[0]
        return {
            "anchor_candidates": [item["doc_id"] for item in scored],
            "selected_anchor": selected["doc_id"],
            "anchor_selection_reason": selected["reason"],
            "anchor_match_type": selected["match_type"],
        }

    def _scored_candidates(self, *, anchor_type: str, anchor_value: str | None, rows: list[dict]) -> list[dict[str, object]]:
        value = str(anchor_value or "").strip().lower()
        endpoint_slug = value.strip("/").replace("/", "_").replace("-", "_")
        scored: list[dict[str, object]] = []
        for row in rows:
            metadata = dict(row.get("metadata") or {})
            for doc_id in self._resolver.candidates(row):
                score = 0
                match_type = "semantic_fallback"
                reason = "relation_neighbor"
                if anchor_type == "endpoint" and value:
                    if str(metadata.get("endpoint") or "").strip().lower() == value:
                        score, match_type, reason = 100, "exact_path", "metadata.endpoint exact match"
                    elif endpoint_slug and endpoint_slug in doc_id.lower():
                        score, match_type, reason = 90, "exact_path", "doc_id matches requested endpoint slug"
                    elif endpoint_slug and endpoint_slug in str(row.get("path") or "").lower().replace("-", "_"):
                        score, match_type, reason = 85, "exact_path", "path matches requested endpoint slug"
                elif anchor_type == "entity" and value:
                    entity_value = str(metadata.get("entity") or "").strip().lower()
                    if entity_value == value:
                        score, match_type, reason = 100, "exact_entity", "metadata.entity exact match"
                    elif value in doc_id.lower():
                        score, match_type, reason = 90, "exact_title", "doc_id matches requested entity"
                if score == 0:
                    score = 40 if str(row.get("layer") or "") == "D5_RELATION_GRAPH" else 20
                scored.append({"doc_id": doc_id, "score": score, "match_type": match_type, "reason": reason})
        unique: dict[str, dict[str, object]] = {}
        for item in scored:
            doc_id = str(item["doc_id"])
            current = unique.get(doc_id)
            if current is None or int(item["score"]) > int(current["score"]):
                unique[doc_id] = item
        return sorted(unique.values(), key=lambda item: (-int(item["score"]), str(item["doc_id"])))
