import { NextRequest, NextResponse } from "next/server"; import { requirePaidApiUser } from "@/lib/api-auth"; import { createVideoJob } from "@/lib/jobs/create-job"; import { applyCreatePlaylistToItems, parseCreatePlaylistInput, } from "@/lib/jobs/resolve-playlist"; import { prisma } from "@/lib/db"; import type { CreateJobPayload } from "@/lib/types"; export async function POST(req: NextRequest) { const { error, user } = await requirePaidApiUser(req); if (error || !user) return error!; const body = (await req.json()) as CreateJobPayload & { createPlaylist?: unknown }; try { const createPlaylist = parseCreatePlaylistInput(body.createPlaylist); if (body.createPlaylist && !createPlaylist) { return NextResponse.json( { error: "createPlaylist requires a title. Optional: description, privacy (public|unlisted|private)", }, { status: 400 }, ); } const { items, playlist } = await applyCreatePlaylistToItems( user, body.items, createPlaylist, ); const job = await createVideoJob(user, { imagePath: body.imagePath, items, }); return NextResponse.json({ jobId: job.id, itemCount: job.items.length, status: job.status, playlist: playlist ? { id: playlist.id, title: playlist.title, privacy: playlist.privacy } : null, }); } catch (err) { const message = err instanceof Error ? err.message : "Failed to create job"; const status = message.includes("Quota exceeded") ? 403 : 400; return NextResponse.json({ error: message }, { status }); } } export async function GET(req: NextRequest) { const { error, user } = await requirePaidApiUser(req); if (error || !user) return error!; const limit = Math.min(Number(req.nextUrl.searchParams.get("limit")) || 20, 100); const jobs = await prisma.job.findMany({ where: { userId: user.id }, orderBy: { createdAt: "desc" }, take: limit, include: { items: { select: { id: true, audioFilename: true, title: true, status: true, youtubeVideoId: true, error: true, }, }, }, }); return NextResponse.json({ jobs: jobs.map((job) => ({ id: job.id, status: job.status, createdAt: job.createdAt.toISOString(), completedAt: job.completedAt?.toISOString() ?? null, items: job.items, })), }); }