"""Diagnosis repository for database operations on diagnoses."""
from datetime import UTC, datetime
from typing import Optional

from bson import ObjectId
from pymongo import ReturnDocument

from app.db import Database
from app.models.diagnosis import Diagnosis

COL = "diagnoses"

def create(diagnosis: Diagnosis) -> Diagnosis:
    """Create a new diagnosis record in the database."""
    now = datetime.now(UTC)
    diagnosis_to_insert = diagnosis.model_copy(
        update={"created_at": now, "updated_at": now}
    ).to_bson()
    res = Database.get_db().get_collection(COL).insert_one(diagnosis_to_insert)
    return Diagnosis.from_bson({**diagnosis_to_insert, "_id": res.inserted_id})

def find_by_patient_id(patient_id: str) -> list[Diagnosis]:
    """Find all diagnoses for a patient."""
    if not ObjectId.is_valid(patient_id):
        raise ValueError("Invalid patient ID")
    docs = Database.get_db().get_collection(COL).find({"patientId": ObjectId(patient_id)})
    return [Diagnosis.from_bson(doc) for doc in docs]


def find_by_id(diagnosis_id: str) -> Optional[Diagnosis]:
    """Find a diagnosis record by its ID."""
    if not ObjectId.is_valid(diagnosis_id):
        return None
    doc = Database.get_db().get_collection(COL).find_one({"_id": ObjectId(diagnosis_id)})
    return Diagnosis.from_bson(doc) if doc else None

def update(diagnosis_id: str, updates: dict) -> Optional[Diagnosis]:
    """Update a diagnosis record."""
    if not ObjectId.is_valid(diagnosis_id):
        raise ValueError("Invalid diagnosis ID")
    db = Database.get_db()
    existing = db.get_collection(COL).find_one({"_id": ObjectId(diagnosis_id)})
    if not existing:
        return None

    # Merge existing document with updates, validate via model,
    # and ensure updated_at is refreshed.
    merged = {**existing, **updates}
    candidate = Diagnosis.from_bson(merged).model_copy(update={"updated_at": datetime.now(UTC)})
    to_set = candidate.to_bson()
    to_set.pop("_id", None)

    doc = db.get_collection(COL).find_one_and_update(
        {"_id": ObjectId(diagnosis_id)},
        {"$set": to_set},
        return_document=ReturnDocument.AFTER,
    )
    return Diagnosis.from_bson(doc) if doc else None

def delete(diagnosis_id: str) -> bool:
    """Delete a diagnosis record."""
    if not ObjectId.is_valid(diagnosis_id):
        return False
    res = Database.get_db().get_collection(COL).delete_one({"_id": ObjectId(diagnosis_id)})
    return res.deleted_count > 0
