from fastapi import FastAPI, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from database.session import get_db
from database.models import Ticket, TicketStatus
from core.redis import acquire_seat_lock, release_seat_lock
from api.routers.auth import router as auth_router
from api.routers.webhooks import router as webhooks_router
from api.routers.tickets import router as tickets_router
from api.routers.tournaments import router as tournaments_router

app = FastAPI(title="Ticketing System API")

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"], # Для локальной песочницы оставляем открытым
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(auth_router)
app.include_router(webhooks_router)
app.include_router(tickets_router)
app.include_router(tournaments_router)

@app.post("/api/seats/{seat_id}/lock", status_code=status.HTTP_200_OK)
async def lock_seat(seat_id: int, user_id: int, db: AsyncSession = Depends(get_db)):
    # 1. Проверяем статус в БД (грязное чтение, чтобы отсеять уже выкупленные билеты)
    query = select(Ticket).where(Ticket.seat_id == seat_id)
    result = await db.execute(query)
    ticket = result.scalar_one_or_none()

    if ticket and ticket.status != TicketStatus.AVAILABLE:
        raise HTTPException(status_code=409, detail="Seat is already booked or locked in DB")

    # 2. Пытаемся захватить распределенную блокировку в Redis (15 минут по ТЗ)
    locked = await acquire_seat_lock(seat_id=seat_id, user_id=user_id)
    if not locked:
        raise HTTPException(status_code=409, detail="Seat is currently locked by another user")

    # 3. Лок наш. Пишем статус в PostgreSQL
    try:
        if not ticket:
            ticket = Ticket(seat_id=seat_id, user_id=user_id, status=TicketStatus.LOCKED)
            db.add(ticket)
        else:
            ticket.status = TicketStatus.LOCKED
            ticket.user_id = user_id
        
        await db.commit()
        return {"message": "Seat locked successfully", "seat_id": seat_id, "ticket_id": ticket.id, "status": "LOCKED"}
        
    except Exception as e:
        # Критически важно: если БД отвалилась, снимаем лок в Redis, иначе место зависнет на 15 минут
        await release_seat_lock(seat_id)
        await db.rollback()
        raise HTTPException(status_code=500, detail="Database transaction failed")
