import { query, queryOne, run } from "@/lib/db"; import { getToken } from "next-auth/jwt"; export const dynamic = "force-dynamic"; // Disable caching // Ensure the user is an admin async function verifyAdmin(request) { const token = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET || "your-fallback-secret-should-be-at-least-32-chars", }); if (!token) { return { authorized: false, error: "Unauthorized", status: 401 }; } if (token.role !== "admin") { return { authorized: false, error: "Admin access required", status: 403 }; } return { authorized: true, token }; } export async function GET(request) { try { // Verify admin access const { authorized, error, status } = await verifyAdmin(request); if (!authorized) { return Response.json({ error }, { status }); } // Get the total number of clues for calculating progress const clueCountResult = await queryOne( "SELECT COUNT(*) as total FROM clues" ); const totalClues = clueCountResult?.total || 0; // Get all teams with member count and clues found // Modified to exclude skipped clues from cluesFound count const teams = await query(` SELECT t.id, t.name, t.code, COUNT(DISTINCT u.id) as memberCount, COUNT(DISTINCT CASE WHEN tc.skipped = 0 OR tc.skipped IS NULL THEN tc.clue_id END) as cluesFound, MAX(tc.found_at) as lastActivity FROM teams t LEFT JOIN users u ON t.id = u.team_id LEFT JOIN team_clues tc ON t.id = tc.team_id GROUP BY t.id HAVING memberCount > 0 ORDER BY cluesFound DESC, lastActivity ASC `); // Enhance team data with total clues const teamsWithProgress = teams.map((team) => ({ ...team, totalClues, progress: totalClues > 0 ? Math.round((team.cluesFound / totalClues) * 100) : 0, })); return Response.json(teamsWithProgress, { headers: { "Cache-Control": "no-store, no-cache, must-revalidate", Pragma: "no-cache", Expires: "0", }, }); } catch (error) { console.error("Admin leaderboard error:", error); return Response.json( { error: "Failed to fetch leaderboard data: " + error.message }, { status: 500 } ); } }