from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, status, Request from sqlalchemy.orm import Session from datetime import date from app.api.deps import get_db, get_current_read_user, get_current_operator_user from app.crud.crud_ppr import ppr as crud_ppr from app.crud.crud_journal import journal as crud_journal from app.schemas.ppr import PPR, PPRCreate, PPRUpdate, PPRStatus, PPRStatusUpdate, Journal from app.models.ppr import User from app.core.utils import get_client_ip router = APIRouter() @router.get("/", response_model=List[PPR]) async def get_pprs( request: Request, skip: int = 0, limit: int = 100, status: Optional[PPRStatus] = None, date_from: Optional[date] = None, date_to: Optional[date] = None, db: Session = Depends(get_db), current_user: User = Depends(get_current_read_user) ): """Get PPR records with optional filtering""" pprs = crud_ppr.get_multi( db, skip=skip, limit=limit, status=status, date_from=date_from, date_to=date_to ) return pprs @router.post("/", response_model=PPR) async def create_ppr( request: Request, ppr_in: PPRCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Create a new PPR record""" client_ip = get_client_ip(request) ppr = crud_ppr.create(db, obj_in=ppr_in, created_by=current_user.username, user_ip=client_ip) # Send real-time update via WebSocket if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "ppr_created", "data": { "id": ppr.id, "ac_reg": ppr.ac_reg, "status": ppr.status.value } }) return ppr @router.post("/public", response_model=PPR) async def create_public_ppr( request: Request, ppr_in: PPRCreate, db: Session = Depends(get_db) ): """Create a new PPR record (public endpoint, no authentication required)""" client_ip = get_client_ip(request) # For public submissions, use a default created_by or None ppr = crud_ppr.create(db, obj_in=ppr_in, created_by="public", user_ip=client_ip) # Send real-time update via WebSocket if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "ppr_created", "data": { "id": ppr.id, "ac_reg": ppr.ac_reg, "status": ppr.status.value } }) return ppr @router.get("/{ppr_id}", response_model=PPR) async def get_ppr( ppr_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_read_user) ): """Get a specific PPR record""" ppr = crud_ppr.get(db, ppr_id=ppr_id) if not ppr: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="PPR record not found" ) return ppr @router.put("/{ppr_id}", response_model=PPR) async def update_ppr( request: Request, ppr_id: int, ppr_in: PPRUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Update a PPR record""" db_ppr = crud_ppr.get(db, ppr_id=ppr_id) if not db_ppr: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="PPR record not found" ) client_ip = get_client_ip(request) ppr = crud_ppr.update(db, db_obj=db_ppr, obj_in=ppr_in, user=current_user.username, user_ip=client_ip) # Send real-time update if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "ppr_updated", "data": { "id": ppr.id, "ac_reg": ppr.ac_reg, "status": ppr.status.value } }) return ppr @router.patch("/{ppr_id}", response_model=PPR) async def patch_ppr( request: Request, ppr_id: int, ppr_in: PPRUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Partially update a PPR record (only provided fields will be updated)""" db_ppr = crud_ppr.get(db, ppr_id=ppr_id) if not db_ppr: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="PPR record not found" ) client_ip = get_client_ip(request) ppr = crud_ppr.update(db, db_obj=db_ppr, obj_in=ppr_in, user=current_user.username, user_ip=client_ip) # Send real-time update if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "ppr_updated", "data": { "id": ppr.id, "ac_reg": ppr.ac_reg, "status": ppr.status.value } }) return ppr @router.patch("/{ppr_id}/status", response_model=PPR) async def update_ppr_status( request: Request, ppr_id: int, status_update: PPRStatusUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Update PPR status (LANDED, DEPARTED, etc.)""" client_ip = get_client_ip(request) ppr = crud_ppr.update_status( db, ppr_id=ppr_id, status=status_update.status, timestamp=status_update.timestamp, user=current_user.username, user_ip=client_ip ) if not ppr: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="PPR record not found" ) # Send real-time update if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "status_update", "data": { "id": ppr.id, "ac_reg": ppr.ac_reg, "status": ppr.status.value, "timestamp": ppr.landed_dt.isoformat() if ppr.landed_dt else (ppr.departed_dt.isoformat() if ppr.departed_dt else None) } }) return ppr @router.delete("/{ppr_id}", response_model=PPR) async def delete_ppr( request: Request, ppr_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Delete (soft delete) a PPR record""" client_ip = get_client_ip(request) ppr = crud_ppr.delete(db, ppr_id=ppr_id, user=current_user.username, user_ip=client_ip) if not ppr: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="PPR record not found" ) # Send real-time update if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "ppr_deleted", "data": { "id": ppr.id, "ac_reg": ppr.ac_reg } }) return ppr @router.get("/{ppr_id}/journal", response_model=List[Journal]) async def get_ppr_journal( ppr_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_read_user) ): """Get journal entries for a specific PPR""" # Verify PPR exists ppr = crud_ppr.get(db, ppr_id=ppr_id) if not ppr: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="PPR record not found" ) return crud_journal.get_by_ppr_id(db, ppr_id=ppr_id)