/**
 * GET /api/admin/integrations
 *
 * Every BrandIntegration row across the platform with the parent
 * brand for context, plus a synthetic "site_tag" row per
 * TrackedSite so admins can triage Site Tag health alongside the
 * OAuth-based integrations. Sortable on the client; the route
 * ships a stable order (most recently synced first, then by
 * brand). Caps at 1000 BrandIntegration rows + every TrackedSite.
 *
 * Superadmin-only.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireSuperadmin, withAdminTiming } from "@/lib/admin-auth";

export const dynamic = "force-dynamic";

/** Site Tag counts as "connected" if its TrackedSite is active
 *  AND the most recent event is within this window. 24 hours
 *  matches the brand dashboard's "Site Tag firing" signal — any
 *  longer and a daytime-only customer site reads as idle
 *  overnight. */
const SITE_TAG_RECENT_MS = 24 * 60 * 60 * 1000;

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

  return NextResponse.json(await withAdminTiming("integrations.list", async () => {
    const [rows, trackedSites] = await Promise.all([
      prisma.brandIntegration.findMany({
        take: 1000,
        orderBy: [{ lastSynced: "desc" }, { brandId: "asc" }],
        include: {
          brand: { select: { id: true, name: true, domain: true } },
        },
      }),
      // Synthetic site_tag rows. lastEventAt is debounced-written
      // from /api/collect (once per 10s per site), which is plenty
      // accurate for a "connected in last 24h" check without having
      // to scan the TrackedEvent table.
      prisma.trackedSite.findMany({
        take: 2000,
        select: {
          id: true,
          brandId: true,
          status: true,
          lastEventAt: true,
          firstEventAt: true,
          createdAt: true,
          brand: { select: { id: true, name: true, domain: true } },
        },
      }),
    ]);

    // Classify each TrackedSite into the integration-row shape the
    // UI already renders. Status strings mirror the badge labels
    // the user sees elsewhere on the admin surface so the two
    // places stay consistent.
    const now = Date.now();
    const siteTagRows = trackedSites.map((s) => {
      const lastMs = s.lastEventAt ? s.lastEventAt.getTime() : null;
      const hasEver = lastMs != null;
      const isRecent = hasEver && (now - lastMs) < SITE_TAG_RECENT_MS;
      let status: string;
      let connected: boolean;
      if (s.status === "disabled") { status = "DISABLED"; connected = false; }
      else if (s.status === "paused") { status = "PAUSED"; connected = false; }
      else if (!hasEver) { status = "NOT INSTALLED"; connected = false; }
      else if (isRecent) { status = "CONNECTED"; connected = true; }
      else { status = "IDLE"; connected = false; }
      return {
        id: `site_tag:${s.id}`,
        integrationId: "site_tag",
        connected,
        status,
        lastSynced: s.lastEventAt?.toISOString() ?? null,
        syncError: null as string | null,
        syncRetryCount: 0,
        tokenExpiresAt: null as string | null,
        // Installed-since hint for the UI when we want it — mirrors
        // the firstEventAt fast path used by /api/dashboard. Falls
        // back to TrackedSite.createdAt only for sites that have
        // never phoned home.
        installedAt: (s.firstEventAt ?? s.createdAt).toISOString(),
        brand: s.brand,
      };
    });

    // Merge. BrandIntegration rows stay in their existing order;
    // site_tag rows slot in by lastSynced (null → bottom) so the
    // admin-facing order matches the BrandIntegration convention.
    const normalised = [
      ...rows.map((r) => ({
        id: r.id,
        integrationId: r.integrationId,
        connected: r.connected,
        status: r.status,
        lastSynced: r.lastSynced?.toISOString() ?? null,
        syncError: r.syncError,
        syncRetryCount: r.syncRetryCount,
        tokenExpiresAt: r.tokenExpiresAt?.toISOString() ?? null,
        installedAt: null as string | null,
        brand: r.brand,
      })),
      ...siteTagRows,
    ].sort((a, b) => {
      const aT = a.lastSynced ? new Date(a.lastSynced).getTime() : 0;
      const bT = b.lastSynced ? new Date(b.lastSynced).getTime() : 0;
      if (aT !== bT) return bT - aT;
      return (a.brand.name || "").localeCompare(b.brand.name || "");
    });

    // Roll-up summary across the platform — counts per integrationId
    // + connected/error breakdown for the headline cards. Built
    // AFTER the merge so site_tag shows up in the per-type table
    // and the Types stat.
    const summary = {
      total: normalised.length,
      connected: normalised.filter((r) => r.connected).length,
      withError: normalised.filter((r) => r.syncError).length,
      byType: {} as Record<string, { total: number; connected: number; withError: number }>,
    };
    for (const r of normalised) {
      const slot = summary.byType[r.integrationId] ?? { total: 0, connected: 0, withError: 0 };
      slot.total++;
      if (r.connected) slot.connected++;
      if (r.syncError) slot.withError++;
      summary.byType[r.integrationId] = slot;
    }

    return { summary, rows: normalised };
  }));
}
