from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.orm import Session
from typing import Optional
from datetime import date
from utils.utils import get_db, AppointmentStatus, AppointmentType
from . import handler
from .schema import (
    AppointmentCreate,
    AppointmentUpdate,
    AppointmentResponse,
    AppointmentDetailResponse,
    PaginatedAppointmentResponse,
)

router = APIRouter(prefix="/appointments", tags=["Appointments"])


@router.post(
    "/",
    response_model=AppointmentResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Appointment",
    description="Creates a new appointment for a patient with a doctor. Validates patient, doctor, and department references. Returns 404 if any reference is invalid.",
)
def create_appointment_route(data: AppointmentCreate, db: Session = Depends(get_db)):
    return handler.create_appointment(db, data)


@router.get(
    "/",
    response_model=PaginatedAppointmentResponse,
    summary="List Appointments",
    description="Returns a paginated list of appointments. Supports filtering by patient_id, doctor_id, department_id, status, appointment_type, and appointment_date.",
)
def list_appointments_route(
    limit: int = Query(20, ge=1),
    offset: int = Query(0, ge=0),
    patient_id: Optional[str] = None,
    doctor_id: Optional[str] = None,
    department_id: Optional[str] = None,
    status: Optional[AppointmentStatus] = None,
    appointment_type: Optional[AppointmentType] = None,
    appointment_date: Optional[date] = None,
    db: Session = Depends(get_db),
):
    return handler.list_appointments(
        db,
        limit,
        offset,
        patient_id=patient_id,
        doctor_id=doctor_id,
        department_id=department_id,
        status=status,
        appointment_type=appointment_type,
        appointment_date=appointment_date,
    )


@router.get(
    "/{appointment_id}",
    response_model=AppointmentResponse,
    summary="Get Appointment",
    description="Retrieves a single appointment by ID. Returns 404 if the appointment does not exist.",
)
def get_appointment_route(appointment_id: str, db: Session = Depends(get_db)):
    return handler.get_appointment(db, appointment_id)


@router.put(
    "/{appointment_id}",
    response_model=AppointmentResponse,
    summary="Update Appointment",
    description="Updates an existing appointment. Only provided fields are updated. Validates patient, doctor, and department references. Returns 404 if the appointment or any reference does not exist.",
)
def update_appointment_route(
    appointment_id: str, data: AppointmentUpdate, db: Session = Depends(get_db)
):
    return handler.update_appointment(db, appointment_id, data)


@router.delete(
    "/{appointment_id}",
    status_code=status.HTTP_200_OK,
    summary="Delete Appointment",
    description="Deletes an appointment. Returns 404 if the appointment does not exist. Returns 409 if the appointment is referenced by other records.",
)
def delete_appointment_route(appointment_id: str, db: Session = Depends(get_db)):
    return handler.delete_appointment(db, appointment_id)


@router.get(
    "/{appointment_id}/details",
    response_model=AppointmentDetailResponse,
    summary="Get Appointment Details",
    description="Retrieves detailed appointment information with eager-loaded patient, doctor, and department. Returns 404 if the appointment does not exist.",
)
def get_appointment_details_route(appointment_id: str, db: Session = Depends(get_db)):
    return handler.get_appointment_details(db, appointment_id)


@router.post(
    "/{appointment_id}/check-in",
    response_model=AppointmentResponse,
    summary="Check In Appointment",
    description="Updates the appointment status to checked_in. Only scheduled or confirmed appointments can be checked in. Returns 400 if the status transition is invalid.",
)
def check_in_appointment_route(appointment_id: str, db: Session = Depends(get_db)):
    return handler.check_in_appointment(db, appointment_id)


@router.post(
    "/{appointment_id}/cancel",
    response_model=AppointmentResponse,
    summary="Cancel Appointment",
    description="Updates the appointment status to cancelled. Cannot cancel an appointment that is already completed, cancelled, or marked no show. Returns 400 if the status transition is invalid.",
)
def cancel_appointment_route(appointment_id: str, db: Session = Depends(get_db)):
    return handler.cancel_appointment(db, appointment_id)


@router.post(
    "/{appointment_id}/complete",
    response_model=AppointmentResponse,
    summary="Complete Appointment",
    description="Updates the appointment status to completed. Only checked-in or in-progress appointments can be completed. Returns 400 if the status transition is invalid.",
)
def complete_appointment_route(appointment_id: str, db: Session = Depends(get_db)):
    return handler.complete_appointment(db, appointment_id)