"""API endpoints for file system-based summary management.""" from fastapi import APIRouter, HTTPException, Path, Query from pydantic import BaseModel, Field from typing import List, Dict, Any, Optional import logging from ..services.summary_storage import storage_service logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/summaries", tags=["file-summaries"]) class SummaryResponse(BaseModel): """Response model for a single summary.""" video_id: str generated_at: str model: str summary: str key_points: List[str] main_themes: List[str] actionable_insights: List[str] confidence_score: float processing_metadata: Dict[str, Any] cost_data: Dict[str, Any] transcript_length: int file_path: str file_size_bytes: int file_created_at: str file_modified_at: str class SummaryListResponse(BaseModel): """Response model for multiple summaries.""" video_id: str summaries: List[SummaryResponse] total_summaries: int class SummaryStatsResponse(BaseModel): """Response model for summary statistics.""" total_videos_with_summaries: int total_summaries: int total_size_bytes: int total_size_mb: float model_distribution: Dict[str, int] video_ids: List[str] @router.get("/video/{video_id}", response_model=SummaryListResponse) async def get_video_summaries( video_id: str = Path(..., description="YouTube video ID"), ): """Get all summaries for a specific video.""" try: summaries_data = storage_service.list_summaries(video_id) # Convert to Pydantic models summaries = [SummaryResponse(**summary) for summary in summaries_data] return SummaryListResponse( video_id=video_id, summaries=summaries, total_summaries=len(summaries) ) except Exception as e: logger.error(f"Failed to get summaries for video {video_id}: {e}") raise HTTPException( status_code=500, detail=f"Failed to retrieve summaries: {str(e)}" ) @router.get("/video/{video_id}/{timestamp}", response_model=SummaryResponse) async def get_specific_summary( video_id: str = Path(..., description="YouTube video ID"), timestamp: str = Path(..., description="Summary timestamp") ): """Get a specific summary by video ID and timestamp.""" try: summary_data = storage_service.get_summary(video_id, timestamp) if not summary_data: raise HTTPException( status_code=404, detail=f"Summary not found for video {video_id} with timestamp {timestamp}" ) return SummaryResponse(**summary_data) except HTTPException: raise except Exception as e: logger.error(f"Failed to get summary {video_id}/{timestamp}: {e}") raise HTTPException( status_code=500, detail=f"Failed to retrieve summary: {str(e)}" ) @router.get("/stats", response_model=SummaryStatsResponse) async def get_summary_stats(): """Get statistics about all stored summaries.""" try: stats = storage_service.get_summary_stats() return SummaryStatsResponse(**stats) except Exception as e: logger.error(f"Failed to get summary stats: {e}") raise HTTPException( status_code=500, detail=f"Failed to retrieve statistics: {str(e)}" ) @router.get("/videos", response_model=List[str]) async def list_videos_with_summaries(): """Get list of video IDs that have summaries.""" try: video_ids = storage_service.get_videos_with_summaries() return video_ids except Exception as e: logger.error(f"Failed to list videos with summaries: {e}") raise HTTPException( status_code=500, detail=f"Failed to retrieve video list: {str(e)}" ) @router.delete("/video/{video_id}/{timestamp}") async def delete_summary( video_id: str = Path(..., description="YouTube video ID"), timestamp: str = Path(..., description="Summary timestamp") ): """Delete a specific summary.""" try: success = storage_service.delete_summary(video_id, timestamp) if not success: raise HTTPException( status_code=404, detail=f"Summary not found for video {video_id} with timestamp {timestamp}" ) return {"message": f"Summary deleted successfully", "video_id": video_id, "timestamp": timestamp} except HTTPException: raise except Exception as e: logger.error(f"Failed to delete summary {video_id}/{timestamp}: {e}") raise HTTPException( status_code=500, detail=f"Failed to delete summary: {str(e)}" ) @router.post("/video/{video_id}/generate") async def trigger_summary_generation( video_id: str = Path(..., description="YouTube video ID"), force: bool = Query(False, description="Force regeneration even if summaries exist") ): """Trigger summary generation for a video.""" try: # Check if summaries already exist existing_summaries = storage_service.list_summaries(video_id) if existing_summaries and not force: return { "message": "Summaries already exist for this video", "video_id": video_id, "existing_summaries": len(existing_summaries), "use_force_parameter": "Set force=true to regenerate" } # TODO: Integrate with actual summary generation pipeline # For now, return a placeholder response return { "message": "Summary generation would be triggered here", "video_id": video_id, "force": force, "note": "This endpoint will be connected to the DeepSeek summarization pipeline" } except Exception as e: logger.error(f"Failed to trigger summary generation for {video_id}: {e}") raise HTTPException( status_code=500, detail=f"Failed to trigger summary generation: {str(e)}" )