/**
 * GET /api/site-tag/analytics/ai-attribution?brandId=xxx&range=28d
 *
 * Returns LLMO/GEO/AEO attribution data for the AI Attribution tab.
 */

import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { getAiAttributionSummary } from "@/lib/services/ai-attribution";
import { calculateContentResonance } from "@/lib/services/ai-content-resonance";
import { rangeToDays } from "@/lib/services/date-utils";

export const dynamic = "force-dynamic";

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");
  // Unified to 30d to match the audit pipeline's 30-day AI attribution window.
  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 = rangeToDays(range);
  // `since` for AI attribution aggregations — rolling window.
  const since = new Date(Date.now() - days * 86_400_000);
  // `scanSince` matches the Overview tab's `rangeStart()` helper so
  // the "Sessions Scanned" tile counts the exact same window as the
  // Overview's "Session Start" tile. The difference is subtle: for
  // "28d" rangeStart walks the calendar back 28 days (preserving the
  // time-of-day), while a plain ms subtraction can land on a slightly
  // different hour across DST boundaries — enough to drop or include
  // a handful of sessions at the edge.
  const scanSince = (() => {
    const d = new Date();
    if (range === "1d") d.setHours(0, 0, 0, 0);
    else d.setDate(d.getDate() - days);
    return d;
  })();

  // Monitoring status — returned regardless of whether there's AI traffic
  // yet, so the empty state can show "monitoring active since X, Y sessions
  // scanned" to reassure the customer that the system is working.
  const trackedSite = await prisma.trackedSite.findUnique({
    where: { brandId },
    select: { id: true, firstEventAt: true, lastEventAt: true, createdAt: true },
  }).catch(() => null);
  // Match the exact source the Overview tab uses for its "Session Start"
  // tile: count TrackedEvent rows with eventType='session_start' in the
  // active range. Using TrackedSession.count with startedAt produced
  // slightly different numbers (e.g. 32,693 vs 31,168 for a 28-day
  // window) because TrackedSession rows can exist without a
  // corresponding session_start event and vice versa.
  const sessionsScanned = trackedSite
    ? await prisma.trackedEvent.count({
        where: {
          trackedSiteId: trackedSite.id,
          eventType: "session_start",
          timestamp: { gte: scanSince },
        },
      }).catch(() => 0)
    : 0;
  const monitoring = {
    installedAt: trackedSite?.firstEventAt?.toISOString() ?? trackedSite?.createdAt?.toISOString() ?? null,
    lastEventAt: trackedSite?.lastEventAt?.toISOString() ?? null,
    sessionsScanned,
    isActive: !!trackedSite,
  };

  try {
    const summary = await getAiAttributionSummary(brandId, since);

    // Daily trend for chart
    const daily = await prisma.aiAttribution.groupBy({
      by: ["timestamp"],
      where: { brandId, timestamp: { gte: since } },
      _count: true,
    }).catch(() => []);

    // Aggregate daily by date string
    const dailyMap = new Map<string, number>();
    for (const d of daily) {
      const key = d.timestamp.toISOString().split("T")[0];
      dailyMap.set(key, (dailyMap.get(key) ?? 0) + (typeof d._count === "number" ? d._count : 0));
    }
    const dailyTrend = Array.from(dailyMap.entries())
      .map(([date, count]) => ({ date, count }))
      .sort((a, b) => a.date.localeCompare(b.date));

    // Recent AI-attributed journeys
    const recentJourneys = await prisma.aiAttribution.findMany({
      where: { brandId, timestamp: { gte: since } },
      orderBy: { timestamp: "desc" },
      take: 20,
      select: {
        id: true,
        aiPlatform: true,
        channel: true,
        queryContext: true,
        referrerUrl: true,
        landingPage: true,
        converted: true,
        conversionType: true,
        engagementScore: true,
        timestamp: true,
      },
    }).catch(() => []);

    // Content resonance (AI vs organic performance per page)
    const resonance = await calculateContentResonance(brandId, since).catch(() => []);

    // Multi-session attribution stats
    const [directCount, assistedCount] = await Promise.all([
      prisma.aiAttribution.count({
        where: { brandId, timestamp: { gte: since }, converted: true, queryContext: { not: { startsWith: "[assisted]" } } },
      }).catch(() => 0),
      prisma.aiAttribution.count({
        where: { brandId, timestamp: { gte: since }, converted: true, queryContext: { startsWith: "[assisted]" } },
      }).catch(() => 0),
    ]);

    // Probable AI (behavioral model) count
    const probableCount = await prisma.aiAttribution.count({
      where: { brandId, timestamp: { gte: since }, aiPlatform: "behavioral_model" },
    }).catch(() => 0);

    return NextResponse.json({
      ...summary,
      dailyTrend,
      recentJourneys,
      contentResonance: resonance.slice(0, 10),
      multiTouch: { direct: directCount, assisted: assistedCount },
      probableAiCount: probableCount,
      monitoring,
      range,
      days,
    });
  } catch (err) {
    console.error("[ai-attribution] query failed:", err instanceof Error ? err.message : String(err));
    return NextResponse.json({
      totalReferrals: 0, conversions: 0, conversionRate: 0,
      byPlatform: [], byChannel: [], topPages: [],
      dailyTrend: [], recentJourneys: [],
      monitoring,
      range, days,
    });
  }
}
