"""
Laboratory business logic service.
"""

import math
from uuid import UUID

from sqlalchemy.ext.asyncio import AsyncSession

from app.core.exceptions import NotFoundException
from app.core.pagination import PaginationParams
from app.core.responses import PaginatedResponse, PaginationMeta
from app.repositories.lab_repository import LabRepository
from app.schemas.lab import LabCreate, LabResponse, LabUpdate


class LabService:
    """Service handling business logic for Laboratory management."""

    def __init__(self, repository: LabRepository | None = None) -> None:
        self.repo = repository or LabRepository()

    async def get_lab(self, db: AsyncSession, lab_id: UUID) -> LabResponse:
        """Retrieve a laboratory by ID or raise NotFoundException."""
        lab = await self.repo.get_by_id(db, lab_id)
        if not lab:
            raise NotFoundException(message=f"Laboratory with id '{lab_id}' was not found.")
        return LabResponse.model_validate(lab)

    async def list_labs(self, db: AsyncSession, params: PaginationParams) -> PaginatedResponse[LabResponse]:
        """Retrieve paginated active laboratories."""
        items, total = await self.repo.list_labs(db, limit=params.limit, offset=params.offset)
        pages = math.ceil(total / params.limit) if total > 0 else 1
        return PaginatedResponse(
            data=[LabResponse.model_validate(lab) for lab in items],
            meta=PaginationMeta(
                total=total,
                page=params.page,
                limit=params.limit,
                pages=pages,
            ),
        )

    async def create_lab(self, db: AsyncSession, data: LabCreate) -> LabResponse:
        """Create and return a new laboratory."""
        lab = await self.repo.create(db, data)
        return LabResponse.model_validate(lab)

    async def update_lab(self, db: AsyncSession, lab_id: UUID, data: LabUpdate) -> LabResponse:
        """Update an existing laboratory."""
        lab = await self.repo.get_by_id(db, lab_id)
        if not lab:
            raise NotFoundException(message=f"Laboratory with id '{lab_id}' was not found.")

        updated = await self.repo.update(db, lab, data)
        return LabResponse.model_validate(updated)

    async def delete_lab(self, db: AsyncSession, lab_id: UUID) -> None:
        """Soft delete a laboratory."""
        lab = await self.repo.get_by_id(db, lab_id)
        if not lab:
            raise NotFoundException(message=f"Laboratory with id '{lab_id}' was not found.")
        await self.repo.delete(db, lab)
