/**
 * Real-User Technical Findings Synthesizer
 * -----------------------------------------
 * Surfaces non-SEO technical issues from Site Tag behavioral data that are
 * invisible to conventional SEO tools. Initial scope: high-frequency JS error
 * patterns. Architecture supports additional subcategories in future phases.
 *
 * Fails open: if Site Tag is not installed or has no data, returns [].
 * Audit pipeline must not block on this synthesizer.
 */

import { getErrorPatterns } from "@/lib/services/site-tag-analytics";
import type { PrioritizedFinding } from "@/lib/audit/types";

// Thresholds for promoting a JS error pattern to a finding.
const OCCURRENCE_THRESHOLD = 100;
const SESSION_THRESHOLD = 20;
const MAX_FINDINGS = 5;

// URL params that indicate paid or tracked acquisition traffic.
// Errors firing on these sessions have higher business impact.
const PAID_TRAFFIC_PARAMS = ["utm_source", "utm_medium", "fbclid", "gclid", "hsa_acc", "msclkid"];

function isPaidTrafficPage(pageUrl: string): boolean {
  try {
    const params = new URL(pageUrl).searchParams;
    return PAID_TRAFFIC_PARAMS.some((p) => params.has(p));
  } catch {
    return false;
  }
}

function errorPatternTitle(message: string, filename: string | null): string {
  const shortMsg = message.length > 60 ? message.slice(0, 60) + "..." : message;
  if (filename) {
    try {
      const path = new URL(filename).pathname;
      const file = path.split("/").pop() ?? path;
      return `JS error in ${file}: "${shortMsg}"`;
    } catch {
      // filename is a relative path
      const file = filename.split("/").pop() ?? filename;
      return `JS error in ${file}: "${shortMsg}"`;
    }
  }
  return `JS error: "${shortMsg}"`;
}

function errorPatternDescription(
  occurrenceCount: number,
  affectedPageCount: number,
  affectedSessionCount: number,
  topPage: string | null,
): string {
  const parts = [
    `Fires approximately ${occurrenceCount.toLocaleString()} times in the last 30 days`,
    `across ${affectedSessionCount} user sessions on ${affectedPageCount} page${affectedPageCount !== 1 ? "s" : ""}`,
  ];
  if (topPage) parts.push(`Most frequently on: ${topPage}`);
  return parts.join(". ") + ". This is a first-party signal invisible to conventional SEO tools.";
}

export async function runRealUserTechnicalSynthesizer(
  brandId: string,
): Promise<PrioritizedFinding[]> {
  let patterns;
  try {
    patterns = await getErrorPatterns(brandId);
  } catch {
    return [];
  }

  if (!patterns.length) return [];

  const qualifying = patterns.filter(
    (p) => p.occurrenceCount >= OCCURRENCE_THRESHOLD || p.affectedSessionCount >= SESSION_THRESHOLD,
  );
  if (!qualifying.length) return [];

  const findings: PrioritizedFinding[] = qualifying
    .slice(0, MAX_FINDINGS)
    .map((p, i) => {
      const topPage = p.topPages[0]?.pageUrl ?? null;
      const hasPaidTraffic = p.topPages.some((pg) => isPaidTrafficPage(pg.pageUrl));
      const priority: "critical" | "high" = hasPaidTraffic ? "critical" : "high";

      return {
        rank: 100 + i, // place after SEO findings in default sort
        title: errorPatternTitle(p.message, p.filename),
        priority,
        whatsWorking: "Site Tag behavioral telemetry is capturing real-user JavaScript errors as they occur.",
        whereItFallsShort: errorPatternDescription(
          p.occurrenceCount,
          p.affectedPageCount,
          p.affectedSessionCount,
          topPage,
        ),
        recommendedNextSteps: [
          "Open the browser console on the affected page and reproduce the error",
          "Replace polling-based code with event-driven patterns (MutationObserver, addEventListener) to eliminate loop errors",
          "Add null checks before accessing DOM elements that may not exist on page load",
          "Audit third-party scripts -- wrap integrations in try/catch to prevent cascading failures",
        ],
        affectedUrls: p.topPages.slice(0, 5).map((pg) => pg.pageUrl),
        dataSourceWeave: ["crawl"] as const,
        category: "tech" as const,
      };
    });

  return findings;
}
