from __future__ import annotations

from typing import Any, Protocol

from app.case_epicrisis.domain.curation import CatalogReference, CodeSystem
from app.case_epicrisis.domain.models import (
    EpicrisisEvidenceSnapshot,
    EpicrisisRuleEvaluation,
    EpicrisisSummaryComposition,
    EpicrisisSummarySourceUnit,
)


class CaseDocumentsReader(Protocol):
    def get_case_documents(self, username: str, case_key: str) -> dict[str, Any]: ...


class CaseEpicrisisCacheRepository(Protocol):
    def ensure_indexes(self) -> None: ...

    def get(self, username: str, case_key: str) -> dict[str, Any] | None: ...

    def upsert(
        self,
        *,
        username: str,
        case_key: str,
        context: dict[str, Any],
        regen_requested: bool,
    ) -> None: ...


class EpicrisisCodingGateway(Protocol):
    def build_soat_and_glosa(
        self,
        *,
        historia_html: str | None,
        qx_html: str | None,
    ) -> tuple[list[dict[str, Any]], str]: ...

    def generate_codes_from_descriptions(
        self,
        descriptions: list[dict[str, str]],
    ) -> list[dict[str, Any]]: ...

    def generate_qx_results(
        self,
        *,
        hallazgos: str,
        descripcion_procedimiento: str,
    ) -> list[dict[str, Any]]: ...

    def refresh_diagnostico_context(self, context: dict[str, Any]) -> dict[str, Any]: ...


class EpicrisisPreGenerationRule(Protocol):
    def evaluate(self, snapshot: EpicrisisEvidenceSnapshot) -> EpicrisisRuleEvaluation: ...


class MedicationPertinenceClinicalReviewer(Protocol):
    def review(
        self,
        *,
        medications: list[dict[str, Any]],
        diagnoses: list[dict[str, Any]],
        procedures: list[dict[str, Any]],
    ) -> list[dict[str, Any]]: ...


class EpicrisisSummaryComposer(Protocol):
    def compose(
        self,
        *,
        username: str,
        sources: list[EpicrisisSummarySourceUnit],
    ) -> EpicrisisSummaryComposition: ...


class CodingCatalogRegistry(Protocol):
    def reference(self, system: CodeSystem) -> CatalogReference: ...

    def contains(self, system: CodeSystem, code: str) -> bool: ...

    def description_matches(self, system: CodeSystem, code: str, description: str) -> bool: ...

    def classification(self, system: CodeSystem, code: str) -> str | None: ...

    def references(self) -> list[CatalogReference]: ...
