from sqlalchemy import select
from app.models.customer import Customer
from app.models.wallet import Wallet
from app.models.wallet_history import WalletHistory
from app.models.transaction import Transaction
from app.services.loyalty_service import LoyaltyService
from app.core.exceptions import not_found, conflict

class TransactionService:
    @staticmethod
    async def create(db, brand_id, data):
        if data.external_reference:
            old = await db.scalar(select(Transaction).where(Transaction.external_reference == data.external_reference))
            if old: raise conflict("Duplicate transaction")
        customer = await db.scalar(select(Customer).where(Customer.id == data.customer_id, Customer.brand_id == brand_id))
        if not customer: raise not_found("Customer not found")
        wallet = await db.scalar(select(Wallet).where(Wallet.customer_id == customer.id, Wallet.brand_id == brand_id).with_for_update())
        if not wallet:
            wallet = Wallet(brand_id=brand_id, customer_id=customer.id, balance=0)
            db.add(wallet); await db.flush()
        points = await LoyaltyService.calculate_points(db, brand_id, data.amount, customer.tier_id)
        tx = Transaction(brand_id=brand_id, points_earned=points, status="completed", **data.model_dump())
        db.add(tx)
        wallet.balance += points
        customer.points_balance = wallet.balance
        customer.lifetime_points += points
        await db.flush()
        db.add(WalletHistory(
            brand_id=brand_id, wallet_id=wallet.id, customer_id=customer.id,
            entry_type="credit", points=points, balance_after=wallet.balance,
            reference_type="transaction", reference_id=str(tx.id),
            description="Purchase loyalty points"
        ))
        await db.commit()
        await db.refresh(tx)
        return tx
