import { NextRequest, NextResponse } from "next/server"; import { db } from "@/lib/db"; // ── Auth ───────────────────────────────────────────────────────────────────── function isAuthorized(req: NextRequest): boolean { const apiKey = process.env.API_SECRET_KEY; if (!apiKey) return false; const authHeader = req.headers.get("authorization") ?? ""; if (authHeader.startsWith("Bearer ")) return authHeader.slice(7) === apiKey; return (req.headers.get("x-api-key") ?? "") === apiKey; } // ── GET /api/ext/projects/[projectCode]/episodes ────────────────────────────── // // Returns the list of distinct episodes in a project along with their shot // codes, sequences, and EDL data. Useful for populating episode selectors in // pipeline tools. // // Query params (optional): // shotNames Pass "1" to include the full shot code list per episode (default off) // // Example: // GET /api/ext/projects/UNG_108/episodes // GET /api/ext/projects/UNG_108/episodes?shotNames=1 export async function GET( req: NextRequest, { params }: { params: Promise<{ projectCode: string }> } ) { if (!isAuthorized(req)) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const { projectCode } = await params; const { searchParams } = new URL(req.url); const includeShotNames = searchParams.get("shotNames") === "1"; const project = await db.project.findUnique({ where: { code: projectCode }, select: { id: true, name: true, code: true, showId: true }, }); if (!project) { return NextResponse.json({ error: "Project not found" }, { status: 404 }); } // Fetch all shots grouped by episode const shots = await db.shot.findMany({ where: { projectId: project.id }, orderBy: [{ episode: "asc" }, { shotCode: "asc" }], select: { id: true, shotCode: true, episode: true, sequence: true, status: true, exrOutput: true, seqTimecodeStart: true, seqTimecodeEnd: true, sourceClip: true, timecodeStart: true, timecodeEnd: true, clipDuration: true, }, }); // Group by episode const episodeMap = new Map< string, { episode: string; shotCount: number; sequences: string[]; shots?: typeof shots; } >(); for (const shot of shots) { const ep = shot.episode ?? "(none)"; if (!episodeMap.has(ep)) { episodeMap.set(ep, { episode: ep, shotCount: 0, sequences: [], shots: [] }); } const entry = episodeMap.get(ep)!; entry.shotCount++; const seq = shot.sequence ?? ""; if (seq && !entry.sequences.includes(seq)) { entry.sequences.push(seq); } if (includeShotNames) { entry.shots!.push(shot); } } const episodes = Array.from(episodeMap.values()).map((e) => { if (!includeShotNames) { const { shots: _omit, ...rest } = e; return rest; } return e; }); return NextResponse.json({ project, episodes }); }