from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func, and_ from datetime import datetime, timezone, timedelta from typing import List from app.database import get_db from app.models import Job, JobExecution, Backup from app.schemas import DashboardStats, JobExecution as JobExecutionSchema router = APIRouter(prefix="/api/dashboard", tags=["dashboard"]) @router.get("/", response_model=DashboardStats) async def get_dashboard_stats(db: AsyncSession = Depends(get_db)): # Active jobs count (enabled jobs) active_jobs_result = await db.execute( select(func.count(Job.id)).where(Job.enabled == True) ) active_jobs = active_jobs_result.scalar() or 0 # Total backups count total_backups_result = await db.execute(select(func.count(Backup.id))) total_backups = total_backups_result.scalar() or 0 # Storage used bytes (sum of all backup sizes) storage_used_result = await db.execute(select(func.sum(Backup.size_bytes))) storage_used_bytes = storage_used_result.scalar() or 0 # Recent failures count (last 24 hours) twenty_four_hours_ago = datetime.now(timezone.utc) - timedelta(hours=24) recent_failures_result = await db.execute( select(func.count(JobExecution.id)).where( and_( JobExecution.status == "failed", JobExecution.completed_at >= twenty_four_hours_ago, ) ) ) recent_failures = recent_failures_result.scalar() or 0 # Recent executions (last 10, ordered by started_at desc) recent_executions_result = await db.execute( select(JobExecution).order_by(JobExecution.started_at.desc()).limit(10) ) recent_executions = recent_executions_result.scalars().all() return DashboardStats( active_jobs=active_jobs, total_backups=total_backups, storage_used_bytes=storage_used_bytes, recent_failures=recent_failures, recent_executions=list(recent_executions), )