/**
 * POST /api/site-audit/run
 * Creates a SiteAuditRun, kicks the worker via waitUntil, returns runId.
 *
 * waitUntil keeps the Lambda alive for up to maxDuration after the response
 * is sent, so the worker starts immediately rather than depending on the
 * 15-minute cleanup cron.
 */
import { NextResponse } from "next/server";
import { waitUntil } from "@vercel/functions";
import { auth } from "@clerk/nextjs/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { verifyBrandAccess } from "@/lib/brand-access";
import { runSiteAudit } from "@/lib/services/site-audit-runner";

export const dynamic = "force-dynamic";
export const maxDuration = 800;

export async function POST(req: Request) {
  const { userId: clerkId } = await auth();
  if (!clerkId) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  let brandId: string;
  try {
    const body = (await req.json()) as { brandId?: string };
    brandId = body.brandId ?? "";
  } catch {
    return NextResponse.json({ error: "Invalid JSON" }, { status: 400 });
  }
  if (!brandId) return NextResponse.json({ error: "brandId required" }, { status: 400 });

  // Resolve DB user by email (same path as the dashboard) so verifyBrandAccess
  // receives the DB User.id, not the Clerk user id.
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const allowed = await verifyBrandAccess(user.id, brandId);
  console.warn("[site-audit/run] access check", { clerkId, dbUserId: user.id, brandId, allowed });
  if (!allowed) return NextResponse.json({ error: "Forbidden" }, { status: 403 });

  // Load brand separately now that access is confirmed.
  // Two separate failure modes must be distinguishable in production:
  //   (a) query threw  -- Prisma runtime error (e.g. missing DB column, bad schema)
  //   (b) query null   -- brand absent (deleted after access check, or bad id)
  let brand: { id: string; domain: string; renderTier: string } | null;
  try {
    brand = await prisma.brand.findUnique({
      where: { id: brandId },
      select: { id: true, domain: true, renderTier: true },
    });
  } catch (err) {
    const detail = err instanceof Error ? err.message : String(err);
    console.error("[site-audit/run] brand query threw -- likely schema mismatch:", detail, { brandId, dbUserId: user.id });
    return NextResponse.json(
      { error: "Brand query failed", detail: detail.slice(0, 300) },
      { status: 500 },
    );
  }
  if (!brand) return NextResponse.json({ error: "Brand not found" }, { status: 404 });

  // Cancel any in-progress run before starting a new one
  await prisma.siteAuditRun.updateMany({
    where: { brandId, status: { in: ["pending", "crawling", "processing"] } },
    data: { status: "failed", errorMessage: "Superseded by new run" },
  });

  const run = await prisma.siteAuditRun.create({
    data: { brandId, status: "pending", startedAt: new Date() },
    select: { id: true },
  });

  // Keep the Lambda alive after the response so the worker runs immediately.
  // The cleanup cron at /api/cron/site-audit-cleanup re-kicks via the process
  // route if this invocation is interrupted mid-crawl.
  waitUntil(
    runSiteAudit(run.id).catch((err: unknown) =>
      console.error(
        "[site-audit/run] waitUntil runner failed:",
        err instanceof Error ? err.message : err,
      ),
    ),
  );

  return NextResponse.json({ runId: run.id });
}
