"""Wallet Engine repositories — Phase 7.6."""
from __future__ import annotations

from uuid import UUID

from sqlalchemy import func, select

from app.models.types import WalletLedgerEntryType
from app.models.wallet import WalletAccount, WalletLedgerEntry
from app.repositories.base import TenantBaseRepository


class WalletAccountRepository(TenantBaseRepository[WalletAccount]):
    model = WalletAccount

    async def get_by_member_program(
        self, tenant_id: UUID, program_id: UUID, member_id: UUID
    ) -> WalletAccount | None:
        stmt = select(WalletAccount).where(
            WalletAccount.tenant_id == tenant_id,
            WalletAccount.program_id == program_id,
            WalletAccount.member_id == member_id,
            WalletAccount.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()

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


class WalletLedgerRepository(TenantBaseRepository[WalletLedgerEntry]):
    model = WalletLedgerEntry

    async def balance_for_account(
        self, tenant_id: UUID, wallet_account_id: UUID
    ) -> int:
        stmt = select(func.coalesce(func.sum(WalletLedgerEntry.amount), 0)).where(
            WalletLedgerEntry.tenant_id == tenant_id,
            WalletLedgerEntry.wallet_account_id == wallet_account_id,
        )
        result = await self.session.execute(stmt)
        return int(result.scalar_one())

    async def get_by_idempotency(
        self, tenant_id: UUID, idempotency_key: str | None
    ) -> WalletLedgerEntry | None:
        if not idempotency_key:
            return None
        stmt = select(WalletLedgerEntry).where(
            WalletLedgerEntry.tenant_id == tenant_id,
            WalletLedgerEntry.idempotency_key == idempotency_key,
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()

    async def list_for_account(
        self,
        tenant_id: UUID,
        wallet_account_id: UUID,
        *,
        entry_type: WalletLedgerEntryType | None = None,
        offset: int = 0,
        limit: int = 50,
    ):
        clauses = [
            WalletLedgerEntry.tenant_id == tenant_id,
            WalletLedgerEntry.wallet_account_id == wallet_account_id,
        ]
        if entry_type is not None:
            clauses.append(WalletLedgerEntry.entry_type == entry_type)
        stmt = (
            select(WalletLedgerEntry)
            .where(*clauses)
            .order_by(WalletLedgerEntry.created_at.desc())
            .offset(offset)
            .limit(limit)
        )
        result = await self.session.execute(stmt)
        return result.scalars().all()

    async def count_for_account(
        self,
        tenant_id: UUID,
        wallet_account_id: UUID,
        *,
        entry_type: WalletLedgerEntryType | None = None,
    ) -> int:
        clauses = [
            WalletLedgerEntry.tenant_id == tenant_id,
            WalletLedgerEntry.wallet_account_id == wallet_account_id,
        ]
        if entry_type is not None:
            clauses.append(WalletLedgerEntry.entry_type == entry_type)
        stmt = select(func.count()).select_from(WalletLedgerEntry).where(*clauses)
        result = await self.session.execute(stmt)
        return int(result.scalar_one())
