from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from app.schemas.bet import BetCreate, BetUpdate, BetResponse, BetDetailResponse, SettleBetRequest
from app.routers.auth import get_current_user
from app.crud.bet import get_bet_by_id, get_open_bets, get_user_bets, create_bet
from app.services.bet_service import accept_bet, settle_bet, cancel_bet
from app.models import User, BetCategory, BetStatus
from app.utils.exceptions import BetNotFoundError, NotBetParticipantError

router = APIRouter(prefix="/api/v1/bets", tags=["bets"])


@router.get("", response_model=list[BetResponse])
async def list_bets(
    skip: int = Query(0, ge=0),
    limit: int = Query(20, ge=1, le=100),
    category: BetCategory | None = None,
    db: AsyncSession = Depends(get_db)
):
    bets = await get_open_bets(db, skip=skip, limit=limit, category=category)
    return bets


@router.post("", response_model=BetResponse)
async def create_new_bet(
    bet_data: BetCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    bet = await create_bet(db, bet_data, current_user.id)
    await db.commit()
    bet = await get_bet_by_id(db, bet.id)
    return bet


@router.get("/{bet_id}", response_model=BetDetailResponse)
async def get_bet(
    bet_id: int,
    db: AsyncSession = Depends(get_db)
):
    bet = await get_bet_by_id(db, bet_id)
    if not bet:
        raise BetNotFoundError()
    return bet


@router.put("/{bet_id}", response_model=BetResponse)
async def update_bet(
    bet_id: int,
    bet_data: BetUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    bet = await get_bet_by_id(db, bet_id)
    if not bet:
        raise BetNotFoundError()

    if bet.creator_id != current_user.id:
        raise NotBetParticipantError()

    if bet.status != BetStatus.OPEN:
        raise ValueError("Cannot update non-open bet")

    # Update fields
    if bet_data.title is not None:
        bet.title = bet_data.title
    if bet_data.description is not None:
        bet.description = bet_data.description
    if bet_data.event_date is not None:
        bet.event_date = bet_data.event_date
    if bet_data.creator_position is not None:
        bet.creator_position = bet_data.creator_position
    if bet_data.opponent_position is not None:
        bet.opponent_position = bet_data.opponent_position
    if bet_data.stake_amount is not None:
        bet.stake_amount = bet_data.stake_amount
    if bet_data.creator_odds is not None:
        bet.creator_odds = bet_data.creator_odds
    if bet_data.opponent_odds is not None:
        bet.opponent_odds = bet_data.opponent_odds
    if bet_data.expires_at is not None:
        bet.expires_at = bet_data.expires_at

    await db.commit()
    await db.refresh(bet)
    return bet


@router.delete("/{bet_id}")
async def delete_bet(
    bet_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    await cancel_bet(db, bet_id, current_user.id)
    return {"message": "Bet cancelled successfully"}


@router.post("/{bet_id}/accept", response_model=BetResponse)
async def accept_bet_route(
    bet_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    bet = await accept_bet(db, bet_id, current_user.id)
    return bet


@router.post("/{bet_id}/settle", response_model=BetDetailResponse)
async def settle_bet_route(
    bet_id: int,
    settle_data: SettleBetRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    bet = await settle_bet(db, bet_id, settle_data.winner_id, current_user.id)
    return bet


@router.get("/my/created", response_model=list[BetResponse])
async def get_my_created_bets(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    from sqlalchemy import select
    from sqlalchemy.orm import selectinload
    from app.models import Bet

    result = await db.execute(
        select(Bet)
        .where(Bet.creator_id == current_user.id)
        .options(selectinload(Bet.creator), selectinload(Bet.opponent))
        .order_by(Bet.created_at.desc())
    )
    return list(result.scalars().all())


@router.get("/my/accepted", response_model=list[BetResponse])
async def get_my_accepted_bets(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    from sqlalchemy import select
    from sqlalchemy.orm import selectinload
    from app.models import Bet

    result = await db.execute(
        select(Bet)
        .where(Bet.opponent_id == current_user.id)
        .options(selectinload(Bet.creator), selectinload(Bet.opponent))
        .order_by(Bet.created_at.desc())
    )
    return list(result.scalars().all())


@router.get("/my/active", response_model=list[BetResponse])
async def get_my_active_bets(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    bets = await get_user_bets(db, current_user.id)
    active_bets = [bet for bet in bets if bet.status in [BetStatus.MATCHED, BetStatus.IN_PROGRESS]]
    return active_bets


@router.get("/my/history", response_model=list[BetDetailResponse])
async def get_my_bet_history(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    bets = await get_user_bets(db, current_user.id, status=BetStatus.COMPLETED)
    return bets
