/**
 * POST /api/cron/paid-media-rebuild
 *
 * Scheduled rebuild of the paid-media read-cache tables:
 *   1. Backfill channelGroup on TrackedSession rows missing it
 *   2. Rebuild VisitorProfile aggregations
 *   3. Rebuild HouseholdCluster groupings
 *   4. Rebuild AttributionPath for recent conversions
 *
 * Runs per-brand across all brands with an active TrackedSite.
 * Designed for a Vercel cron (daily at 3 AM UTC) but safe to call
 * manually. Idempotent — every step upserts by unique key.
 *
 * Auth: Authorization: Bearer ${CRON_SECRET} (standard cron pattern) OR superadmin.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { buildAttributionPaths } from "@/lib/services/attribution";
import {
  rebuildVisitorProfiles,
  rebuildHouseholdClusters,
  backfillChannelGroups,
} from "@/lib/services/visitor-profiles";
import { matchOttImpressions } from "@/lib/services/ott-attribution";

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

export async function POST(req: Request) {
  const cronSecret = process.env.CRON_SECRET;
  const authHeader = req.headers.get("authorization");
  const querySecret = new URL(req.url).searchParams.get("secret");
  const isCron = cronSecret && (authHeader === `Bearer ${cronSecret}` || querySecret === cronSecret);
  if (!isCron) {
    // Allow manual invocation by superadmin as a fallback.
    const { requireSuperadmin } = await import("@/lib/admin-auth");
    const denied = await requireSuperadmin();
    if (denied) return denied;
  }

  const t0 = Date.now();
  const { searchParams } = new URL(req.url);
  const targetBrandId = searchParams.get("brandId");

  const forceReclassify = searchParams.get("force") === "true";

  const sites = await prisma.trackedSite.findMany({
    where: targetBrandId
      ? { brandId: targetBrandId, status: "active" }
      : { status: "active" },
    select: { brandId: true, brand: { select: { name: true } } },
  });

  const results: Array<{
    brand: string;
    channels: { updated: number };
    profiles: { created: number };
    clusters: { created: number };
    paths: { created: number };
  }> = [];

  for (const site of sites) {
    const brandId = site.brandId;
    const name = site.brand.name;
    try {
      const ch = await backfillChannelGroups(brandId, { force: forceReclassify });
      const ott = await matchOttImpressions(brandId).catch(() => ({ matched: 0 }));
      const pr = await rebuildVisitorProfiles(brandId);
      const cl = await rebuildHouseholdClusters(brandId);
      const at = await buildAttributionPaths(brandId, { since: new Date(Date.now() - 90 * 86_400_000) });
      results.push({
        brand: name,
        channels: { updated: ch.updated },
        profiles: { created: pr.profilesCreated },
        clusters: { created: cl.clustersCreated },
        paths: { created: at.pathsCreated },
      });
    } catch (err) {
      console.error("[cron/paid-media-rebuild] brand failed", {
        brandId,
        name,
        err: err instanceof Error ? err.message : String(err),
      });
      results.push({
        brand: name,
        channels: { updated: 0 },
        profiles: { created: 0 },
        clusters: { created: 0 },
        paths: { created: 0 },
      });
    }
  }

  const elapsed = Date.now() - t0;
  console.info("[cron/paid-media-rebuild] complete", {
    brands: sites.length,
    elapsed,
    results,
  });

  return NextResponse.json({
    ok: true,
    brands: sites.length,
    elapsed,
    results,
  });
}
