/**
 * Public façade for the SEO analyzer.
 * Builds a `Paper` from raw article fields and runs every check, returning
 * an aggregate report (0..100, letter grade, per-check breakdown, stats).
 */

import {
  extractLinks,
  extractSubheadings,
  fleschReading,
  readMinutes,
  stripMarkdown,
  wordCount,
} from "./text";
import { allChecks } from "./checks";
import type { AnalysisReport, AnalysisResult, Paper } from "./types";

export interface AnalyzeInput {
  title: string;
  metaTitle?: string | null;
  slug: string;
  metaDesc?: string | null;
  focusKeyword?: string | null;
  metaKeywords?: string | null;
  content: string;
  coverImage?: string | null;
  coverAlt?: string | null;
  host?: string;
  locale?: "en" | "vi";
}

function buildPaper(input: AnalyzeInput): Paper {
  const host = input.host ?? "v2.finzone.io.vn";
  const locale = input.locale ?? "vi";
  const text = stripMarkdown(input.content ?? "");
  const subheadings = extractSubheadings(input.content ?? "");
  const { internal, external, images } = extractLinks(input.content ?? "", host);
  const additional =
    input.metaKeywords
      ?.split(",")
      .map((s) => s.trim())
      .filter(Boolean) ?? [];

  return {
    title: input.title ?? "",
    metaTitle: input.metaTitle?.trim() || input.title || "",
    slug: input.slug ?? "",
    metaDesc: input.metaDesc ?? "",
    keyword: (input.focusKeyword ?? "").trim(),
    keywords: additional,
    text,
    coverImage: input.coverImage ?? null,
    coverAlt: input.coverAlt ?? null,
    subheadings,
    internalLinks: internal,
    externalLinks: external,
    images,
    host,
    locale,
  };
}

export function analyzeArticle(input: AnalyzeInput): AnalysisReport {
  const paper = buildPaper(input);
  const checks: AnalysisResult[] = [];
  let earned = 0;
  let total = 0;

  for (const fn of Object.values(allChecks)) {
    const r = fn(paper);
    if (!r) continue;
    checks.push(r);
    earned += r.score;
    total += r.maxScore;
  }

  const finalScore = total === 0 ? 0 : Math.round((earned / total) * 100);
  const grade: AnalysisReport["grade"] =
    finalScore >= 90 ? "A" : finalScore >= 75 ? "B" : finalScore >= 60 ? "C" : finalScore >= 40 ? "D" : "F";

  // Sort: fails first, then info
  checks.sort((a, b) => {
    if ((a.score === 0) !== (b.score === 0)) return a.score === 0 ? -1 : 1;
    return b.severity - a.severity;
  });

  const wcount = wordCount(paper.text);
  const density = paper.keyword
    ? Math.round(
        ((paper.text.toLowerCase().match(new RegExp(escape(paper.keyword), "gi")) ?? [])
          .length /
          Math.max(1, wcount)) *
          10000,
      ) / 100
    : 0;

  return {
    score: finalScore,
    grade,
    checks,
    stats: {
      wordCount: wcount,
      readMinutes: readMinutes(paper.text),
      fleschScore: fleschReading(paper.text, paper.locale),
      keywordDensity: density,
      internalLinks: paper.internalLinks.length,
      externalLinks: paper.externalLinks.length,
      images: paper.images.length + (paper.coverImage ? 1 : 0),
      subheadings: paper.subheadings.length,
    },
  };
}

function escape(s: string): string {
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

export type { AnalysisReport, AnalysisResult, Paper } from "./types";
