""" Call History API — Read-only access to persisted call records, transcript chunks, and recording files for the dashboard. Thin HTTP layer over the shared data functions in call_persistence. """ import os from datetime import datetime from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import FileResponse from sqlalchemy.ext.asyncio import AsyncSession from db.database import get_db from services import call_persistence as store router = APIRouter() @router.get("/history") async def list_history( limit: int = Query(50, ge=1, le=500), offset: int = Query(0, ge=0), number: str | None = None, status: str | None = None, since: datetime | None = None, until: datetime | None = None, db: AsyncSession = Depends(get_db), ): """Paged list of past calls, newest first.""" rows = await store.search_history( db, number=number, status=status, since=since, until=until, limit=limit, offset=offset, ) return [store.record_summary(r) for r in rows] @router.get("/{call_id}/record") async def get_record(call_id: str, db: AsyncSession = Depends(get_db)): """Full CallRecord with classification_timeline.""" row = await store.get_record(db, call_id) if not row: raise HTTPException(status_code=404, detail=f"Call {call_id} not found") return store.record_detail(row) @router.get("/{call_id}/transcript") async def get_transcript(call_id: str, db: AsyncSession = Depends(get_db)): """Ordered transcript chunks for a call.""" rows = await store.get_transcript_chunks(db, call_id) return [store.chunk_to_dict(c) for c in rows] @router.get("/{call_id}/recording") async def get_recording(call_id: str, db: AsyncSession = Depends(get_db)): """Stream the WAV recording for a call.""" row = await store.latest_recording(db, call_id) if not row or not row.path: raise HTTPException(status_code=404, detail="Recording not found") if not os.path.exists(row.path): raise HTTPException(status_code=404, detail="Recording file missing on disk") return FileResponse(row.path, media_type="audio/wav", filename=os.path.basename(row.path))