"""Healthcare foundation repositories."""
from __future__ import annotations

from typing import Sequence
from uuid import UUID

from sqlalchemy import select

from app.models.foundation import (
    Branch,
    Clinic,
    Department,
    ExternalProviderConfig,
    HealthcareAuditLog,
    HealthcareConfiguration,
    HealthcarePermission,
    HealthcareRole,
    HealthcareSetting,
)
from app.repositories.base import TenantBaseRepository


class ClinicRepository(TenantBaseRepository[Clinic]):
    model = Clinic

    async def get_by_code(self, tenant_id: UUID, code: str) -> Clinic | None:
        stmt = select(self.model).where(
            self.model.tenant_id == tenant_id,
            self.model.code == code,
            self.model.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class BranchRepository(TenantBaseRepository[Branch]):
    model = Branch

    async def list_by_clinic(
        self, tenant_id: UUID, clinic_id: UUID, *, offset: int = 0, limit: int = 20
    ) -> Sequence[Branch]:
        stmt = (
            select(self.model)
            .where(
                self.model.tenant_id == tenant_id,
                self.model.clinic_id == clinic_id,
                self.model.is_deleted.is_(False),
            )
            .offset(offset)
            .limit(limit)
        )
        result = await self.session.execute(stmt)
        return result.scalars().all()


class DepartmentRepository(TenantBaseRepository[Department]):
    model = Department

    async def get_by_code(
        self, tenant_id: UUID, clinic_id: UUID, code: str
    ) -> Department | None:
        stmt = select(self.model).where(
            self.model.tenant_id == tenant_id,
            self.model.clinic_id == clinic_id,
            self.model.code == code,
            self.model.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class HealthcareRoleRepository(TenantBaseRepository[HealthcareRole]):
    model = HealthcareRole


class HealthcarePermissionRepository(TenantBaseRepository[HealthcarePermission]):
    model = HealthcarePermission


class ExternalProviderConfigRepository(TenantBaseRepository[ExternalProviderConfig]):
    model = ExternalProviderConfig

    async def get_by_code(
        self, tenant_id: UUID, code: str
    ) -> ExternalProviderConfig | None:
        stmt = select(self.model).where(
            self.model.tenant_id == tenant_id,
            self.model.code == code,
            self.model.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class HealthcareConfigurationRepository(TenantBaseRepository[HealthcareConfiguration]):
    model = HealthcareConfiguration


class HealthcareSettingRepository(TenantBaseRepository[HealthcareSetting]):
    model = HealthcareSetting

    async def get_by_key(
        self,
        tenant_id: UUID,
        key: str,
        *,
        clinic_id: UUID | None = None,
        branch_id: UUID | None = None,
    ) -> HealthcareSetting | None:
        clauses = [
            self.model.tenant_id == tenant_id,
            self.model.key == key,
            self.model.is_deleted.is_(False),
        ]
        if clinic_id is None:
            clauses.append(self.model.clinic_id.is_(None))
        else:
            clauses.append(self.model.clinic_id == clinic_id)
        if branch_id is None:
            clauses.append(self.model.branch_id.is_(None))
        else:
            clauses.append(self.model.branch_id == branch_id)
        stmt = select(self.model).where(*clauses)
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class HealthcareAuditLogRepository(TenantBaseRepository[HealthcareAuditLog]):
    model = HealthcareAuditLog

    async def list_for_entity(
        self,
        tenant_id: UUID,
        entity_type: str,
        entity_id: UUID,
        *,
        limit: int = 100,
    ) -> Sequence[HealthcareAuditLog]:
        stmt = (
            select(self.model)
            .where(
                self.model.tenant_id == tenant_id,
                self.model.entity_type == entity_type,
                self.model.entity_id == entity_id,
            )
            .order_by(self.model.created_at.desc())
            .limit(limit)
        )
        result = await self.session.execute(stmt)
        return result.scalars().all()
