/**
 * Multilingual SEO Findings Synthesizer
 * ----------------------------------------
 * Surfaces hreflang, content parity, and regional targeting issues from
 * BilingualAudit data already computed in AuditInput.bilingualAuditContext.
 *
 * Fails open: if bilingualAuditContext is absent or any error occurs, returns [].
 * Audit pipeline must not block on this synthesizer.
 */

import type { AuditInput, PrioritizedFinding } from "@/lib/audit/types";

const MAX_FINDINGS = 5;

// US location signals: state abbreviations and common US region indicators.
// Used to detect region-targeting drift when bare language codes like "es" are used.
const US_STATE_ABBRS = new Set([
  "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", "HI", "ID",
  "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS",
  "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK",
  "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV",
  "WI", "WY", "DC",
]);

function hasUsLocationSignal(locations: string[]): boolean {
  return locations.some((loc) => {
    const upper = loc.trim().toUpperCase();
    if (upper === "US" || upper === "USA" || upper === "UNITED STATES") return true;
    // Match "City, ST" patterns -- check every token against the state abbreviation set
    const parts = upper.split(/[\s,]+/);
    return parts.some((part) => US_STATE_ABBRS.has(part));
  });
}

export async function runMultilingualSynthesizer(
  input: AuditInput,
): Promise<PrioritizedFinding[]> {
  try {
    const ctx = input.bilingualAuditContext;

    // Threshold gate -- return early if the site is not meaningfully multilingual.
    if (!ctx) return [];
    const hasMultipleLanguages = ctx.detectedLanguages.length >= 2;
    const hasSomeHreflang = ctx.hreflangImplementation.pagesWithHreflang > 0;
    if (!hasMultipleLanguages && !hasSomeHreflang) return [];

    const findings: PrioritizedFinding[] = [];
    const { hreflangImplementation, contentParity, detectedLanguages } = ctx;
    const langCount = detectedLanguages.length;
    const { coveragePercent, commonBugs } = hreflangImplementation;

    // ── Finding 1: hreflang_missing ───────────────────────────────────────────
    if (hreflangImplementation.status === "missing" && hasMultipleLanguages) {
      findings.push({
        rank: 200,
        title: "Hreflang missing on multilingual site",
        priority: "high",
        whatsWorking: `The site serves content in ${langCount} detected language${langCount !== 1 ? "s" : ""}, giving it the potential to reach a broader audience.`,
        whereItFallsShort:
          `Without hreflang annotations, search engines cannot identify which language-specific pages to serve ` +
          `to each user. With ${langCount} language${langCount !== 1 ? "s" : ""} detected and no hreflang ` +
          `in place, pages may surface to the wrong audience or compete against each other in search results.`,
        recommendedNextSteps: [
          "Add hreflang link elements (or HTTP headers) to every language variant of each page",
          "Include an x-default hreflang entry pointing to the fallback version for unsupported locales",
          "Ensure each URL self-references its own hreflang annotation",
          "Verify bidirectional hreflang -- every alternate URL must reference back to the original",
        ],
        dataSourceWeave: ["crawl"] as const,
        category: "multilingual" as const,
      });
    }

    // ── Finding 2: hreflang_mismatch / partial ────────────────────────────────
    if (hreflangImplementation.status === "partial" || commonBugs.length > 0) {
      const priority: "high" | "medium" = coveragePercent < 50 ? "high" : "medium";
      const bugsSnippet =
        commonBugs.length > 0
          ? ` Known issues include: ${commonBugs.slice(0, 2).map((b) => b.description).join("; ")}.`
          : "";
      findings.push({
        rank: 201,
        title: "Hreflang implementation incomplete",
        priority,
        whatsWorking: "Some hreflang annotations are present, which signals multilingual SEO intent to search engines.",
        whereItFallsShort:
          `Hreflang coverage is at ${coveragePercent.toFixed(0)}%, leaving a significant portion of pages ` +
          `without language targeting.${bugsSnippet} Incomplete hreflang can cause duplicate content ` +
          `signals and misrouted organic traffic across language variants.`,
        recommendedNextSteps: [
          "Audit all existing hreflang tags to confirm they reference correct language-region codes",
          "Fix bidirectional gaps -- every alternate page must point back to every other alternate",
          "Add self-referencing hreflang to all pages that are missing it",
          "Validate the full hreflang implementation in Google Search Console under the International Targeting report",
        ],
        dataSourceWeave: ["crawl"] as const,
        category: "multilingual" as const,
      });
    }

    // ── Finding 3: alternate_language_gap ────────────────────────────────────
    const languagesWithGaps = contentParity.perNonPrimaryLanguage.filter(
      (l) => l.pagesMissingEquivalent > 0,
    );
    if (languagesWithGaps.length > 0) {
      const totalMissing = languagesWithGaps.reduce(
        (sum, l) => sum + l.pagesMissingEquivalent,
        0,
      );
      // Find the language with the most gaps
      const worstLang = languagesWithGaps.reduce((a, b) =>
        a.pagesMissingEquivalent >= b.pagesMissingEquivalent ? a : b,
      );
      const worstLangName =
        detectedLanguages.find((d) => d.code === worstLang.code)?.displayName ?? worstLang.code;
      const priority: "high" | "medium" = totalMissing > 10 ? "high" : "medium";
      const affectedUrls = worstLang.topMissingPages
        .slice(0, 5)
        .map((p) => p.primaryUrl);

      findings.push({
        rank: 202,
        title: `Missing translated equivalents for ${totalMissing} page${totalMissing !== 1 ? "s" : ""}`,
        priority,
        whatsWorking: "A primary language version of these pages already exists, so the content foundation is in place.",
        whereItFallsShort:
          `${totalMissing} primary-language page${totalMissing !== 1 ? "s" : ""} have no translated equivalent. ` +
          `${worstLangName} has the largest gap at ${worstLang.pagesMissingEquivalent} missing ` +
          `page${worstLang.pagesMissingEquivalent !== 1 ? "s" : ""}. Without translated equivalents, ` +
          `search engines cannot surface these pages to the relevant audience segments.`,
        recommendedNextSteps: [
          "Prioritize translating the highest-traffic primary pages first to maximize audience reach",
          "Avoid auto-translate tools for thin or product-critical content -- they can produce low-quality pages that may be filtered from search results",
          "Add hreflang annotations as each new translated page goes live",
          "Check Google Search Console for language-specific crawl or indexing errors once translations are deployed",
        ],
        affectedUrls,
        dataSourceWeave: ["crawl"] as const,
        category: "multilingual" as const,
      });
    }

    // ── Finding 4: language_region_drift ─────────────────────────────────────
    // Bare language codes (e.g. "es") without a region suffix (e.g. "es-MX")
    // are too broad when the site targets a US-located audience.
    const isUsSite = hasUsLocationSignal(input.locations ?? []);
    const bareLanguageCodes = detectedLanguages.filter((l) => !l.code.includes("-"));

    if (isUsSite && bareLanguageCodes.length > 0) {
      const examples = bareLanguageCodes.map((l) => `"${l.code}"`).join(", ");
      findings.push({
        rank: 203,
        title: "Language codes missing regional targeting",
        priority: "medium",
        whatsWorking: "The site already signals multilingual intent by serving content in more than one language.",
        whereItFallsShort:
          `Bare language codes like ${examples} target all global speakers of those languages. ` +
          `For a US-located audience, bare "es" targets all Spanish speakers worldwide rather than ` +
          `"es-MX" for Mexico or "es-US" for US Spanish speakers, which can dilute regional relevance signals.`,
        recommendedNextSteps: [
          "Replace bare language codes with IETF BCP 47 language-region tags (e.g. es-MX, es-US, zh-TW) in all hreflang attributes",
          "Verify updated codes with Google's hreflang testing tool before deploying site-wide",
          "Align hreflang language-region codes with the target audience geography for your business",
        ],
        dataSourceWeave: ["crawl"] as const,
        category: "multilingual" as const,
      });
    }

    // ── Finding 5: x_default_missing ─────────────────────────────────────────
    const hasMissingXDefault = commonBugs.some((b) => b.type === "missing_x_default");
    if (hasMissingXDefault) {
      findings.push({
        rank: 204,
        title: "x-default hreflang missing",
        priority: "medium",
        whatsWorking: "Hreflang annotations are present for at least some language variants.",
        whereItFallsShort:
          "The x-default hreflang annotation is missing. Search engines use x-default to determine which " +
          "page to serve users whose browser language does not match any of the declared language variants. " +
          "Without it, those users may receive an incorrect or unpredictable language version.",
        recommendedNextSteps: [
          "Add rel=\"alternate\" hreflang=\"x-default\" pointing to the primary language version on every page that has hreflang annotations",
          "Include the x-default alternate entry in your XML sitemap language alternates section",
          "Test the updated hreflang set in Google's hreflang validator to confirm correct interpretation",
        ],
        dataSourceWeave: ["crawl"] as const,
        category: "multilingual" as const,
      });
    }

    // ── Sort by priority, then cap at MAX_FINDINGS ────────────────────────────
    const priorityOrder: Record<string, number> = {
      critical: 0,
      high: 1,
      medium: 2,
      low: 3,
    };
    findings.sort(
      (a, b) =>
        (priorityOrder[a.priority] ?? 99) - (priorityOrder[b.priority] ?? 99),
    );

    // Re-assign ranks after sort
    findings.forEach((f, i) => {
      f.rank = 200 + i;
    });

    return findings.slice(0, MAX_FINDINGS);
  } catch {
    return [];
  }
}
