from __future__ import annotations

from sqlalchemy import select
from sqlalchemy.orm import selectinload

from app.api.deps import CurrentUserContext
from app.models.employee import Employee
from app.models.financial_record import ExpenseClaim
from app.services.pagination import PageResult, paginate_select


class ExpenseClaimPaginationMixin:
    def _claim_list_stmt(self):
        return select(ExpenseClaim).options(
            selectinload(ExpenseClaim.items),
            selectinload(ExpenseClaim.employee).selectinload(Employee.manager),
            selectinload(ExpenseClaim.employee).selectinload(Employee.roles),
        )

    def list_claims_page(
        self,
        current_user: CurrentUserContext,
        *,
        page: int | None,
        page_size: int | None,
    ) -> PageResult[ExpenseClaim]:
        stmt = self._claim_list_stmt().order_by(
            ExpenseClaim.created_at.desc(),
            ExpenseClaim.occurred_at.desc(),
        )
        stmt = self._access_policy.apply_claim_scope(stmt, current_user)
        result = paginate_select(self.db, stmt, page=page, page_size=page_size)
        self._access_policy.attach_budget_approval_snapshots(result.items)
        return result

    def list_approval_claims_page(
        self,
        current_user: CurrentUserContext,
        *,
        page: int | None,
        page_size: int | None,
    ) -> PageResult[ExpenseClaim]:
        stmt = self._claim_list_stmt().order_by(
            ExpenseClaim.submitted_at.desc(),
            ExpenseClaim.created_at.desc(),
        )
        stmt = self._access_policy.apply_approval_claim_scope(stmt, current_user)
        result = paginate_select(self.db, stmt, page=page, page_size=page_size)
        self._access_policy.attach_budget_approval_snapshots(result.items)
        return result

    def list_archived_claims_page(
        self,
        current_user: CurrentUserContext,
        *,
        page: int | None,
        page_size: int | None,
    ) -> PageResult[ExpenseClaim]:
        stmt = self._claim_list_stmt().order_by(
            ExpenseClaim.updated_at.desc(),
            ExpenseClaim.submitted_at.desc(),
            ExpenseClaim.created_at.desc(),
        )
        stmt = self._access_policy.apply_archived_claim_scope(stmt, current_user)
        return paginate_select(self.db, stmt, page=page, page_size=page_size)
