/**
 * GET /api/cron/site-tag-rollup
 *
 * Hourly cron that pre-aggregates yesterday + today's TrackedEvent
 * page-view and session data per brand into SiteTagDailyRollup rows.
 *
 * This turns the expensive 30-day groupBy scans in getTrafficSummary
 * (hash-aggregate over 1M+ rows) into a 30-row indexed lookup.
 *
 * Schedule: "0 * * * *" (every hour on the hour)
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { computeOneDayRollup } from "@/lib/services/site-tag-rollup-compute";

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

function utcDayStart(d: Date): Date {
  return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
}

export async function GET(req: Request) {
  const cronSecret = process.env.CRON_SECRET;
  if (!cronSecret) {
    return NextResponse.json({ error: "Server misconfigured: CRON_SECRET unset" }, { status: 500 });
  }
  const authHeader = req.headers.get("authorization");
  const querySecret = new URL(req.url).searchParams.get("secret");
  if (authHeader !== `Bearer ${cronSecret}` && querySecret !== cronSecret) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const now = new Date();
  // Recompute today + yesterday only. Older days are immutable; historical
  // backfill is handled via POST /api/admin/backfill-site-tag-rollup.
  // Processing 30 days x all brands per run caused timeout-induced starvation
  // where high-volume brands at the end of the list never got rows written.
  const today = utcDayStart(now);
  const yesterday = new Date(today.getTime() - 86_400_000);
  const datesToProcess: Date[] = [today, yesterday];

  // Per-brand budget: if a single brand's two-day computation exceeds this,
  // log and skip so one slow brand cannot starve the rest of the fleet.
  const PER_BRAND_BUDGET_MS = 20_000;

  const sites = await prisma.trackedSite.findMany({
    select: { id: true, brandId: true, requireSuccessConfirmed: true },
    where: { brandId: { not: undefined } },
  });

  let written = 0;
  let skipped = 0;
  let timedOut = 0;

  for (const site of sites) {
    const brandStart = Date.now();

    for (const date of datesToProcess) {
      // Per-brand budget guard: skip remaining days for this brand if over budget.
      if (Date.now() - brandStart > PER_BRAND_BUDGET_MS) {
        console.warn("[site-tag-rollup] per-brand budget exceeded, skipping", {
          brandId: site.brandId,
          date: date.toISOString(),
        });
        timedOut++;
        break;
      }

      try {
        await computeOneDayRollup(site.id, site.brandId, date, site.requireSuccessConfirmed);
        written++;
      } catch (err) {
        console.warn("[site-tag-rollup] day computation failed", {
          brandId: site.brandId,
          date: date.toISOString(),
          err: err instanceof Error ? err.message : "unknown",
        });
        skipped++;
      }
    }
  }

  console.log("[site-tag-rollup] complete", { written, skipped, timedOut, sites: sites.length });
  return NextResponse.json({ ok: true, written, skipped, timedOut, sites: sites.length });
}
