""" System API endpoints """ import logging from typing import Dict, Any, List from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from sqlalchemy import func from sqlalchemy.orm import Session from ..core.database import get_db from ..core.scheduler import scheduler_manager from ..services.metube_client import MeTubeClient from ..models.playlist import PlaylistSubscription from ..models.video import VideoRecord, VideoStatus from ..core.config import settings logger = logging.getLogger(__name__) router = APIRouter() # Pydantic models for API responses class SystemStatus(BaseModel): """System status response""" total_playlists: int active_playlists: int total_videos: int pending_downloads: int active_downloads: int completed_downloads: int failed_downloads: int skipped_downloads: int metube_status: Dict[str, Any] class SchedulerStatus(BaseModel): """Scheduler status response""" running: bool jobs: List[Dict[str, Any]] class SyncResponse(BaseModel): """Sync response""" status: str synced_videos: int message: str @router.get("/status", response_model=SystemStatus) async def get_system_status(db: Session = Depends(get_db)): """Get overall system status""" try: # Get playlist statistics total_playlists = db.query(PlaylistSubscription).count() active_playlists = db.query(PlaylistSubscription).filter( PlaylistSubscription.enabled == True ).count() # Get video statistics total_videos = db.query(VideoRecord).count() pending_downloads = db.query(VideoRecord).filter( VideoRecord.status == VideoStatus.PENDING ).count() active_downloads = db.query(VideoRecord).filter( VideoRecord.status == VideoStatus.DOWNLOADING ).count() completed_downloads = db.query(VideoRecord).filter( VideoRecord.status == VideoStatus.COMPLETED ).count() failed_downloads = db.query(VideoRecord).filter( VideoRecord.status == VideoStatus.FAILED ).count() skipped_downloads = db.query(VideoRecord).filter( VideoRecord.status == VideoStatus.SKIPPED ).count() # Check MeTube connection metube_status = { "connected": False, "error": None } try: # Create a temporary MeTube client for health check client = MeTubeClient(settings.METUBE_URL) await client.connect() metube_status["connected"] = await client.health_check() await client.disconnect() except Exception as e: metube_status["error"] = str(e) logger.error(f"Error checking MeTube status: {e}") return SystemStatus( total_playlists=total_playlists, active_playlists=active_playlists, total_videos=total_videos, pending_downloads=pending_downloads, active_downloads=active_downloads, completed_downloads=completed_downloads, failed_downloads=failed_downloads, skipped_downloads=skipped_downloads, metube_status=metube_status ) except Exception as e: logger.error(f"Error getting system status: {e}") raise HTTPException(status_code=500, detail=f"Error getting system status: {str(e)}") @router.get("/scheduler/status", response_model=SchedulerStatus) async def get_scheduler_status(): """Get scheduler status and jobs""" try: running = scheduler_manager.scheduler and scheduler_manager.scheduler.running jobs = scheduler_manager.get_all_jobs() if running else [] return SchedulerStatus( running=running, jobs=jobs ) except Exception as e: logger.error(f"Error getting scheduler status: {e}") raise HTTPException(status_code=500, detail=f"Error getting scheduler status: {str(e)}") @router.post("/sync-metube", response_model=SyncResponse) async def sync_with_metube(db: Session = Depends(get_db)): """Manually sync video status with MeTube""" try: from ..services.video_service import VideoService service = VideoService(db) synced_count = await service.sync_with_metube() return SyncResponse( status="ok", synced_videos=synced_count, message=f"Successfully synced {synced_count} videos with MeTube" ) except Exception as e: logger.error(f"Error syncing with MeTube: {e}") raise HTTPException(status_code=500, detail=f"Error syncing with MeTube: {str(e)}") @router.get("/health") async def health_check(): """Simple health check endpoint""" try: # Basic health check - just return OK # More detailed health checks are done in the main app's health endpoint return { "status": "healthy", "service": "playlist-monitor", "version": "0.1.0" } except Exception as e: logger.error(f"Health check failed: {e}") raise HTTPException(status_code=503, detail="Service unhealthy")