/**
 * GET /api/admin/brands — paginated brand list with search.
 *
 * Query params:
 *   q       — substring match (name, domain)
 *   plan    — filter by plan (growth | professional | agency | agency_pro | enterprise | trial)
 *   page    — 1-indexed
 *   limit   — default 25, max 200
 *   sort    — createdAt | events | members (default createdAt)
 *
 * Returns each brand with: ownerName/email, memberCount,
 * integration status flags, totalEvents (TrackedEvent count),
 * lastAuditScore + date, lastActivityAt (most recent PlatformEvent
 * for this brand). Aggregations run in parallel and lookup-style
 * (groupBy / count by id-set) so the route stays O(pageSize) round
 * trips regardless of brand count.
 *
 * Superadmin-only.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireSuperadmin, withAdminTiming } from "@/lib/admin-auth";
import { getActiveSiteTagBrandIds } from "@/lib/brand/site-tag-active";
import type { Prisma } from "@prisma/client";

export const dynamic = "force-dynamic";

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

  const { searchParams } = new URL(req.url);
  const q = (searchParams.get("q") ?? "").trim();
  const planFilter = searchParams.get("plan") ?? "";
  const sort = (searchParams.get("sort") ?? "createdAt") as "createdAt" | "events" | "members";
  const page = Math.max(1, Number(searchParams.get("page") ?? 1));
  const limit = Math.max(1, Math.min(200, Number(searchParams.get("limit") ?? 25)));
  const skip = (page - 1) * limit;

  return NextResponse.json(await withAdminTiming("brands.list", async () => {
    const where: Prisma.BrandWhereInput = {};
    if (q) {
      where.OR = [
        { name: { contains: q, mode: "insensitive" } },
        { domain: { contains: q, mode: "insensitive" } },
      ];
    }
    if (planFilter) where.plan = planFilter;

    // events / members sort needs an aggregate first; fall back to
    // createdAt for the simple case.
    const orderBy: Prisma.BrandOrderByWithRelationInput =
      sort === "members" ? { organization: { memberships: { _count: "desc" } } }
      : { createdAt: "desc" };

    const [brands, total] = await Promise.all([
      prisma.brand.findMany({
        where,
        orderBy,
        skip,
        take: limit,
        include: {
          organization: {
            select: {
              name: true,
              memberships: {
                where: { role: "owner" },
                take: 1,
                include: { user: { select: { name: true, email: true } } },
              },
              _count: { select: { memberships: true } },
            },
          },
          integrations: { select: { integrationId: true, connected: true } },
          trackedSite: { select: { id: true, status: true, lastEventAt: true } },
          profile: { select: { logoUrl: true } },
        },
      }),
      prisma.brand.count({ where }),
    ]);

    const brandIds = brands.map((b) => b.id);
    const trackedSiteIds = brands.map((b) => b.trackedSite?.id).filter(Boolean) as string[];

    // Duplicate domain detection
    const domainCounts = new Map<string, number>();
    for (const b of brands) {
      if (b.domain) domainCounts.set(b.domain, (domainCounts.get(b.domain) ?? 0) + 1);
    }
    for (const [domain, count] of domainCounts) {
      if (count > 1) console.warn(`[brands] duplicate domain detected domain=${domain} count=${count}`);
    }

    // Per-brand aggregates — four parallel queries keep this at
    // O(1) extra DB round-trips regardless of brand count.
    const [eventCounts, lastAudits, lastActivity, activeSiteTagBrandIds] = await Promise.all([
      trackedSiteIds.length > 0
        ? prisma.trackedEvent.groupBy({
            by: ["trackedSiteId"],
            where: { trackedSiteId: { in: trackedSiteIds } },
            _count: true,
          })
        : Promise.resolve([] as Array<{ trackedSiteId: string; _count: number }>),
      brandIds.length > 0
        ? prisma.technicalAudit.findMany({
            where: { brandId: { in: brandIds } },
            orderBy: { createdAt: "desc" },
            distinct: ["brandId"],
            select: { brandId: true, crawlHealth: true, createdAt: true },
          })
        : Promise.resolve([]),
      brandIds.length > 0
        ? prisma.platformEvent.groupBy({
            by: ["brandId"],
            where: { brandId: { in: brandIds } },
            _max: { timestamp: true },
          })
        : Promise.resolve([] as Array<{ brandId: string | null; _max: { timestamp: Date | null } }>),
      getActiveSiteTagBrandIds(brandIds),
    ]);

    // Build O(1) lookup maps.
    const eventCountByTrackedSite = new Map(eventCounts.map((e) => [e.trackedSiteId, e._count]));
    const lastAuditByBrand = new Map(lastAudits.map((a) => [a.brandId, a]));
    const lastActivityByBrand = new Map(lastActivity.map((a) => [a.brandId, a._max.timestamp]));

    return {
      brands: brands.map((b) => {
        const owner = b.organization.memberships[0]?.user;
        const integ = (id: string) => b.integrations.some((i) => i.integrationId === id && i.connected);
        const audit = lastAuditByBrand.get(b.id);
        return {
          id: b.id,
          name: b.name,
          domain: b.domain,
          logoUrl: b.profile?.logoUrl ?? null,
          orgName: b.organization.name,
          ownerName: owner?.name ?? null,
          ownerEmail: owner?.email ?? null,
          memberCount: b.organization._count.memberships,
          plan: b.plan,
          billingCycle: b.billingCycle,
          createdAt: b.createdAt.toISOString(),
          ga4Connected: integ("ga4"),
          gscConnected: integ("gsc"),
          gbpConnected: integ("gbp"),
          siteTagActive: activeSiteTagBrandIds.has(b.id),
          totalEvents: b.trackedSite ? eventCountByTrackedSite.get(b.trackedSite.id) ?? 0 : 0,
          lastAuditScore: audit?.crawlHealth ?? null,
          lastAuditDate: audit?.createdAt.toISOString() ?? null,
          lastActivityAt: lastActivityByBrand.get(b.id)?.toISOString() ?? null,
          siteTagLastEventAt: b.trackedSite?.lastEventAt?.toISOString() ?? null,
        };
      }),
      total,
      page,
      limit,
      hasMore: skip + brands.length < total,
    };
  }));
}
