from __future__ import annotations

from dataclasses import dataclass

from app.modules.rag.code_qa_pipeline.evidence_gate import EvidenceGateDecision
from app.modules.rag.intent_router_v2.models import IntentRouterResult


@dataclass(slots=True, frozen=True)
class CodeQaPolicyDecision:
    answer_mode: str
    answer: str = ""
    should_call_llm: bool = True
    branch: str = "normal_answer"
    reason: str = "evidence_sufficient"


class CodeQaAnswerPolicy:
    def decide(
        self,
        *,
        router_result: IntentRouterResult,
        gate_decision: EvidenceGateDecision,
    ) -> CodeQaPolicyDecision:
        sub_intent = router_result.query_plan.sub_intent.upper()
        symbol_resolution = router_result.symbol_resolution
        if sub_intent == "OPEN_FILE" and "path_scope_empty" in gate_decision.failure_reasons:
            path_scope = list(getattr(router_result.retrieval_spec.filters, "path_scope", []) or [])
            target = path_scope[0] if path_scope else "запрошенный файл"
            return CodeQaPolicyDecision(
                answer_mode="not_found",
                answer=f"Файл {target} не найден.",
                should_call_llm=False,
                branch="open_file_not_found",
                reason="path_scope_empty",
            )
        if sub_intent == "EXPLAIN" and symbol_resolution.status in {"not_found", "ambiguous"}:
            return CodeQaPolicyDecision(
                answer_mode="degraded",
                answer=self._symbol_message(symbol_resolution.status, symbol_resolution.alternatives),
                should_call_llm=False,
                branch="explain_unresolved_symbol",
                reason=f"symbol_resolution_{symbol_resolution.status}",
            )
        if not gate_decision.passed:
            answer_mode = "insufficient" if "insufficient_evidence" in gate_decision.failure_reasons else "degraded"
            reason = gate_decision.failure_reasons[0] if gate_decision.failure_reasons else "evidence_gate_failed"
            return CodeQaPolicyDecision(
                answer_mode=answer_mode,
                answer=gate_decision.degraded_message,
                should_call_llm=False,
                branch="evidence_gate_short_circuit",
                reason=reason,
            )
        return CodeQaPolicyDecision(answer_mode="normal", branch="normal_answer", reason="evidence_sufficient")

    def _symbol_message(self, status: str, alternatives: list[str]) -> str:
        if status == "ambiguous" and alternatives:
            return f"Сущность не удалось однозначно разрешить. Близкие варианты: {', '.join(alternatives[:3])}."
        if alternatives:
            return f"Сущность не найдена в доступном коде. Ближайшие варианты: {', '.join(alternatives[:3])}."
        return "Сущность не найдена в доступном коде."
