/**
 * GET /api/site-tag/analytics/ecommerce?brandId=X&range=7d|30d|90d
 *
 * Powers the Ecommerce tab on /site-tag-analytics.
 * Reads from SiteConversion (add_to_cart, checkout_started, purchase)
 * and TrackedEvent (product_view) -- both stored by the ingest path.
 *
 * Response shape:
 *   {
 *     funnel: { productViews, addToCarts, checkoutsStarted, purchases,
 *               cartRate, checkoutRate, purchaseRate },
 *     revenue: { total, orderCount, avgOrderValue, currency },
 *     orders: [{ id, orderId, value, currency, timestamp,
 *                pageUrl, channel, source }],
 *   }
 */

import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";

export const dynamic = "force-dynamic";

const CACHE_HEADERS = {
  "Cache-Control": "private, max-age=30, stale-while-revalidate=120",
};

function cap100(n: number, d: number): number {
  if (d === 0) return 0;
  return Math.min(100, Math.round((n / d) * 100));
}

export async function GET(req: Request) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const { searchParams } = new URL(req.url);
  const brandId = searchParams.get("brandId");
  const range = searchParams.get("range") || "30d";
  if (!brandId) return NextResponse.json({ error: "brandId required" }, { status: 400 });

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

  const days = range === "1d" ? 1 : range === "7d" ? 7 : range === "28d" ? 28 : range === "90d" ? 90 : 30;
  const since = new Date(Date.now() - days * 86_400_000);

  // product_view lives in TrackedEvent keyed by trackedSiteId
  const trackedSite = await prisma.trackedSite
    .findUnique({ where: { brandId }, select: { id: true } })
    .catch(() => null);

  try {
    const [addToCarts, checkoutsStarted, productViews, purchaseRows] = await Promise.all([
      prisma.siteConversion
        .count({
          where: {
            brandId,
            conversionType: "add_to_cart",
            isDuplicateOf: null,
            invalidatedReason: null,
            timestamp: { gte: since },
          },
        })
        .catch(() => 0),

      prisma.siteConversion
        .count({
          where: {
            brandId,
            conversionType: "checkout_started",
            isDuplicateOf: null,
            invalidatedReason: null,
            timestamp: { gte: since },
          },
        })
        .catch(() => 0),

      trackedSite
        ? prisma.trackedEvent
            .count({
              where: {
                trackedSiteId: trackedSite.id,
                eventType: "product_view",
                timestamp: { gte: since },
              },
            })
            .catch(() => 0)
        : Promise.resolve(0),

      // Pull purchase rows for revenue aggregation + order list (capped at 500).
      // In-memory aggregation mirrors the video-chat pattern -- Prisma groupBy
      // on nullable Float doesn't produce SUM cleanly across nulls.
      prisma.siteConversion
        .findMany({
          where: {
            brandId,
            conversionType: "purchase",
            isDuplicateOf: null,
            invalidatedReason: null,
            timestamp: { gte: since },
          },
          select: {
            id: true,
            orderId: true,
            conversionValue: true,
            currency: true,
            timestamp: true,
            pageUrl: true,
            firstTouchChannel: true,
            firstTouchSource: true,
          },
          orderBy: { timestamp: "desc" },
          take: 500,
        })
        .catch(() => [] as Array<{
          id: string;
          orderId: string | null;
          conversionValue: number | null;
          currency: string | null;
          timestamp: Date;
          pageUrl: string;
          firstTouchChannel: string | null;
          firstTouchSource: string | null;
        }>),
    ]);

    // Revenue aggregation
    let revenueTotal = 0;
    let orderCount = 0;
    const currencyCounts: Record<string, number> = {};

    for (const row of purchaseRows) {
      if (row.conversionValue != null && Number.isFinite(row.conversionValue)) {
        revenueTotal += row.conversionValue;
        orderCount++;
        const c = row.currency ?? "USD";
        currencyCounts[c] = (currencyCounts[c] ?? 0) + 1;
      }
    }

    const topCurrency =
      Object.entries(currencyCounts).sort(([, a], [, b]) => b - a)[0]?.[0] ?? null;

    const purchases = purchaseRows.length;

    return NextResponse.json(
      {
        funnel: {
          productViews,
          addToCarts,
          checkoutsStarted,
          purchases,
          cartRate: cap100(addToCarts, productViews),
          checkoutRate: cap100(checkoutsStarted, addToCarts),
          purchaseRate: cap100(purchases, checkoutsStarted),
        },
        revenue: {
          total: Math.round(revenueTotal * 100) / 100,
          orderCount,
          avgOrderValue: orderCount > 0 ? Math.round((revenueTotal / orderCount) * 100) / 100 : 0,
          currency: topCurrency,
        },
        orders: purchaseRows.slice(0, 100).map((r) => ({
          id: r.id,
          orderId: r.orderId,
          value: r.conversionValue,
          currency: r.currency,
          timestamp: r.timestamp.toISOString(),
          pageUrl: r.pageUrl,
          channel: r.firstTouchChannel,
          source: r.firstTouchSource,
        })),
      },
      { headers: CACHE_HEADERS },
    );
  } catch (err) {
    console.error("[site-tag/analytics:ecommerce] failed", err);
    return NextResponse.json(emptyPayload());
  }
}

function emptyPayload() {
  return {
    funnel: {
      productViews: 0,
      addToCarts: 0,
      checkoutsStarted: 0,
      purchases: 0,
      cartRate: 0,
      checkoutRate: 0,
      purchaseRate: 0,
    },
    revenue: {
      total: 0,
      orderCount: 0,
      avgOrderValue: 0,
      currency: null as string | null,
    },
    orders: [] as Array<never>,
  };
}
