from __future__ import annotations

from datetime import datetime
import hashlib
import json
from typing import Any


class MongoRipsPayloadRepository:
    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), ("version", -1)]
        )
        self.mongo_analyses.collection.create_index(
            [("usuario", 1), ("tipo_documento", 1), ("template_scope_key", 1), ("version", -1)]
        )

    def get_latest(self, username: str, case_key: str) -> dict[str, Any] | None:
        return self.mongo_analyses.collection.find_one(
            {
                "usuario": username,
                "tipo_documento": "rips_case_payload",
                "case_key": case_key,
            },
            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 _build_source_context_fingerprint(self, source_context: dict[str, Any]) -> str:
        serialized = json.dumps(source_context, ensure_ascii=False, sort_keys=True, default=str)
        return hashlib.sha256(serialized.encode("utf-8")).hexdigest()

    def _build_validation_summary(self, validation_report: dict[str, Any]) -> dict[str, Any]:
        findings = validation_report.get("findings") if isinstance(validation_report.get("findings"), list) else []
        reject_count = 0
        notify_count = 0
        for finding in findings:
            if not isinstance(finding, dict):
                continue
            severity = str(finding.get("severity") or "").strip().lower()
            if severity == "reject":
                reject_count += 1
            elif severity == "notify":
                notify_count += 1
        return {
            "status": validation_report.get("status"),
            "ready_for_cuv": bool(validation_report.get("ready_for_cuv")),
            "finding_count": len(findings),
            "reject_count": reject_count,
            "notify_count": notify_count,
        }

    def save_version(
        self,
        *,
        username: str,
        case_key: str,
        payload: dict[str, Any],
        validation_report: dict[str, Any],
        field_trace_map: list[dict[str, Any]],
        source_context: dict[str, Any],
        regen_requested: bool,
    ) -> dict[str, Any]:
        latest = self.get_latest(username, case_key)
        next_version = int(latest.get("version") or 0) + 1 if latest else 1
        source_document_ids = self._build_source_document_ids(source_context)
        validation_summary = self._build_validation_summary(validation_report)
        document = {
            "usuario": username,
            "tipo_documento": "rips_case_payload",
            "case_key": case_key,
            "version": next_version,
            "schema_version": 2,
            "artifact_type": "rips_json",
            "regen_requested": bool(regen_requested),
            "fecha_analisis": datetime.now(self.colombia_tz),
            "payload": payload,
            "validation_report": validation_report,
            "validation_status": validation_summary["status"],
            "ready_for_cuv": validation_summary["ready_for_cuv"],
            "finding_count": validation_summary["finding_count"],
            "reject_count": validation_summary["reject_count"],
            "notify_count": validation_summary["notify_count"],
            "field_trace_map": field_trace_map,
            "field_trace_count": len(field_trace_map),
            "source_document_ids": source_document_ids,
            "source_document_count": len([value for value in source_document_ids.values() if value]),
            "source_context_fingerprint": self._build_source_context_fingerprint(source_context),
            "persistence_metadata": {
                "schema_version": 2,
                "artifact_type": "rips_json",
                "validation_summary": validation_summary,
            },
        }
        self.mongo_analyses.collection.insert_one(document)
        return document

    def get_template(self, username: str, scope_candidates: list[dict[str, Any]]) -> dict[str, Any] | None:
        for candidate in scope_candidates:
            scope_key = str(candidate.get("scope_key") or "").strip()
            if not scope_key:
                continue
            document = self.mongo_analyses.collection.find_one(
                {
                    "usuario": username,
                    "tipo_documento": "rips_operational_template",
                    "template_scope_key": scope_key,
                },
                sort=[("version", -1), ("fecha_analisis", -1)],
            )
            if document:
                return document
        return None

    def save_template(
        self,
        *,
        username: str,
        scope: dict[str, Any],
        options: dict[str, Any],
    ) -> dict[str, Any]:
        scope_key = str(scope.get("scope_key") or "").strip()
        if not scope_key:
            raise ValueError("scope_key es obligatorio para persistir la plantilla operativa RIPS.")

        latest = self.get_template(username, [scope])
        next_version = int(latest.get("version") or 0) + 1 if latest else 1
        document = {
            "usuario": username,
            "tipo_documento": "rips_operational_template",
            "template_scope_key": scope_key,
            "template_scope": scope,
            "version": next_version,
            "fecha_analisis": datetime.now(self.colombia_tz),
            "options": options,
        }
        self.mongo_analyses.collection.insert_one(document)
        return document
