"""
Laboratory repository for database operations on Lab entities.
"""

from datetime import UTC, datetime
from uuid import UUID

from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.lab import Lab
from app.schemas.lab import LabCreate, LabUpdate


class LabRepository:
    """Repository handling database queries and persistence for Lab records."""

    async def get_by_id(self, db: AsyncSession, lab_id: UUID) -> Lab | None:
        """Fetch active lab by ID."""
        stmt = select(Lab).where(Lab.id == lab_id, Lab.deleted_at.is_(None))
        res = await db.execute(stmt)
        return res.scalars().first()

    async def get_default_lab_id(self, db: AsyncSession) -> UUID:
        """Fetch the default primary lab branch ID or create one if none exists."""
        stmt = select(Lab.id).where(Lab.deleted_at.is_(None)).limit(1)
        res = await db.execute(stmt)
        lab_id = res.scalar()
        if not lab_id:
            lab = Lab(name="Munal Central Lab", address="Kathmandu, Nepal")
            db.add(lab)
            await db.flush()
            await db.refresh(lab)
            return lab.id
        return lab_id

    async def list_labs(self, db: AsyncSession, limit: int = 50, offset: int = 0) -> tuple[list[Lab], int]:
        """Fetch paginated active labs with total count."""
        count_stmt = select(func.count()).select_from(Lab).where(Lab.deleted_at.is_(None))
        total: int = (await db.execute(count_stmt)).scalar_one()

        data_stmt = (
            select(Lab)
            .where(Lab.deleted_at.is_(None))
            .order_by(Lab.created_at.desc())
            .offset(offset)
            .limit(limit)
        )
        res = await db.execute(data_stmt)
        return list(res.scalars().all()), total

    async def create(self, db: AsyncSession, data: LabCreate) -> Lab:
        """Persist a new laboratory."""
        lab = Lab(
            name=data.name,
            address=data.address,
            logo_url=data.logo_url,
        )
        db.add(lab)
        await db.flush()
        await db.refresh(lab)
        return lab

    async def update(self, db: AsyncSession, lab: Lab, data: LabUpdate) -> Lab:
        """Update fields of an existing laboratory."""
        if data.name is not None:
            lab.name = data.name
        if data.address is not None:
            lab.address = data.address
        if data.logo_url is not None:
            lab.logo_url = data.logo_url

        await db.flush()
        await db.refresh(lab)
        return lab

    async def delete(self, db: AsyncSession, lab: Lab) -> None:
        """Soft-delete a laboratory record."""
        lab.deleted_at = datetime.now(UTC)
        await db.flush()
