import type { ContentSample } from "../../audit/scrapers/firecrawl-content";
import type { PageData } from "../../audit/types";
import type { VoiceSearchGap, VoiceSearchRecommendation } from "../types";

export interface SpeakableSchemaResult {
  score: number;
  pagesChecked: number;
  pagesWithSpeakable: number;
  pagesWithArticleSchema: number;
  gaps: VoiceSearchGap[];
  recommendations: VoiceSearchRecommendation[];
}

const SPEAKABLE_PATTERN = /"@type"\s*:\s*"SpeakableSpecification"/;
const ARTICLE_TYPES = ["Article", "NewsArticle", "BlogPosting", "WebPage"];
const ARTICLE_PATTERN = new RegExp(`"@type"\\s*:\\s*"(${ARTICLE_TYPES.join("|")})"`)

function hasSpeakableSpec(markdown: string): boolean {
  return SPEAKABLE_PATTERN.test(markdown);
}

function hasArticleSchema(markdown: string): boolean {
  return ARTICLE_PATTERN.test(markdown);
}

export function checkSpeakableSchema(
  pages: PageData[],
  samples: ContentSample[],
): SpeakableSchemaResult {
  const sampleMap = new Map(samples.map((s) => [s.url, s]));

  let pagesWithSpeakable = 0;
  let pagesWithArticleSchema = 0;
  const checked = Math.min(pages.length, samples.length);

  for (const page of pages) {
    const sample = sampleMap.get(page.url);
    if (!sample) continue;
    const md = sample.markdown ?? "";
    if (hasSpeakableSpec(md)) pagesWithSpeakable++;
    if (hasArticleSchema(md)) pagesWithArticleSchema++;
  }

  const speakableRatio = checked > 0 ? pagesWithSpeakable / checked : 0;
  const articleRatio = checked > 0 ? pagesWithArticleSchema / checked : 0;

  // Score: speakable coverage (60%) + article schema presence (40%)
  const score = Math.round((speakableRatio * 60 + articleRatio * 40) * 100) / 100;

  const gaps: VoiceSearchGap[] = [];
  const recommendations: VoiceSearchRecommendation[] = [];

  if (speakableRatio < 0.3) {
    gaps.push({
      dimension: "speakable-schema",
      gap: "SpeakableSpecification schema absent or minimal across crawled pages",
      impactDescription: "Voice assistants prioritize pages with explicit speakable markup when selecting spoken responses; pages without it are structurally deprioritized.",
      implementationDifficulty: "moderate",
      estimatedScoreLift: 18,
    });
    recommendations.push({
      title: "Add SpeakableSpecification to high-value content pages",
      impact: "high",
      effort: "day",
      rationale: "Explicit speakable markup signals to voice engines which text segments are suitable for audio reading, directly increasing selection probability.",
    });
  } else if (speakableRatio < 0.7) {
    gaps.push({
      dimension: "speakable-schema",
      gap: "SpeakableSpecification coverage below threshold on majority of pages",
      impactDescription: "Partial speakable coverage leaves most pages unoptimized for voice selection.",
      implementationDifficulty: "moderate",
      estimatedScoreLift: 9,
    });
  }

  if (articleRatio < 0.4) {
    gaps.push({
      dimension: "speakable-schema",
      gap: "Article-type schema missing on content pages",
      impactDescription: "Article, BlogPosting, and WebPage schema are prerequisites for SpeakableSpecification eligibility on most voice platforms.",
      implementationDifficulty: "easy",
      estimatedScoreLift: 8,
    });
    recommendations.push({
      title: "Apply Article or WebPage schema to informational content",
      impact: "medium",
      effort: "hour",
      rationale: "Article-type schema is required context for SpeakableSpecification and improves structured data completeness for voice indexing.",
    });
  }

  return { score, pagesChecked: checked, pagesWithSpeakable, pagesWithArticleSchema, gaps, recommendations };
}
