/**
 * E-commerce Findings Synthesizer
 * ---------------------------------
 * Surfaces e-commerce-specific SEO issues from crawl data and SEO findings.
 * Deterministic only -- no LLM calls.
 *
 * Fails open: if the site is not detected as e-commerce or any error occurs,
 * returns []. Audit pipeline must not block on this synthesizer.
 */

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

const CATEGORY_ECOMMERCE = "ecommerce" as const;
const MAX_FINDINGS = 6;
const MAX_AFFECTED_URLS = 5;

// ─── E-commerce detection ─────────────────────────────────────────────────────

function isEcommerceSite(input: AuditInput, seoFindings: SeoFindings | null): boolean {
  // Industry context signals
  const industries = input.industryContext?.industries ?? [];
  if (industries.some((ind) => ind.startsWith("ecommerce"))) return true;
  if (input.industryContext?.industry?.startsWith("ecommerce")) return true;

  // Page structural signals
  const pages = input.pageStrategicPassContext?.pages ?? [];
  if (pages.some((p) => p.structuralSignals.schemaTypes.includes("Product"))) return true;
  if (
    pages.some((p) =>
      /products?\/|\/shop\/|\/store\/|\/collections?\//i.test(p.url),
    )
  )
    return true;

  // SEO findings signals
  if (seoFindings?.schema.typesDetected.includes("Product")) return true;

  return false;
}

// ─── Severity sort helper ─────────────────────────────────────────────────────

const SEVERITY_ORDER: Record<string, number> = {
  critical: 0,
  high: 1,
  medium: 2,
  low: 3,
};

function sortBySeverity(findings: PrioritizedFinding[]): PrioritizedFinding[] {
  return [...findings].sort(
    (a, b) => (SEVERITY_ORDER[a.priority] ?? 99) - (SEVERITY_ORDER[b.priority] ?? 99),
  );
}

// ─── Individual finding builders ──────────────────────────────────────────────

function buildProductSchemaIncomplete(
  input: AuditInput,
  rankBase: number,
): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const affected = pages.filter(
    (p) =>
      p.structuralSignals.schemaTypes.includes("Product") &&
      !p.structuralSignals.schemaTypes.includes("Offer"),
  );
  if (affected.length === 0) return null;

  const count = affected.length;
  const priority = count >= 3 ? "high" : "medium";

  return {
    rank: rankBase,
    title: `Product schema missing Offer data on ${count} product page${count !== 1 ? "s" : ""}`,
    priority,
    whatsWorking:
      "Product schema is present on these pages, providing Google with some structured data to identify product content.",
    whereItFallsShort:
      "Google cannot display price, availability, or currency in rich results without Offer schema. Products without Offer markup lose eligibility for Shopping results and price snippets, reducing visibility in high-intent search experiences.",
    recommendedNextSteps: [
      "Add an Offer property to each Product schema block, including priceCurrency and price fields",
      "Add an availability property using a schema.org/ItemAvailability value such as InStock or OutOfStock",
      "Add priceValidUntil for any time-limited or promotional pricing to maintain accuracy",
      "Validate the updated markup with Google Rich Results Test before deploying to production",
    ],
    affectedUrls: affected.slice(0, MAX_AFFECTED_URLS).map((p) => p.url),
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_ECOMMERCE,
  };
}

function buildAggregateRatingMissing(
  input: AuditInput,
  rankBase: number,
): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const productPages = pages.filter((p) =>
    p.structuralSignals.schemaTypes.includes("Product"),
  );
  if (productPages.length < 3) return null;

  const affected = productPages.filter(
    (p) => !p.structuralSignals.schemaTypes.includes("AggregateRating"),
  );
  if (affected.length === 0) return null;

  return {
    rank: rankBase,
    title: "AggregateRating missing on product pages",
    priority: "medium",
    whatsWorking:
      "Product schema is in place and gives Google context about product content across the catalog.",
    whereItFallsShort:
      "Product pages without AggregateRating cannot display star ratings in Google SERP. Star ratings significantly improve click-through rates on shopping results, and their absence means the site competes without a visual trust signal that many competitors display.",
    recommendedNextSteps: [
      "Add AggregateRating to each Product schema block, including ratingValue, ratingCount, and bestRating",
      "Implement a review collection system (email follow-up, post-purchase prompt) to generate genuine ratings",
      "Validate the updated markup with Google Rich Results Test to confirm eligibility",
      "Resubmit the sitemap after implementation so Google recrawls updated product pages promptly",
    ],
    affectedUrls: affected.slice(0, MAX_AFFECTED_URLS).map((p) => p.url),
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_ECOMMERCE,
  };
}

function buildBreadcrumbSchemaMissing(
  input: AuditInput,
  rankBase: number,
): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const candidates = pages.filter(
    (p) =>
      p.structuralSignals.schemaTypes.includes("Product") ||
      /\/categor|\/collections?\//i.test(p.url),
  );
  if (candidates.length === 0) return null;

  const affected = candidates.filter(
    (p) => !p.structuralSignals.schemaTypes.includes("BreadcrumbList"),
  );
  if (affected.length === 0) return null;

  return {
    rank: rankBase,
    title: "Breadcrumb schema missing on product and category pages",
    priority: "medium",
    whatsWorking:
      "Product and category pages are indexable and accessible to search engines.",
    whereItFallsShort:
      "BreadcrumbList schema enables breadcrumb display in SERP, showing the navigation path beneath the page title. Breadcrumbs improve user navigation clarity and help search engines understand site structure, particularly for deep catalog hierarchies.",
    recommendedNextSteps: [
      "Add BreadcrumbList schema to product page templates, reflecting the full category path to the item",
      "Ensure the breadcrumb hierarchy in schema mirrors the actual URL and navigation hierarchy",
      "Include BreadcrumbList on category and collection pages as well as individual product detail pages",
    ],
    affectedUrls: affected.slice(0, MAX_AFFECTED_URLS).map((p) => p.url),
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_ECOMMERCE,
  };
}

function buildCategoryPageThinContent(
  input: AuditInput,
  rankBase: number,
): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const affected = pages.filter(
    (p) =>
      /\/categor|\/collection|\/shop\//i.test(p.url) &&
      p.structuralSignals.wordCount !== null &&
      (p.structuralSignals.wordCount as number) < 150,
  );
  if (affected.length < 2) return null;

  const count = affected.length;

  return {
    rank: rankBase,
    title: `Category pages have thin content (${count} pages)`,
    priority: "medium",
    whatsWorking:
      "Category pages are crawlable and accessible, allowing search engines to index the product catalog structure.",
    whereItFallsShort:
      "Category pages with only a product grid and no descriptive content struggle to rank for broad category queries. Google's quality guidelines expect category pages to provide value beyond product listings, and thin category pages are frequently outranked by competitors with richer content.",
    recommendedNextSteps: [
      "Add 100 to 200 words of category description above or below the product grid on each affected page",
      "Include relevant keywords naturally in the category description based on how shoppers search for this category",
      "Add a buying guide or FAQ section relevant to the category to increase depth and answer searcher intent",
      "Ensure the added content provides genuine value for shoppers at the consideration stage, not keyword stuffing",
    ],
    affectedUrls: affected.slice(0, MAX_AFFECTED_URLS).map((p) => p.url),
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_ECOMMERCE,
  };
}

function buildProductImageAltPattern(
  seoFindings: SeoFindings,
  rankBase: number,
): PrioritizedFinding | null {
  const { missingAlt, totalImages } = seoFindings.images;
  if (!missingAlt || missingAlt <= 0) return null;
  if (!totalImages || totalImages <= 0) return null;

  const percent = missingAlt / totalImages;
  if (percent <= 0.2) return null;

  const priority = percent > 0.5 ? "high" : "medium";

  return {
    rank: rankBase,
    title: `Product images missing alt text (${missingAlt} images)`,
    priority,
    whatsWorking:
      "Images are present and loading on product pages, supporting the visual merchandising experience.",
    whereItFallsShort:
      "Product images without alt text cannot be discovered through Google Image Search, which drives significant traffic for e-commerce sites. Missing alt text also fails WCAG 1.1.1 accessibility requirements, creating compliance risk and excluding users who rely on screen readers.",
    recommendedNextSteps: [
      "Add descriptive alt text to all product images using a brand plus product name pattern (e.g. 'Brand Model in Color')",
      "Avoid generic alt text such as 'product image' or SKU codes alone, which provide no search or accessibility value",
      "Include key visual descriptors like color, material, and size when those attributes are visible in the image",
      "For large catalogs, automate alt text generation using the product name and primary category as the base template",
    ],
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_ECOMMERCE,
  };
}

function buildInternalSearchIndexable(
  input: AuditInput,
  rankBase: number,
): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const affected = pages.filter(
    (p) => p.url.includes("?q=") || p.url.includes("/search?"),
  );
  if (affected.length === 0) return null;

  return {
    rank: rankBase,
    title: "Internal search result pages may be indexable",
    priority: "medium",
    whatsWorking:
      "The site has internal search functionality, which helps users find products efficiently.",
    whereItFallsShort:
      "Search result pages indexed by Google typically create thin-content soft-404 issues. Google may crawl and index these pages, diluting the site's overall quality signals and wasting crawl budget that could be spent on product and category pages.",
    recommendedNextSteps: [
      "Add a noindex meta tag to all search result page templates to prevent Google from indexing them",
      "Block search result paths (e.g. /search?) in robots.txt as a secondary signal",
      "Remove any search result URLs from the sitemap if they were inadvertently included",
    ],
    affectedUrls: affected.slice(0, MAX_AFFECTED_URLS).map((p) => p.url),
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_ECOMMERCE,
  };
}

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

export async function runEcommerceSynthesizer(
  input: AuditInput,
  seoFindings: SeoFindings | null,
): Promise<PrioritizedFinding[]> {
  try {
    if (!isEcommerceSite(input, seoFindings)) return [];

    const candidates: Array<PrioritizedFinding | null> = [
      buildProductSchemaIncomplete(input, 400),
      buildAggregateRatingMissing(input, 401),
      buildBreadcrumbSchemaMissing(input, 402),
      buildCategoryPageThinContent(input, 403),
      seoFindings ? buildProductImageAltPattern(seoFindings, 404) : null,
      buildInternalSearchIndexable(input, 405),
    ];

    const findings = candidates.filter((f): f is PrioritizedFinding => f !== null);
    const sorted = sortBySeverity(findings);

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