"""Patient CRUD routes.""" from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from core import data_manager, google_services from api.deps import get_current_session, require_admin_session router = APIRouter(prefix="/api/patients", tags=["patients"]) class PatientCreate(BaseModel): name: str email: str = "" address: str = "" notes: str = "" class PatientUpdate(BaseModel): name: str | None = None email: str | None = None address: str | None = None notes: str | None = None def _geocode(address: str) -> tuple[float | None, float | None]: try: result = google_services.geocode_address(address) if result: return result[0], result[1] except Exception: pass return None, None @router.get("") def list_patients(session: dict = Depends(get_current_session)): return data_manager.get_all_patients() @router.get("/{patient_id}") def get_patient(patient_id: str, session: dict = Depends(get_current_session)): p = data_manager.get_patient_by_id(patient_id) if not p: raise HTTPException(status_code=404, detail="Patient not found") return p @router.post("") def create_patient(req: PatientCreate, session: dict = Depends(require_admin_session)): if not req.name: raise HTTPException(status_code=400, detail="Patient name is required") lat, lng = _geocode(req.address) if req.address else (None, None) patient_data = { "name": req.name, "email": req.email, "address": req.address, "notes": req.notes, "lat": lat, "lng": lng, } new_patient = data_manager.add_patient(patient_data) data_manager.log_action( session["current_user"], "ADD_PATIENT", f"Added patient: {req.name} ({new_patient['id']})", ) return new_patient @router.put("/{patient_id}") def update_patient(patient_id: str, req: PatientUpdate, session: dict = Depends(require_admin_session)): existing = data_manager.get_patient_by_id(patient_id) if not existing: raise HTTPException(status_code=404, detail="Patient not found") updates: dict = {} if req.name is not None: updates["name"] = req.name if req.email is not None: updates["email"] = req.email if req.notes is not None: updates["notes"] = req.notes if req.address is not None: updates["address"] = req.address if req.address != existing.get("address"): lat, lng = _geocode(req.address) if req.address else (None, None) updates["lat"] = lat updates["lng"] = lng updated = data_manager.update_patient(patient_id, updates) data_manager.log_action( session["current_user"], "UPDATE_PATIENT", f"Updated patient: {updated['name']} ({patient_id})", ) return updated @router.delete("/{patient_id}") def delete_patient(patient_id: str, session: dict = Depends(require_admin_session)): p = data_manager.get_patient_by_id(patient_id) if not p: raise HTTPException(status_code=404, detail="Patient not found") ok = data_manager.delete_patient(patient_id) if not ok: raise HTTPException(status_code=500, detail="Delete failed") data_manager.log_action( session["current_user"], "DELETE_PATIENT", f"Deleted patient: {p['name']} ({patient_id})", ) return {"ok": True}