from __future__ import annotations

from datetime import datetime
from typing import Any

from app.rda.domain.models import RdaArtifactType


class MongoRdaArtifactRepository:
    def __init__(self, mongo_analyses: Any, colombia_tz: Any):
        self.mongo_analyses = mongo_analyses
        self.colombia_tz = colombia_tz

    def ensure_indexes(self) -> None:
        self.mongo_analyses.collection.create_index(
            [("usuario", 1), ("tipo_documento", 1), ("case_key", 1), ("artifact_type", 1), ("version", -1)]
        )

    def get_latest(
        self, username: str, case_key: str, artifact_type: RdaArtifactType
    ) -> dict[str, Any] | None:
        return self.mongo_analyses.collection.find_one(
            {
                "usuario": username,
                "tipo_documento": "rda_case_artifact",
                "case_key": case_key,
                "artifact_type": artifact_type.value,
            },
            sort=[("version", -1), ("fecha_analisis", -1)],
        )

    def _build_source_document_ids(self, source_context: dict[str, Any]) -> dict[str, Any]:
        return {
            "historia_id": (source_context.get("historia") or {}).get("_id"),
            "quirurgico_id": (source_context.get("quirurgico") or {}).get("_id"),
            "factura_id": (source_context.get("factura") or {}).get("_id"),
        }

    def save_version(
        self,
        *,
        username: str,
        case_key: str,
        artifact_type: RdaArtifactType,
        payload: dict[str, Any],
        completeness_status: str,
        missing_fields: list[str],
        section_trace: list[dict[str, Any]],
        source_context: dict[str, Any],
        source_context_fingerprint: str,
        schema_version: int,
        mapper_version: str,
        regen_requested: bool,
    ) -> dict[str, Any]:
        latest = self.get_latest(username, case_key, artifact_type)
        next_version = int(latest.get("version") or 0) + 1 if latest else 1
        source_document_ids = self._build_source_document_ids(source_context)
        document = {
            "usuario": username,
            "tipo_documento": "rda_case_artifact",
            "case_key": case_key,
            "artifact_type": artifact_type.value,
            "version": next_version,
            "schema_version": schema_version,
            "mapper_version": mapper_version,
            "fecha_analisis": datetime.now(self.colombia_tz),
            "payload": payload,
            "completeness_status": completeness_status,
            "missing_fields": missing_fields,
            "missing_field_count": len(missing_fields),
            "section_trace": section_trace,
            "section_trace_count": len(section_trace),
            "source_document_ids": source_document_ids,
            "source_document_count": len([value for value in source_document_ids.values() if value]),
            "source_context_fingerprint": source_context_fingerprint,
            "regen_requested": bool(regen_requested),
            "persistence_metadata": {
                "schema_version": schema_version,
                "mapper_version": mapper_version,
                "artifact_type": artifact_type.value,
            },
        }
        self.mongo_analyses.collection.insert_one(document)
        return document


class MongoRdaJobStatusRepository:
    def __init__(self, mongo_analyses: Any, colombia_tz: Any):
        self.mongo_analyses = mongo_analyses
        self.colombia_tz = colombia_tz

    def ensure_indexes(self) -> None:
        self.mongo_analyses.collection.create_index(
            [("usuario", 1), ("tipo_documento", 1), ("case_key", 1), ("artifact_type", 1)]
        )

    def get_status(
        self, username: str, case_key: str, artifact_type: RdaArtifactType
    ) -> dict[str, Any] | None:
        return self.mongo_analyses.collection.find_one(
            {
                "usuario": username,
                "tipo_documento": "rda_case_job_status",
                "case_key": case_key,
                "artifact_type": artifact_type.value,
            }
        )

    def upsert_status(
        self,
        *,
        username: str,
        case_key: str,
        artifact_type: RdaArtifactType,
        status: str,
        job_id: str,
        error: str | None = None,
        source_context_fingerprint: str | None = None,
        resolved_version: int | None = None,
        reused: bool = False,
    ) -> dict[str, Any]:
        document = {
            "usuario": username,
            "tipo_documento": "rda_case_job_status",
            "case_key": case_key,
            "artifact_type": artifact_type.value,
            "status": status,
            "job_id": job_id,
            "error": error or "",
            "source_context_fingerprint": source_context_fingerprint or "",
            "resolved_version": resolved_version,
            "reused": bool(reused),
            "updated_at": datetime.now(self.colombia_tz),
        }
        self.mongo_analyses.collection.update_one(
            {
                "usuario": username,
                "tipo_documento": "rda_case_job_status",
                "case_key": case_key,
                "artifact_type": artifact_type.value,
            },
            {"$set": document},
            upsert=True,
        )
        return self.get_status(username, case_key, artifact_type) or document
