/**
 * GET    /api/admin/brands/[brandId]  — full detail panel payload
 * PATCH  /api/admin/brands/[brandId]  — admin override (plan, billingCycle,
 *                                       healthcareMode, dataRetentionDays,
 *                                       dpaStatus)
 * DELETE /api/admin/brands/[brandId]  — purge the brand + all related rows
 *
 * Detail returns the brand row, members + roles, integration
 * details (GA4 propertyId, GSC siteUrl, Site Tag siteId), data-
 * volume row counts (per key table), latest audit, recent activity,
 * and a feature-adoption summary derived from PlatformEvent.
 *
 * Superadmin-only.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { getSuperadmin, requireSuperadmin, withAdminTiming } from "@/lib/admin-auth";
import { NOISE_SITE_EVENT_TYPES } from "@/lib/services/site-event-noise";
import { getBrandLocations } from "@/lib/brand-helpers";

export const dynamic = "force-dynamic";

export async function GET(_req: Request, ctx: { params: { brandId: string } }) {
  const denied = await requireSuperadmin();
  if (denied) return denied;

  const { brandId } = ctx.params;
  if (!brandId) return NextResponse.json({ error: "brandId required" }, { status: 400 });

  return NextResponse.json(await withAdminTiming("brands.detail", async () => {
    const brand = await prisma.brand.findUnique({
      where: { id: brandId },
      include: {
        organization: {
          include: {
            memberships: {
              include: { user: { select: { id: true, name: true, email: true, image: true } } },
              orderBy: { createdAt: "asc" },
            },
          },
        },
        integrations: true,
        trackedSite: { select: { id: true, siteId: true, status: true, lastEventAt: true, createdAt: true, firstEventAt: true } },
        profile: { select: { logoUrl: true } },
      },
    });
    if (!brand) return { error: "not_found" as const };

    // Per-table row counts. Each `count` is cheap on the indexed
    // brandId column; running them in parallel keeps the latency in
    // the noise even for very large brands.
    const trackedSiteId = brand.trackedSite?.id ?? null;
    const [
      eventCount, sessionCount, conversionCount, siteEventCount,
      gscQueryCount, gscPageCount, pageRecordCount,
      latestAudit, recentActivity, featureUsage,
      gscClicksAggregate,
    ] = await Promise.all([
      trackedSiteId ? prisma.trackedEvent.count({ where: { trackedSiteId } }) : Promise.resolve(0),
      trackedSiteId ? prisma.trackedSession.count({ where: { trackedSiteId } }) : Promise.resolve(0),
      // intentionally unfiltered: admin-only endpoint; needs raw or all-time counts
      prisma.siteConversion.count({ where: { brandId } }),
      // Exclude third_party_impact + slow_resource — the noise
      // types that account for ~99% of SiteEvent volume. The admin
      // brand-detail card reports this as "Signal events captured"
      // so dropping the performance-observer rows keeps the number
      // meaningful (rage/dead clicks, JS errors, outbound clicks)
      // and the per-brand query fast against the
      // [brandId, eventType, timestamp] index.
      prisma.siteEvent.count({
        where: { brandId, NOT: { eventType: { in: [...NOISE_SITE_EVENT_TYPES] } } },
      }),
      prisma.gscQuery.count({ where: { brandId } }),
      prisma.gscPage.count({ where: { brandId } }),
      prisma.pageRecord.count({ where: { brandId } }),
      prisma.technicalAudit.findFirst({
        where: { brandId },
        orderBy: { createdAt: "desc" },
        select: { id: true, crawlHealth: true, createdAt: true, status: true },
      }),
      prisma.platformEvent.findMany({
        where: { brandId },
        orderBy: { timestamp: "desc" },
        take: 30,
        select: { id: true, action: true, category: true, userId: true, metadata: true, timestamp: true },
      }),
      // Feature adoption — distinct action keys this brand has fired.
      // Powers the "what features have they touched" panel.
      prisma.platformEvent.groupBy({
        by: ["action"],
        where: { brandId },
        _count: true,
        _max: { timestamp: true },
        orderBy: { _count: { action: "desc" } },
      }),
      // GSC headline aggregates — clicks + impressions over the last 90 days.
      prisma.gscPage.aggregate({
        where: { brandId, date: { gte: new Date(Date.now() - 90 * 86_400_000) } },
        _sum: { clicks: true, impressions: true },
      }),
    ]);

    return {
      brand: {
        id: brand.id,
        name: brand.name,
        domain: brand.domain,
        logoUrl: brand.profile?.logoUrl ?? null,
        industry: brand.industry,
        location: getBrandLocations(brand)[0] ?? null,
        plan: brand.plan,
        billingCycle: brand.billingCycle,
        planExpiresAt: brand.planExpiresAt?.toISOString() ?? null,
        healthcareMode: brand.healthcareMode,
        dataRetentionDays: brand.dataRetentionDays,
        dpaStatus: brand.dpaStatus,
        dpaSignedAt: brand.dpaSignedAt?.toISOString() ?? null,
        createdAt: brand.createdAt.toISOString(),
        updatedAt: brand.updatedAt.toISOString(),
        orgId: brand.orgId,
        orgName: brand.organization.name,
      },
      members: brand.organization.memberships.map((m) => ({
        id: m.id,
        role: m.role,
        joinedAt: m.createdAt.toISOString(),
        user: m.user,
      })),
      integrations: brand.integrations.map((i) => ({
        integrationId: i.integrationId,
        connected: i.connected,
        status: i.status,
        lastSynced: i.lastSynced?.toISOString() ?? null,
        syncError: i.syncError,
        // credentialsMeta carries non-secret config like account name
        // / propertyId / siteUrl. Strip credentials* fields entirely.
        meta: i.credentialsMeta as object,
      })),
      siteTag: brand.trackedSite ? {
        siteId: brand.trackedSite.siteId,
        status: brand.trackedSite.status,
        lastEventAt: brand.trackedSite.lastEventAt?.toISOString() ?? null,
        // When the Site Tag actually started capturing data — prefer
        // the cached firstEventAt (set by recordEvent() on the first
        // hit) and fall back to createdAt for sites that have never
        // phoned home, so the admin panel doesn't display a
        // not-yet-installed row as active-since-row-creation.
        installedAt: (brand.trackedSite.firstEventAt ?? brand.trackedSite.createdAt).toISOString(),
      } : null,
      stats: {
        events: eventCount,
        sessions: sessionCount,
        conversions: conversionCount,
        siteEvents: siteEventCount,
        gscQueries: gscQueryCount,
        gscPages: gscPageCount,
        pageRecords: pageRecordCount,
        gscClicks90d: gscClicksAggregate._sum.clicks ?? 0,
        gscImpressions90d: gscClicksAggregate._sum.impressions ?? 0,
      },
      latestAudit: latestAudit ? {
        id: latestAudit.id,
        crawlHealth: latestAudit.crawlHealth,
        status: latestAudit.status,
        createdAt: latestAudit.createdAt.toISOString(),
      } : null,
      recentActivity: recentActivity.map((a) => ({ ...a, timestamp: a.timestamp.toISOString() })),
      featureAdoption: featureUsage.map((f) => ({
        action: f.action,
        count: f._count,
        lastUsed: f._max.timestamp?.toISOString() ?? null,
      })),
    };
  }));
}

// ─── PATCH (admin overrides) ──────────────────────────────────────

export async function PATCH(req: Request, ctx: { params: { brandId: string } }) {
  const denied = await requireSuperadmin();
  if (denied) return denied;
  const admin = await getSuperadmin();
  if (!admin) return NextResponse.json({ error: "Forbidden" }, { status: 403 });

  const body = await req.json().catch(() => null) as {
    plan?: string;
    billingCycle?: string;
    healthcareMode?: boolean;
    dataRetentionDays?: number | null;
    dpaStatus?: string;
  } | null;
  if (!body) return NextResponse.json({ error: "Invalid JSON" }, { status: 400 });

  const data: Record<string, unknown> = {};
  if (typeof body.plan === "string") data.plan = body.plan;
  if (typeof body.billingCycle === "string") data.billingCycle = body.billingCycle;
  if (typeof body.healthcareMode === "boolean") data.healthcareMode = body.healthcareMode;
  if (body.dataRetentionDays === null || typeof body.dataRetentionDays === "number") {
    data.dataRetentionDays = body.dataRetentionDays;
  }
  if (typeof body.dpaStatus === "string") {
    data.dpaStatus = body.dpaStatus;
    if (body.dpaStatus === "signed") data.dpaSignedAt = new Date();
    else if (body.dpaStatus === "not_required" || body.dpaStatus === "pending") data.dpaSignedAt = null;
  }

  const brand = await prisma.brand.update({
    where: { id: ctx.params.brandId },
    data,
    select: { id: true, plan: true, billingCycle: true, healthcareMode: true, dataRetentionDays: true, dpaStatus: true, dpaSignedAt: true },
  });

  // Audit: any compliance-relevant change lands in ComplianceEvent
  // so the regulatory log stays complete.
  if ("healthcareMode" in data || "dataRetentionDays" in data || "dpaStatus" in data) {
    await prisma.complianceEvent.create({
      data: {
        action: "brand_compliance_change",
        brandId: ctx.params.brandId,
        details: data as object,
        requestedBy: admin.userId,
      },
    }).catch(() => {});
  }

  return NextResponse.json({ brand });
}

// ─── DELETE (soft delete by default, hard delete with ?permanent=true) ──

export async function DELETE(req: Request, ctx: { params: { brandId: string } }) {
  const denied = await requireSuperadmin();
  if (denied) return denied;
  const admin = await getSuperadmin();
  if (!admin) return NextResponse.json({ error: "Forbidden" }, { status: 403 });

  const { brandId } = ctx.params;
  const permanent = new URL(req.url).searchParams.get("permanent") === "true";

  if (!permanent) {
    // Soft delete — preserve all data
    await prisma.brand.update({
      where: { id: brandId },
      data: {
        status: "deleted",
        deactivatedAt: new Date(),
        deactivatedBy: admin.userId,
        deactivationReason: "Admin soft-deleted",
      },
    });
    await prisma.complianceEvent.create({
      data: {
        action: "brand_soft_deleted",
        brandId,
        details: { permanent: false } as object,
        requestedBy: admin.userId,
      },
    }).catch(() => {});
    return NextResponse.json({ ok: true, softDeleted: true, brandId });
  }

  // Hard delete — permanent, requires ?permanent=true
  return NextResponse.json(await withAdminTiming("brands.delete", async () => {
    // Most child rows cascade via Prisma's onDelete: Cascade. We
    // explicitly delete the most-data-heavy children first (in
    // batches if the row count would exceed the connection's
    // statement budget) so the final DELETE Brand transaction stays
    // small. For the typical brand this completes in <2s; very
    // large brands (millions of TrackedEvents) may want a chunked
    // background job instead — out of scope for this commit.
    const trackedSite = await prisma.trackedSite.findUnique({
      where: { brandId },
      select: { id: true },
    });

    let deleted = { events: 0, sessions: 0, siteEvents: 0, conversions: 0 };
    if (trackedSite) {
      const [events, sessions] = await Promise.all([
        prisma.trackedEvent.deleteMany({ where: { trackedSiteId: trackedSite.id } }),
        prisma.trackedSession.deleteMany({ where: { trackedSiteId: trackedSite.id } }),
      ]);
      deleted.events = events.count;
      deleted.sessions = sessions.count;
    }
    const [siteEvents, conversions] = await Promise.all([
      prisma.siteEvent.deleteMany({ where: { brandId } }),
      prisma.siteConversion.deleteMany({ where: { brandId } }),
    ]);
    deleted.siteEvents = siteEvents.count;
    deleted.conversions = conversions.count;

    // The Brand DELETE cascades the rest (PageRecord, GscQuery,
    // GscPage, ClientPortal, integrations, etc.) per schema.prisma.
    await prisma.brand.delete({ where: { id: brandId } });

    await prisma.complianceEvent.create({
      data: {
        action: "brand_deleted",
        brandId,
        details: deleted as object,
        requestedBy: admin.userId,
      },
    }).catch(() => {});

    return { ok: true as const, deleted };
  }));
}
