from __future__ import annotations

from typing import TYPE_CHECKING

from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.steps.step5_execute_subprocesses.path_resolver import (
    DocsPathResolver,
)
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.steps.step5_execute_subprocesses.services import (
    TaskActionResolver,
    TaskAttributeResolver,
)
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.workflow_runtime.context import (
    DocUpdateFromFeatureV2Context,
)
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.workflow_runtime.models import (
    RequirementTaskContext,
)
from app.core.agent.utils.llm import AgentLlmService

if TYPE_CHECKING:
    from app.core.rag.persistence.query_repository import RagQueryRepository


class DocsCatalogLoader:
    def __init__(self, query_repository: "RagQueryRepository | None" = None) -> None:
        self._query_repository = query_repository

    def load(self, context: DocUpdateFromFeatureV2Context) -> None:
        if not context.rag_session_id:
            context.issues.append("Отсутствует active RAG session: fallback по структуре документации будет ограничен.")
            return
        repository = self._query_repository or self._build_repository()
        try:
            context.docs_catalog_rows = repository.list_docs_scope_index_rows(context.rag_session_id)
        except Exception as exc:
            context.issues.append(f"Не удалось загрузить docs catalog rows: {exc}")

    def _build_repository(self) -> "RagQueryRepository":
        from app.core.rag.persistence.query_repository import RagQueryRepository

        self._query_repository = RagQueryRepository()
        return self._query_repository


class RequirementTaskBuilder:
    def __init__(self, llm: AgentLlmService) -> None:
        self._path_resolver = DocsPathResolver()
        self._attribute_resolver = TaskAttributeResolver(llm)
        self._action_resolver = TaskActionResolver(llm)

    def build(self, context: DocUpdateFromFeatureV2Context) -> list[RequirementTaskContext]:
        known_paths = {str(row.get("path") or "") for row in context.docs_catalog_rows}
        tasks: list[RequirementTaskContext] = []
        for index, requirement in enumerate(context.requirements):
            task = RequirementTaskContext(
                index=index,
                section_key=requirement.section_key or f"6.{index + 1}",
                heading=requirement.heading,
                body=requirement.body,
                metadata=dict(requirement.metadata),
            )
            self._attribute_resolver.resolve(context, task, rules_text="")
            task.path = self._path_resolver.resolve(
                application=task.application,
                platform=task.platform,
                doc_type=task.doc_type,
                doc_id=task.doc_id,
                domain=task.domain,
            )
            task.action = self._action_resolver.resolve(task, known_paths)
            known_paths.add(task.path)
            tasks.append(task)
        return tasks


class RequirementTaskOrderer:
    _PLATFORM_PRIORITY = {"pprb": 0, "ufs": 1, "web": 2}

    def order(self, tasks: list[RequirementTaskContext]) -> list[RequirementTaskContext]:
        return sorted(tasks, key=self._sort_key)

    def _sort_key(self, task: RequirementTaskContext) -> tuple[int, int, int]:
        explicit_order = self._explicit_order(task.metadata)
        platform_order = self._PLATFORM_PRIORITY.get(task.platform, len(self._PLATFORM_PRIORITY))
        return explicit_order, platform_order, task.index

    def _explicit_order(self, metadata: dict[str, object]) -> int:
        value = str(metadata.get("build_order") or metadata.get("order") or "").strip()
        return int(value) if value.isdigit() else 1000
