import { prisma } from "@/lib/prisma";
import { getDateRange, DateRange } from "./date-utils";

/**
 * Get user journeys for a brand.
 */
export async function getJourneys(brandId: string, range: DateRange = "30d") {
  const { start, end } = getDateRange(range);

  return prisma.userJourney.findMany({
    where: { brandId, date: { gte: start, lte: end } },
    include: {
      conversion: { select: { id: true, type: true, channel: true, value: true, landingPage: true } },
      deal: { select: { id: true, dealName: true, value: true, status: true, stage: true } },
    },
    orderBy: { date: "desc" },
  });
}

/**
 * Get journey summary — aggregated view of the full funnel.
 */
export async function getJourneySummary(brandId: string, range: DateRange = "30d") {
  const journeys = await getJourneys(brandId, range);

  // By entry channel
  const byChannel: Record<string, { count: number; revenue: number; converted: number }> = {};
  for (const j of journeys) {
    if (!byChannel[j.entryChannel]) byChannel[j.entryChannel] = { count: 0, revenue: 0, converted: 0 };
    byChannel[j.entryChannel].count++;
    byChannel[j.entryChannel].revenue += j.revenue;
    if (j.conversionType) byChannel[j.entryChannel].converted++;
  }

  // Top pages in journeys
  const pageCounts: Record<string, number> = {};
  for (const j of journeys) {
    for (const page of j.pagesVisited) {
      pageCounts[page] = (pageCounts[page] || 0) + 1;
    }
  }
  const topPages = Object.entries(pageCounts)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 10)
    .map(([page, count]) => ({ page, count }));

  // By conversion type
  const byConvType: Record<string, { count: number; revenue: number }> = {};
  for (const j of journeys) {
    if (!j.conversionType) continue;
    if (!byConvType[j.conversionType]) byConvType[j.conversionType] = { count: 0, revenue: 0 };
    byConvType[j.conversionType].count++;
    byConvType[j.conversionType].revenue += j.revenue;
  }

  // Funnel: entries → page views → conversions → deals → revenue
  const totalEntries = journeys.length;
  const totalConverted = journeys.filter((j) => j.conversionType).length;
  const totalWithDeal = journeys.filter((j) => j.dealId).length;
  const totalRevenue = Math.round(journeys.reduce((s, j) => s + j.revenue, 0));
  const avgPages = journeys.length > 0
    ? Math.round(journeys.reduce((s, j) => s + j.pagesVisited.length, 0) / journeys.length * 10) / 10
    : 0;

  return {
    totalEntries,
    totalConverted,
    totalWithDeal,
    totalRevenue,
    avgPagesPerJourney: avgPages,
    conversionRate: totalEntries > 0 ? Math.round((totalConverted / totalEntries) * 1000) / 10 : 0,
    dealRate: totalConverted > 0 ? Math.round((totalWithDeal / totalConverted) * 1000) / 10 : 0,
    byChannel: Object.entries(byChannel)
      .map(([channel, data]) => ({ channel, ...data }))
      .sort((a, b) => b.revenue - a.revenue),
    byConversionType: Object.entries(byConvType)
      .map(([type, data]) => ({ type, ...data }))
      .sort((a, b) => b.revenue - a.revenue),
    topPages,
    recentJourneys: journeys.slice(0, 20).map((j) => ({
      id: j.id,
      entryChannel: j.entryChannel,
      pagesVisited: j.pagesVisited,
      conversionType: j.conversionType,
      revenue: j.revenue,
      date: j.date,
      hasDeal: !!j.dealId,
      dealStatus: j.deal?.status ?? null,
    })),
  };
}

/**
 * Build journeys from existing conversion + CRM data.
 * Links conversions to deals and creates journey records.
 */
export async function buildJourneys(brandId: string) {
  const conversions = await prisma.conversionEvent.findMany({
    where: { brandId },
    include: { crmDeals: { take: 1 } },
    orderBy: { date: "desc" },
    take: 200,
  });

  let created = 0;

  for (const conv of conversions) {
    // Skip if journey already exists for this conversion
    const existing = await prisma.userJourney.findFirst({
      where: { brandId, conversionId: conv.id },
    });
    if (existing) continue;

    const deal = conv.crmDeals[0] ?? null;

    // Build a simplified page path
    const pages: string[] = [];
    if (conv.landingPage) pages.push(conv.landingPage);
    // Add mock intermediate pages based on channel
    if (conv.channel === "organic") pages.push("/blog", conv.landingPage || "/");
    else if (conv.channel === "social") pages.push("/about", conv.landingPage || "/");
    else pages.push(conv.landingPage || "/");

    await prisma.userJourney.create({
      data: {
        brandId,
        entryChannel: conv.channel,
        pagesVisited: [...new Set(pages)],
        conversionType: conv.type,
        revenue: deal?.value ?? conv.value,
        date: conv.date,
        conversionId: conv.id,
        dealId: deal?.id ?? null,
      },
    });
    created++;
  }

  return { created };
}
