from __future__ import annotations

from typing import Any

from app.case_epicrisis.application.rules import HistoriaClinicaRequiredRule
from app.case_epicrisis.application.use_cases import (
    BuildCaseEpicrisisContextUseCase,
    EvaluateEpicrisisRulesUseCase,
    GetCaseEpicrisisContextUseCase,
    UpdateCaseEpicrisisDraftUseCase,
)
from app.case_epicrisis.application.utils import normalize_context_payload
from app.case_epicrisis.infrastructure.gateways import (
    ServicesEpicrisisCodingGateway,
)
from app.case_epicrisis.infrastructure.repositories import (
    MongoCaseDocumentsReader,
    MongoCaseEpicrisisCacheRepository,
)
from app.core.logging import bind_log_context, get_audit_logger


class CaseEpicrisisService:
    """Fachada compatible mientras la lógica migra al módulo hexagonal."""

    def __init__(
        self,
        *,
        mongo_analyses: Any,
        client_groq: Any,
        client_gemini: Any = None,
        soat_retriever: Any = None,
        cie10_retriever: Any = None,
        llm_router: Any = None,
        colombia_tz: Any,
        llm_task_cache_repository: Any = None,
    ):
        self.audit_logger = get_audit_logger()
        self.documents_reader = MongoCaseDocumentsReader(mongo_analyses)
        self.cache_repository = MongoCaseEpicrisisCacheRepository(mongo_analyses, colombia_tz)
        self.coding_gateway = ServicesEpicrisisCodingGateway(
            client_groq=client_groq,
            client_gemini=client_gemini,
            soat_retriever=soat_retriever,
            cie10_retriever=cie10_retriever,
            llm_router=llm_router,
            llm_task_cache_repository=llm_task_cache_repository,
        )
        self.rules_evaluator = EvaluateEpicrisisRulesUseCase(rules=[HistoriaClinicaRequiredRule()])
        self.build_case_context_use_case = BuildCaseEpicrisisContextUseCase(
            documents_reader=self.documents_reader,
            coding_gateway=self.coding_gateway,
            rules_evaluator=self.rules_evaluator,
        )
        self.get_case_context_use_case = GetCaseEpicrisisContextUseCase(
            cache_repository=self.cache_repository,
            build_case_context_use_case=self.build_case_context_use_case,
        )
        self.update_case_draft_use_case = UpdateCaseEpicrisisDraftUseCase(
            cache_repository=self.cache_repository,
            get_case_context_use_case=self.get_case_context_use_case,
        )

    def ensure_indexes(self) -> None:
        self.cache_repository.ensure_indexes()

    def build_case_context(self, username: str, case_key: str) -> dict[str, Any]:
        bind_log_context(username=username, case_key=case_key, document_type="epicrisis")
        existing = self.cache_repository.get(username, case_key)
        preserved_context = existing.get("contexto") if existing else None
        context = self.build_case_context_use_case.execute(
            username,
            case_key,
            preserved_context=preserved_context,
        )
        self.audit_logger.business_event(
            event_type="epicrisis.generated",
            action="build_case_context",
            outcome="success",
            service="case_epicrisis_service",
            resource={"case_key": case_key},
        )
        return context

    def get_cached_case_context(self, username: str, case_key: str) -> dict[str, Any] | None:
        bind_log_context(username=username, case_key=case_key, document_type="epicrisis")
        cache_doc = self.cache_repository.get(username, case_key)
        if not cache_doc or not isinstance(cache_doc.get("contexto"), dict):
            return cache_doc
        normalized_doc = dict(cache_doc)
        normalized_doc["contexto"] = normalize_context_payload(cache_doc["contexto"])
        return normalized_doc

    def cache_case_context(
        self,
        username: str,
        case_key: str,
        *,
        regen: bool = False,
    ) -> dict[str, Any]:
        bind_log_context(username=username, case_key=case_key, document_type="epicrisis")
        context = self.get_case_context_use_case.execute(
            username,
            case_key,
            regen=regen,
        )
        self.audit_logger.business_event(
            event_type="epicrisis.cache_refresh" if regen else "epicrisis.generated",
            action="cache_case_context",
            outcome="success",
            service="case_epicrisis_service",
            resource={"case_key": case_key, "regen": bool(regen)},
        )
        return context

    def update_case_draft(
        self,
        username: str,
        case_key: str,
        *,
        payload: dict[str, Any],
    ) -> dict[str, Any]:
        bind_log_context(username=username, case_key=case_key, document_type="epicrisis")
        result = self.update_case_draft_use_case.execute(
            username,
            case_key,
            payload=payload,
        )
        self.audit_logger.business_event(
            event_type="epicrisis.draft_updated",
            action="update_case_draft",
            outcome="success",
            service="case_epicrisis_service",
            resource={"case_key": case_key},
        )
        return result
