/**
 * AI Source Attribution Comparison — Public Signal Prediction vs First-Party Measurement
 * ─────────────────────────────────────────────────────────────────────────────────────────
 * Runs the same public-signal analysis used in 3rd-party audits and compares
 * those predictions against what the Site Tag actually measured.
 *
 * 1st-party only — returns null when no AI attribution data is available.
 * Internal module — no third-party vendor names in user-facing output.
 */

import type {
  AiAttributionContext,
  BehavioralContext,
  SignalCenter,
  AiSourceAttributionComparison,
  AttributionDimension,
} from "../types";
import type { SerpAnalysis } from "./serp-analysis";
import { INDUSTRY_BENCHMARKS } from "../data/industry-benchmarks";
import type { IndustryContext } from "../synthesizers/industry-classifier";

// ─── Static benchmarks ────────────────────────────────────────────────────────

const AI_CONVERSION_RATE_BENCHMARKS: Record<string, { midpoint: number; label: string }> = {
  "local-services":        { midpoint: 4.0,  label: "2.5–5.5%" },
  "healthcare-medical":    { midpoint: 2.5,  label: "1.5–3.5%" },
  "healthcare-dental":     { midpoint: 3.2,  label: "2.0–4.5%" },
  "b2b-saas":              { midpoint: 1.8,  label: "1.0–2.5%" },
  "ecommerce":             { midpoint: 2.2,  label: "1.5–3.0%" },
  "professional-services": { midpoint: 3.0,  label: "2.0–4.0%" },
  "finance":               { midpoint: 1.8,  label: "1.0–2.5%" },
  "legal":                 { midpoint: 3.8,  label: "2.5–5.0%" },
  "real-estate":           { midpoint: 2.5,  label: "1.5–3.5%" },
  "nonprofit":             { midpoint: 1.2,  label: "0.5–2.0%" },
  "hospitality":           { midpoint: 3.2,  label: "2.0–4.5%" },
  "higher-ed":             { midpoint: 1.2,  label: "0.5–2.0%" },
  "other":                 { midpoint: 2.5,  label: "1.5–3.5%" },
};

// Industry-standard AI engine traffic share distribution
const AI_ENGINE_SHARE_BENCHMARK: Record<string, number> = {
  chatgpt:    35,
  perplexity: 25,
  gemini:     20,
  copilot:    15,
  claude:      5,
};

// ─── Helpers ──────────────────────────────────────────────────────────────────

function roundTo(n: number, decimals = 1): number {
  const factor = Math.pow(10, decimals);
  return Math.round(n * factor) / factor;
}

function deltaDirection(deltaPercent: number): AttributionDimension["deltaDirection"] {
  if (Math.abs(deltaPercent) < 15) return "aligned";
  return deltaPercent < 0 ? "predicted_overestimated" : "predicted_underestimated";
}

function resolveEngineId(raw: string): string {
  const lower = raw.toLowerCase().trim();
  if (lower.includes("perplexity")) return "perplexity";
  if (lower.includes("claude")) return "claude";
  if (lower.includes("gemini") || lower.includes("bard")) return "gemini";
  if (lower.includes("copilot") || lower.includes("bing")) return "copilot";
  if (lower.includes("chatgpt") || lower.includes("openai") || lower.includes("gpt")) return "chatgpt";
  return lower;
}

function engineDisplayName(engineId: string): string {
  const map: Record<string, string> = {
    chatgpt: "ChatGPT",
    perplexity: "Perplexity",
    gemini: "Gemini",
    copilot: "Microsoft Copilot",
    claude: "Claude",
  };
  return map[engineId] ?? engineId;
}

// ─── Per-dimension computation ────────────────────────────────────────────────

function computeCitationRateDimension(
  serpAnalysis: SerpAnalysis | null,
  aiAttribution: AiAttributionContext,
  signalCenter: SignalCenter | null,
): AttributionDimension | null {
  if (!serpAnalysis || signalCenter === null || signalCenter.totalSessions === 0) return null;

  const totalQueries = serpAnalysis.aiOverviewPresence.length;
  if (totalQueries === 0) return null;

  const brandCited = serpAnalysis.aiOverviewPresence.filter((a) => a.brandMentioned).length;
  const predictedPct = roundTo((brandCited / totalQueries) * 100);

  const actualAiSharePct = roundTo((aiAttribution.totalAiReferrals / signalCenter.totalSessions) * 100);

  const deltaPercent = predictedPct > 0
    ? roundTo(((actualAiSharePct - predictedPct) / predictedPct) * 100)
    : 0;

  return {
    dimension: "AI Overview Citation → AI Referral Rate",
    publicSignalPrediction: {
      value: predictedPct,
      method: `SERP analysis: ${brandCited}/${totalQueries} tracked queries returned an AI Overview citing the brand`,
      confidence: totalQueries >= 5 ? "moderate" : "low",
    },
    firstPartyActual: {
      value: actualAiSharePct,
      measurementMethod: "Site Tag: AI referrals as a share of total measured sessions",
      sampleSize: signalCenter.totalSessions,
    },
    deltaPercent,
    deltaDirection: deltaDirection(deltaPercent),
    explanation: deltaPercent < -30
      ? `Public AI Overview citation rate of ${predictedPct}% did not translate to proportional referral traffic — actual AI share is ${actualAiSharePct}% of sessions. Citations appear in AI Overviews but visitors may not be clicking through at the expected rate.`
      : deltaPercent > 30
      ? `Site Tag data shows AI traffic share (${actualAiSharePct}%) running above what SERP-based prediction would suggest (${predictedPct}%). The brand likely receives AI referrals from queries beyond those tracked in the SERP sample.`
      : `Public signal prediction (${predictedPct}%) and first-party measurement (${actualAiSharePct}%) are reasonably aligned, suggesting SERP-based visibility is converting to traffic at a normal rate.`,
  };
}

function computeTopEngineDimension(
  aiAttribution: AiAttributionContext,
): AttributionDimension | null {
  if (aiAttribution.totalAiReferrals === 0 || aiAttribution.topEngines.length === 0) return null;

  const topEngine = aiAttribution.topEngines[0]!;
  const topEngineId = resolveEngineId(topEngine.engine);
  const topEngineDisplayName = engineDisplayName(topEngineId);

  const actualSharePct = roundTo((topEngine.count / aiAttribution.totalAiReferrals) * 100);
  const predictedTopEngineId = "chatgpt";
  const predictedTopSharePct = AI_ENGINE_SHARE_BENCHMARK[predictedTopEngineId] ?? 35;

  // Delta: compare predicted share of ChatGPT vs actual share of actual top engine
  // If top engine is same as predicted (ChatGPT), compare shares
  // If different, show magnitude of inversion
  const deltaPercent = predictedTopEngineId === topEngineId
    ? roundTo(((actualSharePct - predictedTopSharePct) / predictedTopSharePct) * 100)
    : roundTo(((actualSharePct - predictedTopSharePct) / predictedTopSharePct) * 100);

  const isInversion = topEngineId !== predictedTopEngineId;

  return {
    dimension: "Top AI Traffic Source",
    publicSignalPrediction: {
      value: `ChatGPT (~${predictedTopSharePct}% share)`,
      method: "Industry benchmark: ChatGPT is the dominant AI referral source at ~35% share across most verticals",
      confidence: "low",
    },
    firstPartyActual: {
      value: `${topEngineDisplayName} (${actualSharePct}% share)`,
      measurementMethod: "Site Tag: actual AI session source attribution by engine (trailing 30 days)",
      sampleSize: aiAttribution.totalAiReferrals,
    },
    deltaPercent,
    deltaDirection: isInversion ? "predicted_underestimated" : deltaDirection(deltaPercent),
    explanation: isInversion
      ? `Industry benchmarks would predict ChatGPT as the dominant AI source at ~${predictedTopSharePct}% share, but first-party data shows ${topEngineDisplayName} at ${actualSharePct}%. This inversion has direct implications for content optimization: this brand should prioritize ${topEngineDisplayName}-specific signals (${topEngineId === "copilot" ? "Bing indexing, transactional schema, commercial landing pages" : topEngineId === "perplexity" ? "recency signals, dateModified metadata, comparison content" : "E-E-A-T signals, structured definitions, authority content"}).`
      : `Site Tag data confirms ChatGPT as the top AI source at ${actualSharePct}% share, broadly aligned with the industry benchmark of ~${predictedTopSharePct}%. ChatGPT-specific optimizations (FAQPage schema, E-E-A-T signals) represent the highest-leverage schema investments.`,
  };
}

function computeAiConversionRateDimension(
  aiAttribution: AiAttributionContext,
  industry: string,
): AttributionDimension | null {
  if (aiAttribution.totalAiReferrals === 0) return null;

  const benchmark = AI_CONVERSION_RATE_BENCHMARKS[industry] ?? AI_CONVERSION_RATE_BENCHMARKS["other"]!;
  const predictedPct = benchmark.midpoint;
  const actualPct = roundTo((aiAttribution.totalConversions30d / aiAttribution.totalAiReferrals) * 100);

  const deltaPercent = roundTo(((actualPct - predictedPct) / predictedPct) * 100);

  return {
    dimension: "AI Visitor Conversion Rate",
    publicSignalPrediction: {
      value: predictedPct,
      method: `Industry benchmark for ${industry}: ${benchmark.label} AI conversion rate midpoint`,
      confidence: "low",
    },
    firstPartyActual: {
      value: actualPct,
      measurementMethod: "Site Tag: AI-attributed conversions / AI referrals (trailing 30 days)",
      sampleSize: aiAttribution.totalAiReferrals,
    },
    deltaPercent,
    deltaDirection: deltaDirection(deltaPercent),
    explanation: actualPct < predictedPct * 0.5
      ? `AI traffic converts at ${actualPct}%, well below the ${industry} benchmark of ${benchmark.label}. AI visitors are landing but not converting — this is a conversion pathway gap, not a traffic acquisition problem. The site needs stronger CTAs and clearer conversion pathways on the pages AI traffic lands on.`
      : actualPct > predictedPct * 1.5
      ? `AI traffic converts at ${actualPct}%, significantly above the ${industry} benchmark of ${benchmark.label}. AI visitors are highly qualified. The opportunity is volume expansion rather than conversion optimization — more AI referral traffic would directly amplify this above-benchmark rate.`
      : `AI conversion rate of ${actualPct}% falls within the ${industry} benchmark range of ${benchmark.label}. AI traffic quality is on par with industry expectations; growth requires either more AI referral volume or pushing conversion rate toward the top of the benchmark range.`,
  };
}

function computeTopLandingPageDimension(
  aiAttribution: AiAttributionContext,
): AttributionDimension | null {
  if (aiAttribution.topPages.length === 0) return null;

  const topActualPage = aiAttribution.topPages[0]!;
  const topActualPath = topActualPage.url.replace(/^https?:\/\/[^/]+/, "") || "/";
  const isHomepage = topActualPath === "/" || topActualPath === "";

  const totalAiVisits = aiAttribution.topPages.reduce((s, p) => s + p.aiVisits, 0);
  const topPageShare = totalAiVisits > 0
    ? roundTo((topActualPage.aiVisits / totalAiVisits) * 100)
    : 0;

  // Predicted: homepage as the authority page most likely to be cited
  const predicted = "Homepage (authority + brand page)";
  const delta = isHomepage ? 0 : -100; // -100 signals misalignment

  return {
    dimension: "Top AI-Cited Landing Page",
    publicSignalPrediction: {
      value: predicted,
      method: "Authority heuristic: homepage typically receives the highest inbound link concentration and is most likely to appear in AI citation results",
      confidence: "low",
    },
    firstPartyActual: {
      value: `${topActualPath} (${topPageShare}% of AI landings)`,
      measurementMethod: "Site Tag: first-touch landing page for all AI-referred sessions",
      sampleSize: aiAttribution.totalAiReferrals,
    },
    deltaPercent: delta,
    deltaDirection: isHomepage ? "aligned" : "predicted_underestimated",
    explanation: isHomepage
      ? `The homepage is confirmed as the top AI-cited landing page at ${topPageShare}% of AI landings, matching the authority-based prediction. This is the expected pattern for brand-cited AI queries.`
      : `Contrary to the authority-based prediction, AI traffic concentrates on ${topActualPath} (${topPageShare}% of AI landings) rather than the homepage. AI engines are surfacing this specific page for transactional or topic-specific queries. This page's schema, CTA, and content depth deserve prioritized investment.`,
  };
}

function computeAiBounceRateDimension(
  aiAttribution: AiAttributionContext,
  behavioralData: BehavioralContext | null,
): AttributionDimension | null {
  if (!behavioralData || aiAttribution.topPages.length === 0) return null;

  const normUrl = (u: string) => u.toLowerCase().replace(/^https?:\/\/[^/]+/, "").replace(/\/$/, "");

  // Avg bounce rate across AI landing pages that have behavioral data
  const aiPageBounces: number[] = [];
  for (const aiPage of aiAttribution.topPages.slice(0, 5)) {
    const behav = behavioralData.pages.find((p) => normUrl(p.url) === normUrl(aiPage.url));
    if (behav?.bounceRate !== null && behav?.bounceRate !== undefined) {
      aiPageBounces.push(behav.bounceRate);
    }
  }

  if (aiPageBounces.length === 0) return null;

  const avgAiBounce = roundTo(
    (aiPageBounces.reduce((s, r) => s + r, 0) / aiPageBounces.length) * 100,
  );

  // Overall avg bounce rate from all behavioral pages as baseline
  const allBounces = behavioralData.pages
    .filter((p) => p.bounceRate !== null)
    .map((p) => p.bounceRate as number);

  if (allBounces.length === 0) return null;

  const avgOverallBounce = roundTo(
    (allBounces.reduce((s, r) => s + r, 0) / allBounces.length) * 100,
  );

  // Predicted: AI visitors engage at least as well as average (industry expectation)
  const predicted = avgOverallBounce;
  const deltaPercent = roundTo(((avgAiBounce - predicted) / predicted) * 100);

  return {
    dimension: "AI Visitor Bounce Rate vs Site Average",
    publicSignalPrediction: {
      value: `${predicted}%`,
      method: "Baseline assumption: AI-referred visitors engage at parity with site-average visitors",
      confidence: "low",
    },
    firstPartyActual: {
      value: `${avgAiBounce}%`,
      measurementMethod: `Site Tag: bounce rate on top ${aiPageBounces.length} AI-cited pages`,
      sampleSize: aiPageBounces.length,
    },
    deltaPercent,
    deltaDirection: deltaDirection(deltaPercent),
    explanation: avgAiBounce < avgOverallBounce * 0.85
      ? `AI visitors bounce at ${avgAiBounce}% vs the site average of ${avgOverallBounce}% — they are more engaged than typical visitors. AI-referred traffic is high-intent and the landing pages are serving them well.`
      : avgAiBounce > avgOverallBounce * 1.15
      ? `AI visitors bounce at ${avgAiBounce}% vs the site average of ${avgOverallBounce}% — they are less engaged than typical visitors. AI-referred sessions reach the landing page but don't find what they expect. Review the content match between the AI-cited pages and the queries triggering those citations.`
      : `AI visitor bounce rate (${avgAiBounce}%) is roughly in line with the site-wide average (${avgOverallBounce}%), indicating AI-referred traffic engages at parity with other channels.`,
  };
}

// ─── Gap magnitude ────────────────────────────────────────────────────────────

function computeGapMagnitude(dimensions: AttributionDimension[]): AiSourceAttributionComparison["overallGapMagnitude"] {
  const maxDelta = Math.max(...dimensions.map((d) => Math.abs(d.deltaPercent)));
  if (maxDelta >= 50) return "significant";
  if (maxDelta >= 20) return "moderate";
  return "minimal";
}

// ─── Main export ──────────────────────────────────────────────────────────────

export function aggregateAiSourceAttributionComparison(
  serpAnalysis: SerpAnalysis | null,
  industryContext: IndustryContext | null,
  signalCenter: SignalCenter | null,
  aiAttribution: AiAttributionContext | null,
  behavioralData: BehavioralContext | null,
): AiSourceAttributionComparison | null {
  if (!aiAttribution || aiAttribution.totalAiReferrals === 0) return null;

  const industry = industryContext?.industry ?? "other";
  const now = new Date();
  const start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);

  const dimensions: AttributionDimension[] = [];

  // Compute each dimension with per-dimension error isolation
  try {
    const d = computeCitationRateDimension(serpAnalysis, aiAttribution, signalCenter);
    if (d) dimensions.push(d);
  } catch { /* skip dimension on error */ }

  try {
    const d = computeTopEngineDimension(aiAttribution);
    if (d) dimensions.push(d);
  } catch { /* skip dimension on error */ }

  try {
    const d = computeAiConversionRateDimension(aiAttribution, industry);
    if (d) dimensions.push(d);
  } catch { /* skip dimension on error */ }

  try {
    const d = computeTopLandingPageDimension(aiAttribution);
    if (d) dimensions.push(d);
  } catch { /* skip dimension on error */ }

  try {
    const d = computeAiBounceRateDimension(aiAttribution, behavioralData);
    if (d) dimensions.push(d);
  } catch { /* skip dimension on error */ }

  if (dimensions.length === 0) return null;

  const gapMagnitude = computeGapMagnitude(dimensions);

  // Build top insights
  const topInsights: AiSourceAttributionComparison["topInsights"] = [];

  const engineDim = dimensions.find((d) => d.dimension === "Top AI Traffic Source");
  if (engineDim && engineDim.deltaDirection !== "aligned") {
    topInsights.push({
      insight: engineDim.explanation,
      supportingDimension: "Top AI Traffic Source",
      patentRelevance: "Site Tag engine-level attribution reveals which engines actually drive traffic — undetectable from public signals alone",
    });
  }

  const convDim = dimensions.find((d) => d.dimension === "AI Visitor Conversion Rate");
  if (convDim) {
    topInsights.push({
      insight: convDim.explanation,
      supportingDimension: "AI Visitor Conversion Rate",
      patentRelevance: "Site Tag conversion event tracking closes the attribution loop from AI citation to revenue — impossible to infer from public signals",
    });
  }

  const pageDim = dimensions.find((d) => d.dimension === "Top AI-Cited Landing Page");
  if (pageDim && pageDim.deltaDirection !== "aligned") {
    topInsights.push({
      insight: pageDim.explanation,
      supportingDimension: "Top AI-Cited Landing Page",
      patentRelevance: "First-touch landing page measurement reveals which transactional pages AI engines favor — invisible to public authority analysis",
    });
  }

  const citeDim = dimensions.find((d) => d.dimension === "AI Overview Citation → AI Referral Rate");
  if (citeDim && Math.abs(citeDim.deltaPercent) >= 30) {
    topInsights.push({
      insight: citeDim.explanation,
      supportingDimension: "AI Overview Citation → AI Referral Rate",
      patentRelevance: "Only the Site Tag measures whether AI Overview citations actually convert to referral traffic — the SERP-to-traffic conversion gap is otherwise unmeasurable",
    });
  }

  // Fill to minimum 3 insights
  if (topInsights.length < 3) {
    for (const dim of dimensions) {
      if (topInsights.some((i) => i.supportingDimension === dim.dimension)) continue;
      topInsights.push({
        insight: dim.explanation,
        supportingDimension: dim.dimension,
        patentRelevance: "Site Tag first-party measurement captures signals that public analysis cannot access",
      });
      if (topInsights.length >= 3) break;
    }
  }

  const topEngine = aiAttribution.topEngines[0];
  const topEngineId = topEngine ? resolveEngineId(topEngine.engine) : null;
  const topEngineDisplay = topEngineId ? engineDisplayName(topEngineId) : "AI engines";

  const overallGapNarrative = gapMagnitude === "significant"
    ? `Public signal analysis systematically mis-predicts this brand's AI search reality. The most consequential gap is the top AI source engine — industry benchmarks would predict ChatGPT dominance, but first-party data reveals ${topEngineDisplay} as the actual primary driver. Without first-party measurement, content optimization would have been directed at the wrong engine's citation signals.`
    : gapMagnitude === "moderate"
    ? `Public signal analysis provides a directional estimate of this brand's AI search performance, but first-party measurement reveals meaningful gaps in at least ${dimensions.filter((d) => Math.abs(d.deltaPercent) >= 20).length} of ${dimensions.length} dimensions. The most actionable gap is the ${dimensions.sort((a, b) => Math.abs(b.deltaPercent) - Math.abs(a.deltaPercent))[0]?.dimension ?? "conversion rate"} dimension.`
    : `Public signal analysis is reasonably aligned with first-party measurement for this brand — the predictions hold within typical variance across ${dimensions.length} measured dimensions. This indicates the brand's authority signals are translating to AI traffic performance at the expected rate.`;

  return {
    hasFirstPartyData: true,
    comparisonWindow: {
      startDate: start,
      endDate: now,
      daysCovered: 30,
    },
    predictionVsActual: dimensions,
    topInsights: topInsights.slice(0, 5),
    overallGapMagnitude: gapMagnitude,
    overallGapNarrative,
  };
}
