import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import {
  getLatestAudit,
  buildHeroViewModel,
  buildStatsViewModel,
  buildPriorityViewModel,
  buildMatrixViewModel,
  buildAnnotationViewModel,
  buildBehavioralViewModel,
  type SiteTagStatCounts,
} from "@/app/technical-audit/_lib/queries";
import { getErrorPatterns } from "@/lib/services/site-tag-analytics";
import { getCached, setCached } from "@/lib/cache/redis-cache";

export const dynamic = "force-dynamic";

const STATS_TIMEOUT_MS = 5000;

function timedCount(query: Promise<number>): Promise<number | null> {
  const timeout = new Promise<null>((resolve) => setTimeout(() => resolve(null), STATS_TIMEOUT_MS));
  return Promise.race([query, timeout]);
}

export async function GET(
  _req: Request,
  { params }: { params: Promise<{ brandId: string }> },
) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const { brandId } = await params;

  const brand = await prisma.brand.findUnique({
    where: { id: brandId },
    include: {
      organization: { include: { memberships: true } },
      trackedSite: { select: { firstEventAt: true } },
    },
  });
  if (!brand || !brand.organization.memberships.some((m) => m.userId === user.id)) {
    return NextResponse.json({ error: "Access denied" }, { status: 403 });
  }

  const siteTagInstalled = !!(brand.trackedSite?.firstEventAt);

  const cacheKey = `audit-latest:${brandId}`;
  const cached = await getCached<object>(cacheKey);
  if (cached) return NextResponse.json({ ...cached, siteTagInstalled });

  // Fetch latest audit + Site Tag event counts in parallel.
  // count() uses @@index([brandId, eventType, timestamp]) directly -- no hash-aggregate.
  // getErrorPatterns samples the last 5000 js_error rows; bounded scan, safe on large tables.
  // getFrictionPages uses findMany with distinct to count affected pages without a full groupBy.
  // timedCount wraps each count() in a 5s timeout; null means timed out (graceful degradation).
  const since30d = new Date(Date.now() - 30 * 86_400_000);
  const [result, jsErrCount, frictionCount, brokenCount, errorPatterns, frictionPages] =
    await Promise.all([
      getLatestAudit(brandId),
      timedCount(prisma.siteEvent.count({
        where: { brandId, eventType: "js_error", timestamp: { gte: since30d } },
      })).catch(() => null),
      timedCount(prisma.siteEvent.count({
        where: { brandId, eventType: { in: ["rage_click", "dead_click"] }, timestamp: { gte: since30d } },
      })).catch(() => null),
      timedCount(prisma.siteEvent.count({
        where: { brandId, eventType: { in: ["broken_link", "http_error"] }, timestamp: { gte: since30d } },
      })).catch(() => null),
      getErrorPatterns(brandId).catch(() => null),
      prisma.siteEvent.findMany({
        where: { brandId, eventType: { in: ["rage_click", "dead_click"] }, timestamp: { gte: since30d } },
        select: { pageUrl: true },
        distinct: ["pageUrl"],
        take: 200,
      }).then((rows) => rows.length).catch(() => null),
    ]);

  if (!result) return NextResponse.json(null);

  const { seoSection, previousHealthScore, brandName, brandDomain, degradedMode, crawlErrorReason } = result;

  const siteTag: SiteTagStatCounts = {
    errors: jsErrCount,
    friction: frictionCount,
    notFound: brokenCount,
    errorPatterns,
    frictionPageCount: frictionPages,
  };

  const timedOut = jsErrCount === null || frictionCount === null || brokenCount === null;
  const statsStatus: "complete" | "partial" | "updating" = timedOut
    ? (jsErrCount === null && frictionCount === null && brokenCount === null ? "updating" : "partial")
    : "complete";

  const body = {
    auditId: result.auditId,
    createdAt: result.createdAt,
    degradedMode,
    ...(crawlErrorReason && { crawlErrorReason }),
    statsStatus,
    siteTagInstalled,
    heroVm:       buildHeroViewModel(seoSection, previousHealthScore, brandName, brandDomain),
    statsVm:      buildStatsViewModel(seoSection, siteTag),
    priorityVm:   buildPriorityViewModel(seoSection),
    matrixVm:     buildMatrixViewModel(seoSection),
    annotationVm: buildAnnotationViewModel(seoSection),
    behavioralVm: buildBehavioralViewModel(seoSection),
  };

  if (statsStatus === "complete") {
    setCached(cacheKey, body, 300).catch(() => {});
  }

  return NextResponse.json(body);
}
