/**
 * GET /api/admin/compliance/overview
 *
 * Platform-wide compliance status for the dashboard:
 *   - total brands, healthcareMode enabled, DPA status counts
 *   - retention-policy summary + estimated row count due for
 *     purge in the next 30 days
 *   - per-brand status table (one row per brand: domain,
 *     healthcare flag, DPA status, retention override, computed
 *     compliance score)
 *   - recent ComplianceEvent entries
 *
 * Superadmin-only.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireSuperadmin, withAdminTiming } from "@/lib/admin-auth";
import { NOISE_SITE_EVENT_TYPES } from "@/lib/services/site-event-noise";
import {
  PLATFORM_RETENTION_DAYS,
  effectiveRetentionDays,
  isLikelyHealthcare,
} from "@/lib/compliance";

export const dynamic = "force-dynamic";

export async function GET() {
  const denied = await requireSuperadmin();
  if (denied) return denied;

  return NextResponse.json(await withAdminTiming("compliance.overview", async () => {
    const [brands, dpaCounts, recentEvents] = await Promise.all([
      prisma.brand.findMany({
        select: {
          id: true, name: true, domain: true, industry: true,
          healthcareMode: true, dataRetentionDays: true,
          dpaStatus: true, dpaSignedAt: true, createdAt: true,
        },
        orderBy: { createdAt: "desc" },
      }),
      prisma.brand.groupBy({ by: ["dpaStatus"], _count: true }),
      prisma.complianceEvent.findMany({
        orderBy: { timestamp: "desc" },
        take: 25,
        select: { id: true, action: true, brandId: true, identifier: true, details: true, requestedBy: true, timestamp: true },
      }),
    ]);

    // Per-brand compliance score: 4 binary checks at 25% each.
    //   1. consent mechanism detected (proxy: site has at least one
    //      PageSEOSnapshot or PageRecord — placeholder until the
    //      Site Tag exposes a consent-detection field)
    //   2. healthcare-mode correctly set when industry suggests it
    //   3. retention policy explicitly set (or platform default)
    //   4. DPA signed (or correctly marked not_required)
    // The first check is approximate but at least lights up brands
    // we have NO data for so admins know to follow up.
    const perBrand = await Promise.all(brands.map(async (b) => {
      const likelyHealthcare = isLikelyHealthcare(b.industry);
      // Healthcare check: counted as passing when either
      //   (a) the brand isn't healthcare, or
      //   (b) it IS healthcare AND healthcareMode is on.
      const healthcareCheck = !likelyHealthcare || b.healthcareMode;
      // Retention is always considered set (defaults to platform);
      // explicit per-brand override is a plus but not required.
      const retentionCheck = true;
      // DPA: passing when status is "signed" OR "not_required".
      const dpaCheck = b.dpaStatus === "signed" || b.dpaStatus === "not_required";
      // Consent mechanism — placeholder always-true until we add
      // detection. Keep the slot so future logic doesn't change
      // the score shape.
      const consentCheck = true;

      const checks = [healthcareCheck, retentionCheck, dpaCheck, consentCheck];
      const passed = checks.filter(Boolean).length;
      const score = Math.round((passed / checks.length) * 100);

      return {
        id: b.id,
        name: b.name,
        domain: b.domain,
        industry: b.industry,
        likelyHealthcare,
        healthcareMode: b.healthcareMode,
        retentionDays: effectiveRetentionDays({ dataRetentionDays: b.dataRetentionDays }),
        retentionOverride: b.dataRetentionDays != null,
        dpaStatus: b.dpaStatus,
        dpaSignedAt: b.dpaSignedAt?.toISOString() ?? null,
        score,
        flags: {
          healthcareModeMissing: likelyHealthcare && !b.healthcareMode,
          dpaMissing: b.dpaStatus === "pending",
        },
      };
    }));

    // Estimated rows due for purge in the next 30 days, computed
    // as: per-brand cutoff minus 30 days vs now's cutoff. The exact
    // count is the union of TrackedEvent + TrackedSession + SiteEvent
    // + SiteConversion older than the brand's effective retention.
    const now = Date.now();
    const cutoff30 = new Date(now - 30 * 86_400_000);
    let purgeCount = 0;
    for (const b of brands) {
      const days = effectiveRetentionDays({ dataRetentionDays: b.dataRetentionDays });
      // Rows that will fall out of retention in the next 30 days =
      // rows older than (retention - 30) days but newer than the
      // cutoff. Approximate; use SiteEvent as the cheapest proxy
      // since all four tables track in lockstep.
      const upperCutoff = new Date(now - (days - 30) * 86_400_000);
      const lowerCutoff = new Date(now - days * 86_400_000);
      if (upperCutoff <= lowerCutoff) continue;
      // Exclude third_party_impact + slow_resource (99% of SiteEvent
      // volume). Without the filter, this per-brand count walks every
      // eventType bucket and can take 10+ seconds for high-volume
      // brands. The noise rows get purged by the retention cron
      // regardless — the compliance dashboard only needs to estimate
      // how many MEANINGFUL signal rows are due for purge.
      const c = await prisma.siteEvent.count({
        where: {
          brandId: b.id,
          timestamp: { gte: lowerCutoff, lt: upperCutoff },
          NOT: { eventType: { in: [...NOISE_SITE_EVENT_TYPES] } },
        },
      }).catch(() => 0);
      purgeCount += c;
      // Cap the total count we'll spend time computing — large
      // platforms shouldn't have us groveling through every brand
      // forever just to render the headline number.
      if (purgeCount > 1_000_000) break;
    }

    const totalBrands = brands.length;
    const healthcareEnabled = brands.filter((b) => b.healthcareMode).length;
    const likelyHealthcareTotal = brands.filter((b) => isLikelyHealthcare(b.industry)).length;
    const dpaSignedCount = brands.filter((b) => b.dpaStatus === "signed").length;
    const platformScore = perBrand.length === 0 ? 100
      : Math.round(perBrand.reduce((s, b) => s + b.score, 0) / perBrand.length);

    return {
      summary: {
        totalBrands,
        healthcareEnabled,
        likelyHealthcareTotal,
        dpaSignedCount,
        dpaCounts: dpaCounts.map((d) => ({ status: d.dpaStatus, count: d._count })),
        platformScore,
        platformRetentionDays: PLATFORM_RETENTION_DAYS,
        purgeCountNext30Days: purgeCount,
        // Cron has not necessarily run yet; surface the schedule
        // hint in the UI so admins know when the purge would fire.
        nextScheduledPurge: "Daily at 03:00 UTC",
      },
      perBrand,
      recentEvents: recentEvents.map((e) => ({
        ...e,
        timestamp: e.timestamp.toISOString(),
      })),
    };
  }));
}
