/**
 * Page SEO Score Calculator
 * ─────────────────────────
 * Evaluates a Page Studio page against on-page SEO best practices
 * and returns a 0-100 score with specific recommendations.
 */

import type { Section } from "@/lib/page-studio/section-registry";

export interface SeoScoreResult {
  score: number;
  maxScore: number;
  checks: SeoCheck[];
  grade: "A" | "B" | "C" | "D" | "F";
}

export interface SeoCheck {
  name: string;
  passed: boolean;
  points: number;
  maxPoints: number;
  recommendation: string | null;
}

function allText(sections: Section[]): string {
  return sections.map((s) => {
    return Object.values(s.content)
      .filter((v) => typeof v === "string")
      .join(" ");
  }).join(" ");
}

function wordCount(text: string): number {
  return text.split(/\s+/).filter(Boolean).length;
}

export function calculatePageSEOScore(
  sections: Section[],
  targetKeyword: string,
  metaTitle: string,
  metaDescription: string,
): SeoScoreResult {
  const checks: SeoCheck[] = [];
  const kw = targetKeyword.toLowerCase();
  const text = allText(sections);
  const textLower = text.toLowerCase();
  const words = wordCount(text);

  // 1. H1 with keyword (+15)
  const heroSection = sections.find((s) => s.type.startsWith("hero"));
  const headline = String(heroSection?.content?.headline || "").toLowerCase();
  const h1HasKeyword = !!(kw && headline.includes(kw));
  checks.push({
    name: "H1 contains target keyword",
    passed: h1HasKeyword,
    points: h1HasKeyword ? 15 : 0,
    maxPoints: 15,
    recommendation: h1HasKeyword ? null : `Add "${targetKeyword}" to your hero headline`,
  });

  // 2. Meta title with keyword (+10)
  const titleHasKw = !!(kw && metaTitle.toLowerCase().includes(kw));
  checks.push({
    name: "Meta title contains keyword",
    passed: titleHasKw,
    points: titleHasKw ? 10 : 0,
    maxPoints: 10,
    recommendation: titleHasKw ? null : `Include "${targetKeyword}" in your meta title`,
  });

  // 3. Has meta description (+10)
  const hasMetaDesc = metaDescription.length >= 50;
  checks.push({
    name: "Meta description (50+ characters)",
    passed: hasMetaDesc,
    points: hasMetaDesc ? 10 : 0,
    maxPoints: 10,
    recommendation: hasMetaDesc ? null : "Add a meta description of at least 50 characters",
  });

  // 4. All images have alt text (+10)
  const imageFields = sections.flatMap((s) =>
    Object.entries(s.content)
      .filter(([k]) => /image|logo|photo|avatar|poster/i.test(k))
      .map(([k, v]) => ({ key: k, value: v, section: s }))
  );
  const altFields = sections.flatMap((s) =>
    Object.entries(s.content)
      .filter(([k]) => /alt/i.test(k))
  );
  const imagesHaveAlt = imageFields.length === 0 || altFields.length > 0;
  checks.push({
    name: "Images have alt text",
    passed: imagesHaveAlt,
    points: imagesHaveAlt ? 10 : 0,
    maxPoints: 10,
    recommendation: imagesHaveAlt ? null : "Add alt text to all images for accessibility and SEO",
  });

  // 5. Has schema-ready data (+10) — NAP info present
  const hasPhone = textLower.includes("call") || sections.some((s) =>
    s.type === "phone_cta" || s.type === "contact_form"
  );
  const hasNAP = hasPhone || sections.some((s) => s.content.phoneNumber || s.content.address);
  checks.push({
    name: "NAP / contact information present",
    passed: hasNAP,
    points: hasNAP ? 10 : 0,
    maxPoints: 10,
    recommendation: hasNAP ? null : "Add phone number or address for local SEO and schema markup",
  });

  // 6. Keyword in first 100 words (+10)
  const first100 = textLower.split(/\s+/).slice(0, 100).join(" ");
  const kwInFirst100 = !!(kw && first100.includes(kw));
  checks.push({
    name: "Keyword in first 100 words",
    passed: kwInFirst100,
    points: kwInFirst100 ? 10 : 0,
    maxPoints: 10,
    recommendation: kwInFirst100 ? null : `Mention "${targetKeyword}" in the first section's copy`,
  });

  // 7. Has internal links / CTA links (+10)
  const hasLinks = sections.some((s) =>
    s.type === "cta_banner" || s.type === "contact_form" || s.type === "phone_cta" ||
    Object.values(s.content).some((v) => typeof v === "string" && /^https?:\/\//i.test(v))
  );
  checks.push({
    name: "Has CTA / internal links",
    passed: hasLinks,
    points: hasLinks ? 10 : 0,
    maxPoints: 10,
    recommendation: hasLinks ? null : "Add CTA buttons or links to your website",
  });

  // 8. Word count > 500 (+10)
  const goodLength = words >= 500;
  checks.push({
    name: "Content length (500+ words)",
    passed: goodLength,
    points: goodLength ? 10 : 0,
    maxPoints: 10,
    recommendation: goodLength ? null : `Page has ${words} words — aim for 500+ for better rankings`,
  });

  // 9. Has FAQ section (+10)
  const hasFaq = sections.some((s) => s.type === "faq");
  checks.push({
    name: "FAQ section included",
    passed: hasFaq,
    points: hasFaq ? 10 : 0,
    maxPoints: 10,
    recommendation: hasFaq ? null : "Add an FAQ section — helps with featured snippets and long-tail keywords",
  });

  // 10. Has trust signals (+5)
  const hasTrust = sections.some((s) =>
    ["trust_bar", "testimonials", "reviews", "stats_row", "logo_bar"].includes(s.type)
  );
  checks.push({
    name: "Trust signals present",
    passed: hasTrust,
    points: hasTrust ? 5 : 0,
    maxPoints: 5,
    recommendation: hasTrust ? null : "Add testimonials, reviews, or trust badges",
  });

  const score = checks.reduce((sum, c) => sum + c.points, 0);
  const maxScore = checks.reduce((sum, c) => sum + c.maxPoints, 0);
  const pct = maxScore > 0 ? (score / maxScore) * 100 : 0;

  let grade: SeoScoreResult["grade"] = "F";
  if (pct >= 90) grade = "A";
  else if (pct >= 75) grade = "B";
  else if (pct >= 60) grade = "C";
  else if (pct >= 40) grade = "D";

  return { score, maxScore, checks, grade };
}
