"""Life-event CRUD nested under a scenario.""" from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import delete, select from sqlalchemy.ext.asyncio import AsyncSession from fire_planner.api.dependencies import get_session from fire_planner.api.schemas import LifeEventCreate, LifeEventOut, LifeEventPatch from fire_planner.db import LifeEvent, Scenario router = APIRouter(tags=["life-events"]) @router.get( "/scenarios/{scenario_id}/life-events", response_model=list[LifeEventOut], ) async def list_events( scenario_id: int, session: AsyncSession = Depends(get_session), ) -> list[LifeEvent]: scen = await session.get(Scenario, scenario_id) if scen is None: raise HTTPException(status_code=404, detail="Scenario not found") rows = (await session.execute( select(LifeEvent).where(LifeEvent.scenario_id == scenario_id).order_by( LifeEvent.year_start, LifeEvent.id))).scalars().all() return list(rows) @router.post( "/scenarios/{scenario_id}/life-events", response_model=LifeEventOut, status_code=201, ) async def create_event( scenario_id: int, payload: LifeEventCreate, session: AsyncSession = Depends(get_session), ) -> LifeEvent: scen = await session.get(Scenario, scenario_id) if scen is None: raise HTTPException(status_code=404, detail="Scenario not found") if payload.year_end is not None and payload.year_end < payload.year_start: raise HTTPException(status_code=400, detail="year_end < year_start") ev = LifeEvent(scenario_id=scenario_id, **payload.model_dump()) session.add(ev) await session.commit() await session.refresh(ev) return ev @router.patch( "/life-events/{event_id}", response_model=LifeEventOut, ) async def patch_event( event_id: int, payload: LifeEventPatch, session: AsyncSession = Depends(get_session), ) -> LifeEvent: ev = await session.get(LifeEvent, event_id) if ev is None: raise HTTPException(status_code=404, detail="Event not found") updates = payload.model_dump(exclude_unset=True) for k, v in updates.items(): setattr(ev, k, v) if ev.year_end is not None and ev.year_end < ev.year_start: raise HTTPException(status_code=400, detail="year_end < year_start") await session.commit() await session.refresh(ev) return ev @router.delete( "/life-events/{event_id}", status_code=204, response_model=None, ) async def delete_event( event_id: int, session: AsyncSession = Depends(get_session), ) -> None: ev = await session.get(LifeEvent, event_id) if ev is None: raise HTTPException(status_code=404, detail="Event not found") await session.execute(delete(LifeEvent).where(LifeEvent.id == event_id)) await session.commit()