from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.orm import Session
from typing import Optional, List
from utils.utils import get_db
from . import handler
from .schema import (
    ScheduleCreate,
    ScheduleUpdate,
    ScheduleResponse,
    ScheduleDetailResponse,
    SeatCreate,
    SeatUpdate,
    SeatResponse,
    GenerateSeatsRequest,
    GenerateSeatsResponse,
    ScheduleStatus,
    SeatStatus,
)

router = APIRouter(prefix="/schedules", tags=["Schedule Management"])


@router.post(
    "/",
    response_model=ScheduleResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Bus Schedule",
    description="Creates a new bus schedule for a specific route and bus. Validates that the bus and route exist and are active, departure time is in the future, and arrival time is after departure time. Returns 404 if bus or route not found, 400 if validation fails.",
)
def create_schedule_route(data: ScheduleCreate, db: Session = Depends(get_db)):
    return handler.create_schedule(db, data)


@router.get(
    "/{schedule_id}",
    response_model=ScheduleResponse,
    summary="Get Schedule By ID",
    description="Retrieves a single schedule by its unique identifier. Returns 404 if the schedule does not exist.",
)
def get_schedule_route(schedule_id: str, db: Session = Depends(get_db)):
    return handler.get_schedule(db, schedule_id)


@router.get(
    "/",
    response_model=List[ScheduleResponse],
    summary="List Schedules",
    description="Returns a paginated list of schedules. Supports optional filtering by route_id and status. Results are ordered by departure datetime in descending order.",
)
def list_schedules_route(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    route_id: Optional[str] = Query(None),
    status: Optional[ScheduleStatus] = Query(None),
    db: Session = Depends(get_db),
):
    status_value = status.value if status else None
    return handler.list_schedules(db, limit, offset, route_id, status_value)


@router.put(
    "/{schedule_id}",
    response_model=ScheduleResponse,
    summary="Update Schedule",
    description="Updates an existing schedule. Validates that any new bus or route references exist and are active, and that arrival time remains after departure time. Returns 404 if schedule, bus, or route not found, 400 if validation fails.",
)
def update_schedule_route(
    schedule_id: str, data: ScheduleUpdate, db: Session = Depends(get_db)
):
    return handler.update_schedule(db, schedule_id, data)


@router.delete(
    "/{schedule_id}",
    status_code=status.HTTP_200_OK,
    summary="Delete Schedule",
    description="Deletes a schedule and all associated seats. Cannot delete schedules that are in_transit or completed. Returns 404 if schedule not found, 400 if schedule status prevents deletion.",
)
def delete_schedule_route(schedule_id: str, db: Session = Depends(get_db)):
    return handler.delete_schedule(db, schedule_id)


@router.get(
    "/{schedule_id}/details",
    response_model=ScheduleDetailResponse,
    summary="Get Schedule Details With Related Data",
    description="Retrieves a schedule with all related bus, route, and seat information eagerly loaded. Returns comprehensive details including bus amenities, route distance, and all seat statuses. Returns 404 if schedule not found.",
)
def get_schedule_details_route(schedule_id: str, db: Session = Depends(get_db)):
    return handler.get_schedule_details(db, schedule_id)


@router.post(
    "/{schedule_id}/generate-seats",
    response_model=GenerateSeatsResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Generate Seat Inventory For Schedule",
    description="Auto-generates seat records for a schedule based on the bus seat layout configuration. Creates individual seat records with seat numbers, types, and price modifiers. Updates the schedule available_seats count. Returns 404 if schedule not found, 409 if seats already exist, 400 if bus layout configuration is invalid.",
)
def generate_seats_route(
    schedule_id: str, data: GenerateSeatsRequest, db: Session = Depends(get_db)
):
    return handler.generate_seats_for_schedule(db, schedule_id)


@router.get(
    "/search/schedules",
    response_model=List[ScheduleResponse],
    summary="Search Schedules By Route And Date",
    description="Searches for available schedules by origin city, destination city, and departure date. Returns only schedules with status 'scheduled'. Results are ordered by departure datetime ascending. Supports pagination.",
)
def search_schedules_route(
    origin_city: Optional[str] = Query(None),
    destination_city: Optional[str] = Query(None),
    departure_date: Optional[str] = Query(None),
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    db: Session = Depends(get_db),
):
    return handler.search_schedules(db, origin_city, destination_city, departure_date, limit, offset)


@router.get(
    "/{schedule_id}/seats",
    response_model=List[SeatResponse],
    summary="Get All Seats For Schedule",
    description="Retrieves all seat records for a specific schedule, ordered by seat number. Returns real-time seat availability status. Returns 404 if schedule not found.",
)
def get_schedule_seats_route(schedule_id: str, db: Session = Depends(get_db)):
    return handler.get_schedule_seats(db, schedule_id)


@router.post(
    "/seats",
    response_model=SeatResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Individual Seat",
    description="Creates a single seat record for a schedule. Validates that the schedule exists and the seat number is unique within the schedule. Returns 404 if schedule not found, 409 if seat number already exists.",
)
def create_seat_route(data: SeatCreate, db: Session = Depends(get_db)):
    return handler.create_seat(db, data)


@router.get(
    "/seats/{seat_id}",
    response_model=SeatResponse,
    summary="Get Seat By ID",
    description="Retrieves a single seat by its unique identifier. Returns 404 if the seat does not exist.",
)
def get_seat_route(seat_id: str, db: Session = Depends(get_db)):
    return handler.get_seat(db, seat_id)


@router.get(
    "/seats/list/all",
    response_model=List[SeatResponse],
    summary="List Seats",
    description="Returns a paginated list of seats. Supports optional filtering by schedule_id and status. Results are ordered by seat number.",
)
def list_seats_route(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    schedule_id: Optional[str] = Query(None),
    status: Optional[SeatStatus] = Query(None),
    db: Session = Depends(get_db),
):
    status_value = status.value if status else None
    return handler.list_seats(db, limit, offset, schedule_id, status_value)


@router.put(
    "/seats/{seat_id}",
    response_model=SeatResponse,
    summary="Update Seat",
    description="Updates an existing seat record. Validates that any new schedule reference exists and seat number remains unique within the schedule. Returns 404 if seat or schedule not found, 409 if seat number conflict.",
)
def update_seat_route(seat_id: str, data: SeatUpdate, db: Session = Depends(get_db)):
    return handler.update_seat(db, seat_id, data)


@router.delete(
    "/seats/{seat_id}",
    status_code=status.HTTP_200_OK,
    summary="Delete Seat",
    description="Deletes a seat record. Can only delete seats with status 'available'. Returns 404 if seat not found, 400 if seat is reserved or booked.",
)
def delete_seat_route(seat_id: str, db: Session = Depends(get_db)):
    return handler.delete_seat(db, seat_id)