"""Repositorios MongoDB para la carga individual."""

from __future__ import annotations

from typing import Any

from bson import ObjectId

from app.core.logging import InstrumentedMongoCollection, bind_log_context, get_audit_logger
from app.core.mongo_runtime import get_mongo_runtime
from app.individual_ingestion.domain.models import NON_TERMINAL_UPLOAD_STATUSES


class _EphemeralCollection:
    def create_index(self, *args: Any, **kwargs: Any) -> None:
        return None

    def insert_one(self, payload: dict[str, Any]):
        raise RuntimeError("Colección efímera no soporta escrituras persistentes.")

    def update_one(self, *args: Any, **kwargs: Any):
        return None

    def find_one(self, *args: Any, **kwargs: Any):
        return None


def _serialize_document(doc: dict[str, Any] | None) -> dict[str, Any] | None:
    if not doc:
        return None
    serialized = dict(doc)
    if "_id" in serialized:
        serialized["_id"] = str(serialized["_id"])
    return serialized


class MongoIndividualUploadRepository:
    def __init__(self, database: Any | None = None) -> None:
        db = database if database is not None else get_mongo_runtime().sync_database
        collection = None
        if hasattr(db, "__getitem__"):
            try:
                collection = db["individual_ingestion_uploads"]
            except KeyError:
                collection = _EphemeralCollection()
        if collection is None:
            collection = _EphemeralCollection()
        self.collection = InstrumentedMongoCollection(
            collection, service="individual_upload_repository"
        )
        self.audit_logger = get_audit_logger()
        self.ensure_indexes()

    def ensure_indexes(self) -> None:
        self.collection.create_index([("usuario", 1), ("updated_at", -1)])
        self.collection.create_index([("usuario", 1), ("source_file_hash", 1), ("updated_at", -1)])
        self.collection.create_index([("status", 1), ("updated_at", -1)])

    def create_upload(self, payload: dict[str, Any]) -> str:
        inserted = self.collection.insert_one(payload)
        upload_id = str(inserted.inserted_id)
        bind_log_context(file_id=upload_id, username=payload.get("usuario", ""))
        self.audit_logger.business_event(
            event_type="individual.upload_created",
            action="create_upload",
            outcome="success",
            service="individual_upload_repository",
            resource={"upload_id": upload_id, "document_type": payload.get("selected_document_type", "")},
        )
        return upload_id

    def update_upload(self, upload_id: str, payload: dict[str, Any]) -> None:
        if not ObjectId.is_valid(upload_id):
            return
        self.collection.update_one({"_id": ObjectId(upload_id)}, {"$set": payload})

    def get_upload(self, upload_id: str) -> dict[str, Any] | None:
        if not ObjectId.is_valid(upload_id):
            return None
        return _serialize_document(self.collection.find_one({"_id": ObjectId(upload_id)}))

    def find_latest_active(self, username: str) -> dict[str, Any] | None:
        return _serialize_document(
            self.collection.find_one(
                {"usuario": username, "status": {"$in": sorted(NON_TERMINAL_UPLOAD_STATUSES)}},
                sort=[("updated_at", -1)],
            )
        )

    def find_latest_by_hash(self, username: str, source_file_hash: str) -> dict[str, Any] | None:
        if not source_file_hash:
            return None
        return _serialize_document(
            self.collection.find_one(
                {"usuario": username, "source_file_hash": source_file_hash},
                sort=[("updated_at", -1)],
            )
        )
