/**
 * GET /api/conversion-intelligence/attribution?brandId=xxx&days=30
 *
 * Aggregates SiteConversion rows into a per-channel attribution view
 * powering the Conversion Intelligence UI. Returns first-touch,
 * last-touch, and assisted conversion counts per channel plus totals
 * for the selected window.
 */

import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { countedConversionWhere } from "@/lib/conversions/counted-where";

export const dynamic = "force-dynamic";

const CANONICAL_CHANNELS = [
  "organic",
  "social",
  "paid",
  "paid_social",
  "direct",
  "local", // GBP / Google Maps
  "email",
  "referral",
  "internal",
  "other",
] as const;
type Channel = (typeof CANONICAL_CHANNELS)[number];

function normaliseChannel(raw: string | null | undefined): Channel {
  const c = (raw || "other").toLowerCase();
  if ((CANONICAL_CHANNELS as readonly string[]).includes(c)) return c as Channel;
  if (c === "cpc" || c === "ppc") return "paid";
  return "other";
}

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");
  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 = Math.max(1, Math.min(365, Number(searchParams.get("days") || 30)));
  const since = new Date(Date.now() - days * 86400000);

  const rows = await prisma.siteConversion.findMany({
    where: countedConversionWhere(brandId, { since }),
    select: {
      conversionType: true,
      pageUrl: true,
      formProvider: true,
      firstTouchChannel: true,
      lastTouchChannel: true,
      assistedChannels: true,
      timestamp: true,
    },
  });

  // ── Per-channel rollup ────────────────────────────────────────────
  // total = unique conversions that touched the channel (dedupe per row).
  type ChannelStats = { channel: Channel; firstTouch: number; lastTouch: number; assisted: number; total: number };
  const byChannel = new Map<Channel, ChannelStats>();
  function get(ch: Channel): ChannelStats {
    let s = byChannel.get(ch);
    if (!s) { s = { channel: ch, firstTouch: 0, lastTouch: 0, assisted: 0, total: 0 }; byChannel.set(ch, s); }
    return s;
  }

  // ── Per-conversion-type rollup ────────────────────────────────────
  const byType = new Map<string, { type: string; count: number; byProvider: Record<string, number> }>();

  // ── Top pages ─────────────────────────────────────────────────────
  const byPage = new Map<string, { pageUrl: string; count: number }>();

  for (const row of rows) {
    const first = normaliseChannel(row.firstTouchChannel);
    const last = normaliseChannel(row.lastTouchChannel);
    const touchedByRow = new Set<Channel>();
    get(first).firstTouch++; touchedByRow.add(first);
    get(last).lastTouch++; touchedByRow.add(last);
    const assisted = Array.isArray(row.assistedChannels) ? (row.assistedChannels as unknown as string[]) : [];
    for (const a of assisted) {
      const norm = normaliseChannel(a);
      if (norm === first || norm === last) continue;
      get(norm).assisted++;
      touchedByRow.add(norm);
    }
    for (const ch of touchedByRow) get(ch).total++;

    const t = row.conversionType || "unknown";
    let typeBucket = byType.get(t);
    if (!typeBucket) { typeBucket = { type: t, count: 0, byProvider: {} }; byType.set(t, typeBucket); }
    typeBucket.count++;
    const provider = row.formProvider || (t.startsWith("phone") ? "phone" : "unknown");
    typeBucket.byProvider[provider] = (typeBucket.byProvider[provider] || 0) + 1;

    const pageKey = row.pageUrl;
    let pageBucket = byPage.get(pageKey);
    if (!pageBucket) { pageBucket = { pageUrl: pageKey, count: 0 }; byPage.set(pageKey, pageBucket); }
    pageBucket.count++;
  }

  const channels = Array.from(byChannel.values()).sort((a, b) => b.total - a.total);
  const types = Array.from(byType.values()).sort((a, b) => b.count - a.count);
  const topPages = Array.from(byPage.values()).sort((a, b) => b.count - a.count).slice(0, 20);

  return NextResponse.json({
    brandId,
    days,
    total: rows.length,
    channels,
    types,
    topPages,
  });
}
