"""Процесс v2: роутинг запроса и dispatch в workflow."""

from __future__ import annotations

from typing import Any

from app.core.agent.processes.base import AgentProcess, ProcessResult
from app.core.agent.processes.v2.intent_router import V2IntentRouter
from app.core.agent.processes.v2.workflows.doc_explain_api_exposed.workflow_runtime.context import (
    DocExplainApiExposedContext,
)
from app.core.agent.processes.v2.workflows.doc_explain_api_exposed.graph import DocExplainApiExposedGraph
from app.core.agent.processes.v2.workflows.doc_explain_find_files.workflow_runtime.context import DocExplainFindFilesContext
from app.core.agent.processes.v2.workflows.doc_explain_find_files.graph import DocExplainFindFilesGraph
from app.core.agent.processes.v2.workflows.doc_explain_summary.workflow_runtime.context import DocExplainSummaryContext
from app.core.agent.processes.v2.workflows.doc_explain_summary.graph import DocExplainSummaryGraph
from app.core.agent.processes.v2.workflows.doc_update_from_feature.graph import DocUpdateFromFeatureGraph
from app.core.agent.processes.v2.workflows.doc_update_from_feature.workflow_runtime.context import (
    DocUpdateFromFeatureContext,
)
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.graph import DocUpdateFromFeatureV2Graph
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.workflow_runtime.context import (
    DocUpdateFromFeatureV2Context,
)
from app.core.agent.processes.v2.workflows.general_qa_summary.workflow_runtime.context import GeneralQaSummaryContext
from app.core.agent.processes.v2.workflows.general_qa_summary.graph import GeneralQaSummaryGraph
from app.core.agent.utils.llm import AgentLlmService
from app.core.agent.utils.process_v2.anchor_signals import route_anchor_summary
from app.core.agent.utils.process_v2.evidence.assembler import DocsEvidenceAssembler
from app.core.agent.utils.process_v2.evidence.gate import DocsEvidenceGate
from app.core.agent.utils.process_v2.models import V2Domain, V2Intent, V2Subintent
from app.core.agent.utils.process_v2.plan_resolver import RetrievalPlanResolver
from app.core.agent.utils.process_v2.rag_retrieval import V2RagRetrievalAdapter


class V2Process(AgentProcess):
    version = "v2"

    def __init__(
        self,
        llm: AgentLlmService,
        policy_resolver: RetrievalPlanResolver,
        rag_adapter: V2RagRetrievalAdapter,
        evidence_assembler: DocsEvidenceAssembler,
        evidence_gate: DocsEvidenceGate | None = None,
        router: V2IntentRouter | None = None,
        docs_summary_prompt_name: str = "v2_docs_explain.summary_answer",
        general_summary_prompt_name: str = "v2_general.summary_answer",
        workflow_llm_enabled: bool = True,
        doc_rules_enabled: bool = True,
        doc_update_workflow_version: str = "v2",
    ) -> None:
        self._router = router or V2IntentRouter()
        gate = evidence_gate or DocsEvidenceGate()
        self._docs_summary_prompt_name = docs_summary_prompt_name
        self._general_summary_prompt_name = general_summary_prompt_name
        self._workflow_llm_enabled = workflow_llm_enabled
        self._doc_rules_enabled = doc_rules_enabled
        self._doc_update_workflow_version = doc_update_workflow_version.strip().lower() or "v2"
        doc_update_graph = self._build_doc_update_workflow(llm, doc_rules_enabled)
        self._workflows: dict[tuple[str, str, str], Any] = {
            (V2Domain.DOCS, V2Intent.DOC_EXPLAIN, V2Subintent.SUMMARY): DocExplainSummaryGraph(
                llm,
                policy_resolver=policy_resolver,
                rag_adapter=rag_adapter,
                evidence_assembler=evidence_assembler,
                evidence_gate=gate,
            ),
            (V2Domain.DOCS, V2Intent.DOC_EXPLAIN, V2Subintent.FIND_FILES): DocExplainFindFilesGraph(
                policy_resolver=policy_resolver,
                rag_adapter=rag_adapter,
                evidence_assembler=evidence_assembler,
                evidence_gate=gate,
            ),
            (V2Domain.DOCS, V2Intent.DOC_EXPLAIN, V2Subintent.API_EXPOSED): DocExplainApiExposedGraph(
                policy_resolver=policy_resolver,
                rag_adapter=rag_adapter,
            ),
            (V2Domain.DOCS, V2Intent.DOC_UPDATE, V2Subintent.FROM_FEATURE): doc_update_graph,
            (V2Domain.GENERAL, V2Intent.GENERAL_QA, V2Subintent.SUMMARY): GeneralQaSummaryGraph(
                llm,
                policy_resolver=policy_resolver,
                rag_adapter=rag_adapter,
                evidence_assembler=evidence_assembler,
                evidence_gate=gate,
            ),
        }

    async def run(self, context) -> ProcessResult:
        rag_session_id = context.session.active_rag_session_id or ""
        route = self._router.route(context.request.message, rag_session_id=rag_session_id or None)
        context.trace.module("process.v2").log(
            "intent_routed",
            {
                "routing_domain": route.routing_domain,
                "intent": route.intent,
                "subintent": route.subintent,
                "normalized_query": route.normalized_query,
                "target_terms": route.target_terms,
                "anchors": route_anchor_summary(route),
                "confidence": route.confidence,
                "routing_mode": route.routing_mode,
                "llm_router_used": route.llm_router_used,
                "reason_short": route.reason_short,
                "rag_session_id": rag_session_id,
            },
        )
        self._log_step(
            context,
            "router_resolved",
            {
                "domain": route.routing_domain,
                "intent": route.intent,
                "subintent": route.subintent,
                "confidence": route.confidence,
            },
        )
        self._log_step(
            context,
            "anchors_extracted",
            {
                "signal_types": route_anchor_summary(route)["signal_types"],
                "endpoint_paths": route.anchors.endpoint_paths,
                "target_doc_hints": route.anchors.target_doc_hints,
                "matched_aliases": route.anchors.matched_aliases,
                "target_terms": route.target_terms,
            },
        )
        self._log_step(
            context,
            "alias_resolution",
            {
                "resolved_aliases": route.anchors.matched_aliases,
                "target_doc_hints": route.anchors.target_doc_hints,
            },
        )
        flow_context = await self._run_workflow(context, route, rag_session_id)
        if flow_context.answer_generated_payload is not None:
            self._log_step(context, "answer_generated", dict(flow_context.answer_generated_payload))
        changeset = list(getattr(flow_context, "changeset", []) or [])
        apply_changeset = bool(getattr(flow_context, "apply_changeset", False))
        return ProcessResult(
            answer=flow_context.answer,
            changeset=changeset,
            apply_changeset=apply_changeset,
        )

    def _log_step(self, context, step: str, payload: dict[str, object]) -> None:
        context.trace.module("process.v2.pipeline").log(step, payload)

    async def _run_workflow(self, runtime_context, route, rag_session_id: str):
        workflow = self._workflows.get((route.routing_domain, route.intent, route.subintent))
        if workflow is None:
            raise ValueError(f"Unsupported v2 workflow route: {(route.routing_domain, route.intent, route.subintent)!r}")
        if route.intent == V2Intent.GENERAL_QA:
            return await workflow.run(
                GeneralQaSummaryContext(
                    runtime=runtime_context,
                    route=route,
                    rag_session_id=rag_session_id,
                    prompt_name=self._general_summary_prompt_name,
                    workflow_llm_enabled=self._workflow_llm_enabled,
                )
            )
        if route.subintent == V2Subintent.FIND_FILES:
            return await workflow.run(
                DocExplainFindFilesContext(
                    runtime=runtime_context,
                    route=route,
                    rag_session_id=rag_session_id,
                )
            )
        if route.subintent == V2Subintent.API_EXPOSED:
            return await workflow.run(
                DocExplainApiExposedContext(
                    runtime=runtime_context,
                    route=route,
                    rag_session_id=rag_session_id,
                )
            )
        if route.intent == V2Intent.DOC_UPDATE and route.subintent == V2Subintent.FROM_FEATURE:
            if self._doc_update_workflow_version == "legacy":
                return await workflow.run(
                    DocUpdateFromFeatureContext(
                        runtime=runtime_context,
                        route=route,
                        rag_session_id=rag_session_id,
                        doc_rules_enabled=self._doc_rules_enabled,
                    )
                )
            return await workflow.run(
                DocUpdateFromFeatureV2Context(
                    runtime=runtime_context,
                    route=route,
                    rag_session_id=rag_session_id,
                )
            )
        return await workflow.run(
            DocExplainSummaryContext(
                runtime=runtime_context,
                route=route,
                rag_session_id=rag_session_id,
                prompt_name=self._docs_summary_prompt_name,
                workflow_llm_enabled=self._workflow_llm_enabled,
            )
        )

    def _build_doc_update_workflow(self, llm: AgentLlmService, doc_rules_enabled: bool):
        if self._doc_update_workflow_version == "legacy":
            return DocUpdateFromFeatureGraph(llm=llm, doc_rules_enabled=doc_rules_enabled)
        return DocUpdateFromFeatureV2Graph(llm=llm)
