from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from typing import List, Optional

from app.database import get_db
from app.models import User, SpreadBet, MatchComment
from app.models.spread_bet import SpreadBetStatus
from app.schemas.match_comment import (
    MatchComment as MatchCommentSchema,
    MatchCommentCreate,
    MatchDetailResponse,
    MatchBetDetail,
    MatchUser
)
from app.routers.auth import get_current_user, get_current_user_optional
from app.routers.websocket import broadcast_to_match

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


async def get_match_bet(bet_id: int, db: AsyncSession) -> SpreadBet:
    """Get a matched bet by ID with all relationships loaded."""
    result = await db.execute(
        select(SpreadBet)
        .options(
            selectinload(SpreadBet.event),
            selectinload(SpreadBet.creator),
            selectinload(SpreadBet.taker)
        )
        .where(SpreadBet.id == bet_id)
    )
    bet = result.scalar_one_or_none()
    if not bet:
        raise HTTPException(status_code=404, detail="Bet not found")
    if bet.status not in [SpreadBetStatus.MATCHED, SpreadBetStatus.COMPLETED]:
        raise HTTPException(status_code=400, detail="Bet is not matched")
    return bet


@router.get("/{bet_id}", response_model=MatchDetailResponse)
async def get_match_detail(
    bet_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: Optional[User] = Depends(get_current_user_optional)
):
    """Get match details - public access, anyone can view."""
    bet = await get_match_bet(bet_id, db)

    # Get comments
    comments_result = await db.execute(
        select(MatchComment)
        .options(selectinload(MatchComment.user))
        .where(MatchComment.spread_bet_id == bet_id)
        .order_by(MatchComment.created_at.asc())
    )
    comments = comments_result.scalars().all()

    # Check if current user can comment
    can_comment = False
    if current_user:
        can_comment = current_user.id in [bet.creator_id, bet.taker_id]

    return MatchDetailResponse(
        bet=MatchBetDetail(
            id=bet.id,
            event_id=bet.event_id,
            spread=bet.spread,
            team=bet.team,
            stake_amount=bet.stake_amount,
            house_commission_percent=bet.house_commission_percent,
            status=bet.status,
            payout_amount=bet.payout_amount,
            winner_id=bet.winner_id,
            created_at=bet.created_at,
            matched_at=bet.matched_at,
            completed_at=bet.completed_at,
            home_team=bet.event.home_team,
            away_team=bet.event.away_team,
            game_time=bet.event.game_time,
            official_spread=bet.event.official_spread,
            creator=MatchUser(id=bet.creator.id, username=bet.creator.username),
            taker=MatchUser(id=bet.taker.id, username=bet.taker.username) if bet.taker else None
        ),
        comments=[
            MatchCommentSchema(
                id=c.id,
                spread_bet_id=c.spread_bet_id,
                user_id=c.user_id,
                username=c.user.username,
                content=c.content,
                created_at=c.created_at
            )
            for c in comments
        ],
        can_comment=can_comment
    )


@router.get("/{bet_id}/comments", response_model=List[MatchCommentSchema])
async def get_match_comments(
    bet_id: int,
    db: AsyncSession = Depends(get_db)
):
    """Get all comments for a match - public access."""
    # Verify bet exists and is matched
    await get_match_bet(bet_id, db)

    result = await db.execute(
        select(MatchComment)
        .options(selectinload(MatchComment.user))
        .where(MatchComment.spread_bet_id == bet_id)
        .order_by(MatchComment.created_at.asc())
    )
    comments = result.scalars().all()

    return [
        MatchCommentSchema(
            id=c.id,
            spread_bet_id=c.spread_bet_id,
            user_id=c.user_id,
            username=c.user.username,
            content=c.content,
            created_at=c.created_at
        )
        for c in comments
    ]


@router.post("/{bet_id}/comments", response_model=MatchCommentSchema)
async def add_match_comment(
    bet_id: int,
    comment_data: MatchCommentCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """Add a comment to a match - only participants can comment."""
    bet = await get_match_bet(bet_id, db)

    # Check if user is a participant
    if current_user.id not in [bet.creator_id, bet.taker_id]:
        raise HTTPException(
            status_code=403,
            detail="Only bet participants can comment"
        )

    # Create comment
    comment = MatchComment(
        spread_bet_id=bet_id,
        user_id=current_user.id,
        content=comment_data.content
    )
    db.add(comment)
    await db.commit()
    await db.refresh(comment)

    comment_response = MatchCommentSchema(
        id=comment.id,
        spread_bet_id=comment.spread_bet_id,
        user_id=comment.user_id,
        username=current_user.username,
        content=comment.content,
        created_at=comment.created_at
    )

    # Broadcast new comment to match subscribers
    await broadcast_to_match(
        bet_id,
        "new_comment",
        {
            "id": comment.id,
            "spread_bet_id": comment.spread_bet_id,
            "user_id": comment.user_id,
            "username": current_user.username,
            "content": comment.content,
            "created_at": comment.created_at.isoformat()
        }
    )

    return comment_response
