from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update
from typing import List
from datetime import datetime
from decimal import Decimal

from app.database import get_db
from app.models import User, SportEvent, SpreadBet, AdminSettings, EventStatus
from app.schemas.sport_event import SportEventCreate, SportEventUpdate, SportEvent as SportEventSchema
from app.routers.auth import get_current_user

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


# Dependency to check if user is admin
async def get_admin_user(current_user: User = Depends(get_current_user)) -> User:
    if not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Admin access required"
        )
    return current_user


# Admin Settings Routes

@router.get("/settings")
async def get_admin_settings(
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Get current admin settings"""
    result = await db.execute(select(AdminSettings).limit(1))
    settings = result.scalar_one_or_none()

    if not settings:
        # Create default settings if none exist
        settings = AdminSettings()
        db.add(settings)
        await db.commit()
        await db.refresh(settings)

    return settings


@router.patch("/settings")
async def update_admin_settings(
    default_house_commission_percent: Decimal | None = None,
    default_min_bet_amount: Decimal | None = None,
    default_max_bet_amount: Decimal | None = None,
    default_min_spread: float | None = None,
    default_max_spread: float | None = None,
    spread_increment: float | None = None,
    platform_name: str | None = None,
    maintenance_mode: bool | None = None,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Update admin settings"""
    result = await db.execute(select(AdminSettings).limit(1))
    settings = result.scalar_one_or_none()

    if not settings:
        settings = AdminSettings()
        db.add(settings)

    # Update provided fields
    if default_house_commission_percent is not None:
        settings.default_house_commission_percent = default_house_commission_percent
    if default_min_bet_amount is not None:
        settings.default_min_bet_amount = default_min_bet_amount
    if default_max_bet_amount is not None:
        settings.default_max_bet_amount = default_max_bet_amount
    if default_min_spread is not None:
        settings.default_min_spread = default_min_spread
    if default_max_spread is not None:
        settings.default_max_spread = default_max_spread
    if spread_increment is not None:
        settings.spread_increment = spread_increment
    if platform_name is not None:
        settings.platform_name = platform_name
    if maintenance_mode is not None:
        settings.maintenance_mode = maintenance_mode

    await db.commit()
    await db.refresh(settings)

    return settings


# Sport Event Management Routes

@router.post("/events", response_model=SportEventSchema)
async def create_sport_event(
    event: SportEventCreate,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Create a new sport event"""
    # Get default settings
    result = await db.execute(select(AdminSettings).limit(1))
    settings = result.scalar_one_or_none()

    # Apply defaults from settings if not provided
    if settings:
        event_data = event.model_dump()
        event_data['created_by'] = admin.id
        new_event = SportEvent(**event_data)
    else:
        new_event = SportEvent(**event.model_dump(), created_by=admin.id)

    db.add(new_event)
    await db.commit()
    await db.refresh(new_event)

    return new_event


@router.get("/events", response_model=List[SportEventSchema])
async def get_all_sport_events(
    skip: int = 0,
    limit: int = 100,
    status: EventStatus | None = None,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Get all sport events (admin view)"""
    query = select(SportEvent)

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

    query = query.offset(skip).limit(limit).order_by(SportEvent.game_time.desc())

    result = await db.execute(query)
    events = result.scalars().all()

    return events


@router.get("/events/{event_id}", response_model=SportEventSchema)
async def get_sport_event(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Get a specific sport event"""
    result = await db.execute(select(SportEvent).where(SportEvent.id == event_id))
    event = result.scalar_one_or_none()

    if not event:
        raise HTTPException(status_code=404, detail="Event not found")

    return event


@router.patch("/events/{event_id}", response_model=SportEventSchema)
async def update_sport_event(
    event_id: int,
    event_update: SportEventUpdate,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Update a sport event"""
    result = await db.execute(select(SportEvent).where(SportEvent.id == event_id))
    event = result.scalar_one_or_none()

    if not event:
        raise HTTPException(status_code=404, detail="Event not found")

    # Update fields
    update_data = event_update.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        setattr(event, field, value)

    await db.commit()
    await db.refresh(event)

    return event


@router.delete("/events/{event_id}")
async def delete_sport_event(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Delete a sport event (only if no active bets)"""
    result = await db.execute(select(SportEvent).where(SportEvent.id == event_id))
    event = result.scalar_one_or_none()

    if not event:
        raise HTTPException(status_code=404, detail="Event not found")

    # Check for active bets
    bets_result = await db.execute(
        select(SpreadBet).where(
            SpreadBet.event_id == event_id,
            SpreadBet.status.in_(['open', 'matched'])
        )
    )
    active_bets = bets_result.scalars().all()

    if active_bets:
        raise HTTPException(
            status_code=400,
            detail=f"Cannot delete event with {len(active_bets)} active bet(s)"
        )

    await db.delete(event)
    await db.commit()

    return {"message": "Event deleted successfully"}


@router.post("/events/{event_id}/complete")
async def complete_sport_event(
    event_id: int,
    final_score_home: int,
    final_score_away: int,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user)
):
    """Mark event as completed and set final scores"""
    result = await db.execute(select(SportEvent).where(SportEvent.id == event_id))
    event = result.scalar_one_or_none()

    if not event:
        raise HTTPException(status_code=404, detail="Event not found")

    event.status = EventStatus.COMPLETED
    event.final_score_home = final_score_home
    event.final_score_away = final_score_away

    await db.commit()
    await db.refresh(event)

    # TODO: Auto-settle all matched bets for this event

    return {"message": "Event completed", "event": event}
