import { NextResponse } from "next/server"; import { gte, sql } from "drizzle-orm"; import { db } from "@/lib/db"; import { claws, tasks } from "@/lib/db/schema"; import { redis, getGlobalStats, getRegionStats, getHourlyActivity, } from "@/lib/redis"; export async function GET() { try { const globalStats = await getGlobalStats(); const regionStats = await getRegionStats(); const hourlyRaw = await getHourlyActivity(); // Convert hourly data to array format const hourlyActivity = Object.entries(hourlyRaw).map(([hour, count]) => ({ hour: hour.split("T")[1] + ":00", count, })); const now = Date.now(); const fiveMinutesAgo = now - 300_000; const activeClaws = await redis.zcount( "active:claws", fiveMinutesAgo, "+inf" ); const totalClawsResult = await db .select({ count: sql`count(*)` }) .from(claws); const totalClaws = totalClawsResult[0]?.count ?? 0; const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0); const tasksTodayResult = await db .select({ count: sql`count(*)` }) .from(tasks) .where(gte(tasks.timestamp, todayStart)); const tasksToday = tasksTodayResult[0]?.count ?? 0; const avgDurationResult = await db .select({ avg: sql`AVG(${tasks.durationMs})` }) .from(tasks) .where(gte(tasks.timestamp, todayStart)); const avgTaskDuration = avgDurationResult[0]?.avg ? Math.round(avgDurationResult[0].avg) : 0; // Convert region stats from string values to numbers const regionBreakdown: Record = {}; for (const [key, val] of Object.entries(regionStats)) { regionBreakdown[key] = parseInt(val, 10) || 0; } return NextResponse.json({ totalClaws, activeClaws, tasksToday, tasksTotal: parseInt(globalStats.total_tasks ?? "0", 10), avgTaskDuration, regionBreakdown, hourlyActivity, }); } catch (error) { console.error("Stats error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } }