/**
 * B2B Findings Synthesizer
 * -------------------------
 * Surfaces B2B-specific SEO issues from crawl and structural signals.
 * Only runs when the site is detected as a B2B property.
 *
 * Fails open: if the site is not B2B or any error occurs, returns [].
 * Deterministic only -- no LLM calls.
 */

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

const CATEGORY_B2B = "b2b" as const;
const MAX_FINDINGS = 5;
const MAX_AFFECTED_URLS = 5;

const B2B_URL_PATTERN = /pricing|\/plans|\/case-stud|\/customers|\/resources|\/solutions|\/whitepapers|\/ebook/i;

// ─── B2B detection ────────────────────────────────────────────────────────────

function isB2bSite(input: AuditInput): boolean {
  // Industry context signals
  const industries = input.industryContext?.industries ?? [];
  if (industries.some((ind) => ind.startsWith("b2b-"))) return true;
  if (input.industryContext?.industry?.startsWith("b2b")) return true;

  // Page URL signals
  const pages = input.pageStrategicPassContext?.pages ?? [];
  if (pages.some((p) => B2B_URL_PATTERN.test(p.url))) return true;

  // Conversion path signals
  const conversionPaths = input.industryContext?.conversionPathExpectation ?? [];
  if (
    conversionPaths.some((path) =>
      /demo|sales|trial/i.test(path),
    )
  )
    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 buildPricingPageSeo(input: AuditInput, rankBase: number): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const hasPricingPage = pages.some((p) => /pricing|plans/i.test(p.url));
  if (hasPricingPage) return null;

  // Build a whatsWorking string based on other B2B signals found
  const hasCaseStudies = pages.some((p) => /case-stud|customer|success-stor|testimonial/i.test(p.url));
  const hasResources = pages.some((p) => /\/resources|\/whitepaper|\/ebook|\/guide/i.test(p.url));
  const hasSolutions = pages.some((p) => /\/solutions|\/use-case/i.test(p.url));

  const workingSignals: string[] = [];
  if (hasCaseStudies) workingSignals.push("case studies");
  if (hasResources) workingSignals.push("resource content");
  if (hasSolutions) workingSignals.push("solutions pages");

  const whatsWorking =
    workingSignals.length > 0
      ? `B2B signals are present on the site, including ${workingSignals.join(", ")}, which support the buyer journey.`
      : "The site has B2B-oriented content and conversion signals that support the buyer journey.";

  return {
    rank: rankBase,
    title: "Pricing or plans page not detected in crawl",
    priority: "high",
    whatsWorking,
    whereItFallsShort:
      "Pricing queries have the highest intent in B2B search (e.g. 'tool X pricing', 'software Y cost'). A discoverable pricing page captures bottom-of-funnel searchers actively evaluating options. Its absence forces high-intent visitors to seek pricing information from competitors or third-party review sites.",
    recommendedNextSteps: [
      "Create a dedicated /pricing page with tier names, key features per tier, and a clear call to action even if prices are listed as 'contact us'",
      "Include tier names and feature comparisons to help buyers self-qualify, reducing friction in the sales process",
      "Add Product or Service schema with an offer structure to help search engines surface pricing information in rich results",
      "Ensure the pricing page is indexable, linked from the main navigation, and included in the sitemap",
    ],
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_B2B,
  };
}

function buildFunnelStageGap(input: AuditInput, rankBase: number): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  if (pages.length < 5) return null;

  // TOFU: informational content
  const tofuPages = pages.filter((p) => {
    const urlOrTitle = (p.url + " " + (p.structuralSignals.h1Text ?? "")).toLowerCase();
    return (
      (p.structuralSignals.wordCount ?? 0) > 500 &&
      /guide|what-is|how-to|tips|blog/.test(urlOrTitle)
    );
  });

  // MOFU: comparison / evaluation content
  const mofuPages = pages.filter((p) =>
    /comparison|\/vs\/|-vs-|alternative|features|use-case/i.test(p.url),
  );

  // BOFU: decision-ready content
  const bofuPages = pages.filter((p) =>
    /pricing|demo|trial|contact/i.test(p.url),
  );

  const missingStages: string[] = [];
  if (tofuPages.length === 0) missingStages.push("TOFU (awareness)");
  if (mofuPages.length === 0) missingStages.push("MOFU (evaluation)");
  if (bofuPages.length === 0) missingStages.push("BOFU (decision)");

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

  const bofuMissing = bofuPages.length === 0;
  const priority = bofuMissing ? "high" : "medium";

  const stepsForMissingStages: string[] = [];
  if (tofuPages.length === 0) {
    stepsForMissingStages.push(
      "Create TOFU content such as how-to guides, educational blog posts, and 'what is X' explainers targeting awareness-stage queries",
    );
  }
  if (mofuPages.length === 0) {
    stepsForMissingStages.push(
      "Create MOFU content such as feature comparison pages, use-case pages, and competitor alternative pages targeting evaluation-stage buyers",
    );
  }
  if (bofuPages.length === 0) {
    stepsForMissingStages.push(
      "Create BOFU content including a pricing page, demo request page, and free trial landing page to capture decision-ready buyers",
    );
  }
  stepsForMissingStages.push(
    "Interlink funnel stages so that awareness content links to evaluation content, and evaluation content links to decision pages",
  );

  return {
    rank: rankBase,
    title: `B2B content funnel gaps: ${missingStages.join(", ")} stage coverage missing`,
    priority,
    whatsWorking:
      "The site has some stage coverage in the B2B buyer journey, giving search engines and buyers a starting point.",
    whereItFallsShort:
      "B2B buyers need content at each funnel stage before making a purchase decision. Missing TOFU content limits organic discovery; missing MOFU content means buyers cannot compare options on the site; missing BOFU content means no page to capture decision-ready buyers who are ready to act.",
    recommendedNextSteps: stepsForMissingStages.slice(0, 4),
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_B2B,
  };
}

function buildCaseStudyIndexability(input: AuditInput, rankBase: number): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const hasCaseStudies = pages.some((p) =>
    /case-stud|\/customer|success-stor|testimonial/i.test(p.url),
  );
  if (hasCaseStudies) return null;

  return {
    rank: rankBase,
    title: "No indexable case studies or customer success content found",
    priority: "medium",
    whatsWorking:
      "The site has B2B positioning and conversion-oriented content that establishes the product or service offering.",
    whereItFallsShort:
      "Case studies are high-intent content that converts B2B buyers at the decision stage. They also rank for '[brand] reviews' and 'does [brand] work for [industry]' queries, capturing buyers who are actively researching before a purchase decision.",
    recommendedNextSteps: [
      "Create a dedicated case study section at /case-studies/ with a consistent URL structure for each story",
      "Use a consistent URL pattern such as /case-studies/[client-name] or /case-studies/[industry]-[outcome] for discoverability",
      "Add Article or Review schema to each case study page to support rich result eligibility",
      "Include named metrics and specific client details where possible, as specificity increases both credibility and search relevance",
    ],
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_B2B,
  };
}

function buildComparisonPageMissing(input: AuditInput, rankBase: number): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const hasComparisonPage = pages.some((p) =>
    /\/vs\/|-vs-|\/versus\/|alternative|\/compare/i.test(p.url),
  );
  if (hasComparisonPage) return null;

  return {
    rank: rankBase,
    title: "No competitor comparison or alternatives content found",
    priority: "medium",
    whatsWorking:
      "The site has product or service content that establishes the offering and its value proposition.",
    whereItFallsShort:
      "'X vs Y' and 'alternative to X' are high-intent commercial queries frequently searched by B2B buyers during evaluation. Brands that do not publish comparison content cede these SERP positions to competitors or third-party review sites, losing visibility exactly when buyers are ready to decide.",
    recommendedNextSteps: [
      "Create /[product]-vs-[competitor] pages for the top 3 to 5 competitors, addressing the key differentiators buyers care about",
      "Create /alternatives-to-[competitor] pages targeting buyers actively searching for a switch",
      "Add OfferCatalog or SoftwareApplication schema where applicable to support structured search features",
      "Ensure comparison content is objective, factual, and addresses the specific reasons buyers choose one product over another",
    ],
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_B2B,
  };
}

function buildGatedContentDiscoverability(input: AuditInput, rankBase: number): PrioritizedFinding | null {
  const pages = input.pageStrategicPassContext?.pages ?? [];
  const gatedAssetPattern = /\/whitepaper|\/ebook|\/guide|\/report/i;

  const gatedPages = pages.filter(
    (p) =>
      gatedAssetPattern.test(p.url) &&
      p.structuralSignals.wordCount !== null &&
      (p.structuralSignals.wordCount as number) < 200,
  );

  if (gatedPages.length < 2) return null;

  return {
    rank: rankBase,
    title: "Gated content may lack indexable preview for search visibility",
    priority: "medium",
    whatsWorking:
      "The site has gated content assets such as whitepapers, ebooks, and guides, demonstrating topical depth and supporting lead generation.",
    whereItFallsShort:
      "Fully-gated content with no preview has no SEO value. Searchers looking for industry guides and whitepapers cannot find the content through organic search, and Google cannot assess its quality. Providing a table of contents or sample section captures organic discovery while preserving lead generation value.",
    recommendedNextSteps: [
      "Add a 300 to 500 word summary and table of contents to each gated landing page so Google can index and rank the page for relevant queries",
      "Include the most compelling insight from the content ungated to demonstrate value and encourage downloads",
      "Optimize the gated page title and meta description for the target query rather than generic 'Download our ebook' phrasing",
      "Consider ungating older content entirely to build topical authority, while keeping newer assets gated for lead capture",
    ],
    affectedUrls: gatedPages.slice(0, MAX_AFFECTED_URLS).map((p) => p.url),
    dataSourceWeave: ["crawl"] as const,
    category: CATEGORY_B2B,
  };
}

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

export async function runB2bSynthesizer(input: AuditInput): Promise<PrioritizedFinding[]> {
  try {
    if (!isB2bSite(input)) return [];

    const candidates: Array<PrioritizedFinding | null> = [
      buildPricingPageSeo(input, 500),
      buildFunnelStageGap(input, 501),
      buildCaseStudyIndexability(input, 502),
      buildComparisonPageMissing(input, 503),
      buildGatedContentDiscoverability(input, 504),
    ];

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

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