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

from typing import Sequence
from uuid import UUID

from sqlalchemy import select

from app.models.foundation import (
    BeautyAuditLog,
    BeautyConfiguration,
    BeautyBranch,
    BeautyOrganization,
    BeautyPermission,
    BeautyRole,
    BeautySetting,
    ExternalProviderConfig,
    BookingEngineRegistration,
)
from app.repositories.base import TenantBaseRepository


class BeautyOrganizationRepository(TenantBaseRepository[BeautyOrganization]):
    model = BeautyOrganization

    async def get_by_code(
        self, tenant_id: UUID, code: str
    ) -> BeautyOrganization | 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 BeautyBranchRepository(TenantBaseRepository[BeautyBranch]):
    model = BeautyBranch

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


class BeautyRoleRepository(TenantBaseRepository[BeautyRole]):
    model = BeautyRole


class BeautyPermissionRepository(TenantBaseRepository[BeautyPermission]):
    model = BeautyPermission


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 BookingEngineRegistrationRepository(
    TenantBaseRepository[BookingEngineRegistration]
):
    model = BookingEngineRegistration


class BeautyConfigurationRepository(TenantBaseRepository[BeautyConfiguration]):
    model = BeautyConfiguration


class BeautySettingRepository(TenantBaseRepository[BeautySetting]):
    model = BeautySetting

    async def get_by_key(
        self,
        tenant_id: UUID,
        key: str,
        *,
        organization_id: UUID | None = None,
        branch_id: UUID | None = None,
    ) -> BeautySetting | None:
        clauses = [
            self.model.tenant_id == tenant_id,
            self.model.key == key,
            self.model.is_deleted.is_(False),
        ]
        if organization_id is None:
            clauses.append(self.model.organization_id.is_(None))
        else:
            clauses.append(self.model.organization_id == organization_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 BeautyAuditLogRepository(TenantBaseRepository[BeautyAuditLog]):
    model = BeautyAuditLog

    async def list_for_entity(
        self,
        tenant_id: UUID,
        entity_type: str,
        entity_id: UUID,
        *,
        limit: int = 100,
    ) -> Sequence[BeautyAuditLog]:
        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()
