"""Foundation repositories."""
from __future__ import annotations

from uuid import UUID

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

from app.models.foundation import (
    Account,
    ChartOfAccounts,
    CostCenter,
    Currency,
    FiscalPeriod,
    FiscalYear,
    Project,
    TenantAccountingConfiguration,
)
from app.repositories.base import TenantBaseRepository


class ChartOfAccountsRepository(TenantBaseRepository[ChartOfAccounts]):
    model = ChartOfAccounts

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


class AccountRepository(TenantBaseRepository[Account]):
    model = Account

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

    async def list_by_chart(
        self, tenant_id: UUID, chart_id: UUID, *, offset: int = 0, limit: int = 100
    ):
        stmt = (
            select(Account)
            .where(Account.tenant_id == tenant_id, Account.chart_id == chart_id)
            .offset(offset)
            .limit(limit)
        )
        result = await self.session.execute(stmt)
        return result.scalars().all()


class CurrencyRepository(TenantBaseRepository[Currency]):
    model = Currency


class FiscalYearRepository(TenantBaseRepository[FiscalYear]):
    model = FiscalYear

    async def get_current(self, tenant_id: UUID) -> FiscalYear | None:
        stmt = select(FiscalYear).where(
            FiscalYear.tenant_id == tenant_id, FiscalYear.is_current.is_(True)
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class FiscalPeriodRepository(TenantBaseRepository[FiscalPeriod]):
    model = FiscalPeriod

    async def get_current(self, tenant_id: UUID) -> FiscalPeriod | None:
        stmt = select(FiscalPeriod).where(
            FiscalPeriod.tenant_id == tenant_id, FiscalPeriod.is_current.is_(True)
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()

    async def list_by_year(self, tenant_id: UUID, fiscal_year_id: UUID):
        stmt = select(FiscalPeriod).where(
            FiscalPeriod.tenant_id == tenant_id,
            FiscalPeriod.fiscal_year_id == fiscal_year_id,
        )
        result = await self.session.execute(stmt)
        return result.scalars().all()


class CostCenterRepository(TenantBaseRepository[CostCenter]):
    model = CostCenter


class ProjectRepository(TenantBaseRepository[Project]):
    model = Project


class TenantAccountingConfigRepository(TenantBaseRepository[TenantAccountingConfiguration]):
    model = TenantAccountingConfiguration

    async def get_for_tenant(self, tenant_id: UUID) -> TenantAccountingConfiguration | None:
        stmt = select(TenantAccountingConfiguration).where(
            TenantAccountingConfiguration.tenant_id == tenant_id
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()
