import uuid from datetime import datetime, timezone from typing import Optional from fastapi import APIRouter, BackgroundTasks, HTTPException, Depends from app.models import IncidentCreate, IncidentUpdate from app.internal import firestore as fstore from app.internal.auth import require_admin_token router = APIRouter(prefix="/incidents", tags=["incidents"]) @router.get("") async def list_incidents(status: Optional[str] = None, type: Optional[str] = None): filters = {} if status: filters["status"] = status if type: filters["type"] = type return await fstore.collection_list("incidents", **filters) @router.post("/summarize") async def summarize_all_stale(background_tasks: BackgroundTasks): """Immediately run the summarizer pass on all stale incidents (don't wait for the next interval).""" from app.internal.summarizer import _run_summary_pass background_tasks.add_task(_run_summary_pass) return {"ok": True} @router.get("/{incident_id}") async def get_incident(incident_id: str): doc = await fstore.doc_get("incidents", incident_id) if not doc: raise HTTPException(404, f"Incident '{incident_id}' not found.") return doc @router.post("") async def create_incident(body: IncidentCreate, _: dict = Depends(require_admin_token)): now = datetime.now(timezone.utc).isoformat() incident_id = str(uuid.uuid4()) doc = { "incident_id": incident_id, "title": body.title, "type": body.type, "status": body.status, "location": body.location, "call_ids": body.call_ids, "summary": body.summary, "tags": body.tags, "started_at": now, "updated_at": now, } await fstore.doc_set("incidents", incident_id, doc, merge=False) return doc @router.put("/{incident_id}") async def update_incident(incident_id: str, body: IncidentUpdate, _: dict = Depends(require_admin_token)): doc = await fstore.doc_get("incidents", incident_id) if not doc: raise HTTPException(404, f"Incident '{incident_id}' not found.") updates = body.model_dump(exclude_none=True) updates["updated_at"] = datetime.now(timezone.utc).isoformat() await fstore.doc_update("incidents", incident_id, updates) return {**doc, **updates} @router.delete("/{incident_id}") async def delete_incident(incident_id: str, _: dict = Depends(require_admin_token)): doc = await fstore.doc_get("incidents", incident_id) if not doc: raise HTTPException(404, f"Incident '{incident_id}' not found.") await fstore.doc_delete("incidents", incident_id) return {"ok": True} @router.post("/{incident_id}/summarize") async def summarize_incident(incident_id: str, background_tasks: BackgroundTasks): """Immediately run the summarizer for a specific incident.""" from app.internal.summarizer import _summarize_incident inc = await fstore.doc_get("incidents", incident_id) if not inc: raise HTTPException(404, f"Incident '{incident_id}' not found.") background_tasks.add_task(_summarize_incident, inc) return {"ok": True, "incident_id": incident_id} @router.post("/{incident_id}/calls/{call_id}") async def link_call_to_incident(incident_id: str, call_id: str, _: dict = Depends(require_admin_token)): doc = await fstore.doc_get("incidents", incident_id) if not doc: raise HTTPException(404, f"Incident '{incident_id}' not found.") call_ids = doc.get("call_ids", []) if call_id not in call_ids: call_ids.append(call_id) await fstore.doc_update("incidents", incident_id, { "call_ids": call_ids, "updated_at": datetime.now(timezone.utc).isoformat(), }) await fstore.doc_update("calls", call_id, {"incident_id": incident_id}) return {"ok": True}