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
from app.api.dependencies.database import get_async_session
from app.api.dependencies.auth import get_current_active_user
from app.schemas.appointment import (
AppointmentCreate,
AppointmentUpdate,
AppointmentResponse,
)
from app.models.appointment import Appointment
from app.models.patient import Patient
from app.models.doctor import Doctor
from app.models.user import User
router = APIRouter(prefix="/appointments", tags=["appointments"])
@router.post("/", response_model=AppointmentResponse)
async def create_appointment(
appointment_data: AppointmentCreate,
db: AsyncSession = Depends(get_async_session),
current_user: User = Depends(get_current_active_user),
):
# Verify patient exists
patient_result = await db.execute(
select(Patient).where(Patient.id == appointment_data.patient_id)
)
if not patient_result.scalar_one_or_none():
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Patient not found"
)
# Verify doctor exists
doctor_result = await db.execute(
select(Doctor).where(Doctor.id == appointment_data.doctor_id)
)
if not doctor_result.scalar_one_or_none():
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Doctor not found"
)
appointment = Appointment(**appointment_data.model_dump())
db.add(appointment)
await db.commit()
await db.refresh(appointment)
return appointment
@router.get("/", response_model=List[AppointmentResponse])
async def get_appointments(
skip: int = 0,
limit: int = 100,
db: AsyncSession = Depends(get_async_session),
current_user: User = Depends(get_current_active_user),
):
result = await db.execute(
select(Appointment)
.options(selectinload(Appointment.patient), selectinload(Appointment.doctor))
.offset(skip)
.limit(limit)
)
appointments = result.scalars().all()
return appointments
@router.get("/{appointment_id}", response_model=AppointmentResponse)
async def get_appointment(
appointment_id: int,
db: AsyncSession = Depends(get_async_session),
current_user: User = Depends(get_current_active_user),
):
result = await db.execute(
select(Appointment)
.options(selectinload(Appointment.patient), selectinload(Appointment.doctor))
.where(Appointment.id == appointment_id)
)
appointment = result.scalar_one_or_none()
if not appointment:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Appointment not found"
)
return appointment
@router.put(
"/{appointment_id}",
response_model=AppointmentResponse,
operation_id="update_appointment",
)
async def update_appointment(
appointment_id: int,
appointment_data: AppointmentUpdate,
db: AsyncSession = Depends(get_async_session),
current_user: User = Depends(get_current_active_user),
):
result = await db.execute(
select(Appointment).where(Appointment.id == appointment_id)
)
appointment = result.scalar_one_or_none()
if not appointment:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Appointment not found"
)
update_data = appointment_data.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(appointment, field, value)
await db.commit()
await db.refresh(appointment)
return appointment
@router.delete(
"/{appointment_id}",
operation_id="delete_appointment",
)
async def delete_appointment(
appointment_id: int,
db: AsyncSession = Depends(get_async_session),
current_user: User = Depends(get_current_active_user),
):
result = await db.execute(
select(Appointment).where(Appointment.id == appointment_id)
)
appointment = result.scalar_one_or_none()
if not appointment:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Appointment not found"
)
await db.delete(appointment)
await db.commit()
return {"message": "Appointment deleted successfully"}