from sqlalchemy import select, or_
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.models import Bet, BetStatus, BetCategory
from app.schemas.bet import BetCreate


async def get_bet_by_id(db: AsyncSession, bet_id: int) -> Bet | None:
    result = await db.execute(
        select(Bet)
        .options(
            selectinload(Bet.creator),
            selectinload(Bet.opponent)
        )
        .where(Bet.id == bet_id)
    )
    return result.scalar_one_or_none()


async def get_open_bets(
    db: AsyncSession,
    skip: int = 0,
    limit: int = 20,
    category: BetCategory | None = None,
) -> list[Bet]:
    query = select(Bet).where(Bet.status == BetStatus.OPEN)

    if category:
        query = query.where(Bet.category == category)

    query = query.options(
        selectinload(Bet.creator)
    ).offset(skip).limit(limit).order_by(Bet.created_at.desc())

    result = await db.execute(query)
    return list(result.scalars().all())


async def get_user_bets(
    db: AsyncSession,
    user_id: int,
    status: BetStatus | None = None,
) -> list[Bet]:
    query = select(Bet).where(
        or_(Bet.creator_id == user_id, Bet.opponent_id == user_id)
    )

    if status:
        query = query.where(Bet.status == status)

    query = query.options(
        selectinload(Bet.creator),
        selectinload(Bet.opponent)
    ).order_by(Bet.created_at.desc())

    result = await db.execute(query)
    return list(result.scalars().all())


async def create_bet(db: AsyncSession, bet_data: BetCreate, user_id: int) -> Bet:
    bet = Bet(
        creator_id=user_id,
        title=bet_data.title,
        description=bet_data.description,
        category=bet_data.category,
        event_name=bet_data.event_name,
        event_date=bet_data.event_date,
        creator_position=bet_data.creator_position,
        opponent_position=bet_data.opponent_position,
        creator_odds=bet_data.creator_odds,
        opponent_odds=bet_data.opponent_odds,
        stake_amount=bet_data.stake_amount,
        visibility=bet_data.visibility,
        expires_at=bet_data.expires_at,
    )
    db.add(bet)
    await db.flush()
    await db.refresh(bet)
    return bet
