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

from backend.app.models.finance import CostCenter, CostCenterMember, UserWallet
from backend.app.models.settings import Settings as AppSettingModel
from backend.app.models.user import User
from backend.app.schemas.settings import AppSettings as AppSettingsSchema


async def ensure_user_finance_defaults(db: AsyncSession, user: User) -> bool:
    """Ensure wallet and private cost center defaults exist for a user.

    Returns True when database objects were created or changed.
    """
    changed = False

    wallet = (await db.execute(select(UserWallet).where(UserWallet.user_id == user.id))).scalar_one_or_none()
    if wallet is None:
        # Respect admin-configured currency if present, otherwise fall back to app default
        default_currency = AppSettingsSchema().currency
        result = await db.execute(select(AppSettingModel).where(AppSettingModel.key == "currency"))
        setting = result.scalar_one_or_none()
        currency = setting.value if setting and setting.value else default_currency
        db.add(UserWallet(user_id=user.id, balance=0.0, currency=currency))
        changed = True

    private_center = (
        (
            await db.execute(
                select(CostCenter)
                .where(
                    CostCenter.is_private.is_(True),
                    CostCenter.owner_user_id == user.id,
                )
                .order_by(CostCenter.id.asc())
            )
        )
        .scalars()
        .first()
    )

    if private_center is None:
        private_center = CostCenter(
            name=user.username,
            is_active=True,
            is_private=True,
            owner_user_id=user.id,
        )
        db.add(private_center)
        await db.flush()
        changed = True
    else:
        # A private center is the billing fallback for its owner and therefore
        # must remain active. A zero budget is the supported way to prevent
        # printing from it.
        if not private_center.is_active:
            private_center.is_active = True
            changed = True
        if private_center.name != user.username:
            private_center.name = user.username
            changed = True

    membership = (
        await db.execute(
            select(CostCenterMember).where(
                CostCenterMember.cost_center_id == private_center.id,
                CostCenterMember.user_id == user.id,
            )
        )
    ).scalar_one_or_none()
    if membership is None:
        db.add(CostCenterMember(cost_center_id=private_center.id, user_id=user.id, can_print=True))
        changed = True

    return changed
