/**
 * Benchmark Engine — computes anonymized cross-customer industry
 * benchmarks. Only aggregates when 5+ brands contribute.
 */

import { prisma } from "@/lib/prisma";

export const MIN_SAMPLE = 5;

async function upsertBenchmark(industry: string, metric: string, value: number, sampleSize: number, location?: string) {
  const period = `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}`;
  await prisma.industryBenchmark.upsert({
    where: { industry_location_metric_period: { industry, location: location ?? "", metric, period } },
    create: { industry, location: location ?? null, metric, value, sampleSize, period },
    update: { value, sampleSize },
  });
}

export async function computeAllBenchmarks(): Promise<{ industries: number; metrics: number }> {
  // Group brands by industry
  const industries = await prisma.brand.groupBy({ by: ["industry"], _count: true, having: { industry: { _count: { gte: MIN_SAMPLE } } } });
  let totalMetrics = 0;
  const d30 = new Date(Date.now() - 30 * 86400000);

  for (const { industry, _count } of industries) {
    if (!industry) continue;
    const brandIds = (await prisma.brand.findMany({ where: { industry: { equals: industry, mode: "insensitive" }, isDemo: false }, select: { id: true } })).map((b) => b.id);
    const n = brandIds.length;
    if (n < MIN_SAMPLE) continue;

    // CTR benchmarks by position (1-10)
    for (let pos = 1; pos <= 10; pos++) {
      const agg = await prisma.gscPage.aggregate({ where: { brandId: { in: brandIds }, position: { gte: pos - 0.5, lt: pos + 0.5 }, date: { gte: d30 } }, _avg: { ctr: true } });
      if (agg._avg.ctr != null) { await upsertBenchmark(industry, `ctr_at_position_${pos}`, Math.round(agg._avg.ctr * 10000) / 100, n); totalMetrics++; }
    }

    // Traffic benchmarks
    const trafficAgg = await prisma.gscPage.aggregate({ where: { brandId: { in: brandIds }, date: { gte: d30 } }, _sum: { clicks: true, impressions: true } });
    await upsertBenchmark(industry, "avg_monthly_clicks", Math.round((trafficAgg._sum.clicks ?? 0) / n), n);
    await upsertBenchmark(industry, "avg_monthly_impressions", Math.round((trafficAgg._sum.impressions ?? 0) / n), n);
    totalMetrics += 2;

    // Average position
    const posAgg = await prisma.gscPage.aggregate({ where: { brandId: { in: brandIds }, date: { gte: d30 } }, _avg: { position: true } });
    if (posAgg._avg.position != null) { await upsertBenchmark(industry, "avg_position", Math.round(posAgg._avg.position * 10) / 10, n); totalMetrics++; }

    // Conversion rate
    // intentionally unfiltered: cross-brand benchmarking; needs all rows
    const convCount = await prisma.siteConversion.count({ where: { brandId: { in: brandIds }, timestamp: { gte: d30 } } });
    const sessions = (await prisma.metricSnapshot.aggregate({ where: { brandId: { in: brandIds }, date: { gte: d30 } }, _sum: { sessions: true } }))._sum.sessions ?? 0;
    if (sessions > 0) { await upsertBenchmark(industry, "conversion_rate", Math.round((convCount / sessions) * 10000) / 100, n); totalMetrics++; }

    // Technical health
    const healthAgg = await prisma.technicalAudit.aggregate({ where: { brandId: { in: brandIds } }, _avg: { crawlHealth: true } });
    if (healthAgg._avg.crawlHealth != null) { await upsertBenchmark(industry, "avg_crawl_health", Math.round(healthAgg._avg.crawlHealth), n); totalMetrics++; }

    // Content velocity
    const newPages = await prisma.pageRecord.count({ where: { brandId: { in: brandIds }, firstSeenAt: { gte: d30 } } });
    await upsertBenchmark(industry, "avg_new_pages_per_month", Math.round((newPages / n) * 10) / 10, n);
    totalMetrics++;

    // Engagement (from heatmaps)
    const scrollAgg = await prisma.heatmapEvent.aggregate({ where: { brandId: { in: brandIds }, eventType: "scroll" }, _avg: { maxScrollPercent: true, timeOnPage: true } });
    if (scrollAgg._avg.maxScrollPercent != null) { await upsertBenchmark(industry, "avg_scroll_depth", Math.round(scrollAgg._avg.maxScrollPercent), n); totalMetrics++; }
    if (scrollAgg._avg.timeOnPage != null) { await upsertBenchmark(industry, "avg_time_on_page", Math.round(scrollAgg._avg.timeOnPage), n); totalMetrics++; }
  }

  return { industries: industries.length, metrics: totalMetrics };
}

export async function getIndustryBenchmarks(industry: string): Promise<Record<string, { value: number; sampleSize: number }>> {
  const benchmarks = await prisma.industryBenchmark.findMany({ where: { industry, sampleSize: { gte: MIN_SAMPLE } }, orderBy: { computedAt: "desc" } });
  const map: Record<string, { value: number; sampleSize: number }> = {};
  for (const b of benchmarks) { if (!map[b.metric]) map[b.metric] = { value: b.value, sampleSize: b.sampleSize }; }
  return map;
}
