/**
 * POST /api/admin/backfill-platforms
 *
 * Iterates all brands with an active TrackedSite, fetches the brand domain's
 * HTML, runs server-side platform detection, and writes results to TrackedSite.
 * Superadmin only.
 *
 * Body options:
 *   { dryRun: true }                      — detect without writing
 *   { trackedSiteIds: string[] }          — limit to specific sites
 *   { force: true }                       — bypass 24h rate limit (via direct update)
 */

import { NextResponse } from "next/server";
import { requireSuperadmin } from "@/lib/admin-auth";
import { prisma } from "@/lib/prisma";
import { detectPlatformFromHtml } from "@/lib/site-tag/platform-signatures";
import { upsertDetectedPlatform } from "@/lib/site-tag/upsert-detected-platform";

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

const THROTTLE_MS = 250;
const FETCH_TIMEOUT_MS = 10_000;

function sleep(ms: number) {
  return new Promise<void>((r) => setTimeout(r, ms));
}

async function fetchHtml(url: string): Promise<{ html: string; headers: Record<string, string> } | null> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
  try {
    const res = await fetch(url, {
      signal: controller.signal,
      headers: { "User-Agent": "Mozilla/5.0 (compatible; meSEO-bot/1.0)" },
    });
    const headers: Record<string, string> = {};
    res.headers.forEach((v, k) => { headers[k.toLowerCase()] = v; });
    const html = await res.text();
    return { html: html.slice(0, 200_000), headers };
  } catch {
    return null;
  } finally {
    clearTimeout(timer);
  }
}

export async function POST(req: Request) {
  const denied = await requireSuperadmin();
  if (denied) return denied;

  let dryRun = false;
  let force = false;
  let trackedSiteIds: string[] | null = null;
  try {
    const body = await req.json().catch(() => ({})) as Record<string, unknown>;
    dryRun = body.dryRun === true;
    force = body.force === true;
    if (Array.isArray(body.trackedSiteIds)) trackedSiteIds = body.trackedSiteIds as string[];
  } catch { /* ignore */ }

  const where = {
    status: "active",
    ...(trackedSiteIds ? { id: { in: trackedSiteIds } } : {}),
  };

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

  const results: Array<{ domain: string; platform: string | null; hosting: string | null; skipped?: boolean; error?: string }> = [];

  for (const site of sites) {
    const domain = site.brand?.domain;
    if (!domain) { results.push({ domain: "", platform: null, hosting: null, skipped: true }); continue; }

    const url = domain.startsWith("http") ? domain : `https://${domain}`;
    await sleep(THROTTLE_MS);

    const fetched = await fetchHtml(url);
    if (!fetched) {
      results.push({ domain, platform: null, hosting: null, error: "fetch failed" });
      continue;
    }

    const { platform, hosting } = detectPlatformFromHtml(fetched.html, fetched.headers);

    if (!dryRun && platform) {
      try {
        if (force) {
          // Bypass the 24h rate limit by clearing sitePlatformDetectedAt first
          await prisma.trackedSite.update({
            where: { id: site.id },
            data: { sitePlatformDetectedAt: null },
          });
        }
        await upsertDetectedPlatform({ trackedSiteId: site.id, platform, hosting: hosting ?? undefined });
      } catch {
        results.push({ domain, platform: platform.name, hosting: hosting?.name ?? null, error: "write failed" });
        continue;
      }
    }

    results.push({ domain, platform: platform?.name ?? null, hosting: hosting?.name ?? null });
  }

  const detected = results.filter((r) => r.platform).length;
  const failed = results.filter((r) => r.error).length;

  return NextResponse.json({
    ok: true,
    dryRun,
    force,
    total: sites.length,
    detected,
    failed,
    results,
  });
}
