/**
 * Brief Schema Generator
 * ──────────────────────
 * Generates JSON-LD schemas for the SEO Content Brief and the LLMO
 * Content Brief. Kept separate from the brief-generation LLM prompts
 * because schema shape is deterministic given topic + content type +
 * brand context — no LLM call needed.
 *
 * SEO schemas target Google's rich-results catalogue (Article,
 * MedicalCondition, MedicalProcedure, FAQ, HowTo, LocalBusiness,
 * Breadcrumb). LLMO schemas target AI engines' citation behaviour
 * (Speakable, MedicalWebPage with author/lastReviewed, FAQ, and a
 * MedicalClinic entity for local-intent answers).
 *
 * IMPORTANT: these two are NOT merged. The brief pages import the
 * function that matches their brief type — callers never mix the
 * two sets. Every schema in either set stands on its own and can
 * be pasted directly into a <script type="application/ld+json"> tag.
 *
 * All schemas return JSON objects (not strings). The UI layer
 * formats them via JSON.stringify for display + copy-to-clipboard.
 */

export type ContentType =
  | "blog" | "article" | "guide"       // editorial / long-form
  | "service" | "treatment" | "procedure"
  | "condition" | "disease" | "symptom"
  | "howto" | "tutorial"
  | "faq"
  | "location";

export interface BriefBrand {
  name: string;
  domain: string;
  phone?: string | null;
}

export interface BriefLocation {
  address?: string | null;
  city?: string | null;
  state?: string | null;
  locationName?: string | null;
}

export interface BriefPhysician {
  name: string;
  specialty?: string | null;
  credentials?: string | null;
}

export interface BriefData {
  topic: string;
  keyword: string;
  contentType: ContentType;
  brand: BriefBrand;
  locations: BriefLocation[];
  physicians: BriefPhysician[];
  faqQuestions: string[];
}

export interface SchemaItem {
  /** Short display name ("FAQ Schema"). */
  name: string;
  /** What this schema does + when to use it. Rendered below the name. */
  description: string;
  /** Why the schema helps. Rendered as the blue "💡" hint line. */
  whyItHelps: string;
  /** The actual JSON-LD object. UI stringifies for display + copy. */
  json: Record<string, unknown>;
}

// ─── Shared helpers ─────────────────────────────────────────────────────────

function slugify(s: string): string {
  return s
    .toLowerCase()
    .trim()
    .replace(/[^a-z0-9\s-]/g, "")
    .replace(/\s+/g, "-")
    .replace(/-+/g, "-")
    .replace(/^-|-$/g, "");
}

function todayIso(): string {
  return new Date().toISOString().split("T")[0];
}

/** Build a canonical URL from domain + keyword slug. */
function canonicalUrl(brand: BriefBrand, keyword: string): string {
  const host = brand.domain.replace(/^https?:\/\//, "").replace(/^www\./, "").replace(/\/+$/, "");
  return `https://${host}/${slugify(keyword)}/`;
}

/** Address block for Medical* schemas. Uses the first location with any
 *  city/state data; returns null when every location is blank. */
function buildAddress(locations: BriefLocation[]) {
  const loc = locations.find((l) => l.city || l.state || l.address);
  if (!loc) return null;
  return {
    "@type": "PostalAddress" as const,
    streetAddress: loc.address ?? "[Street address]",
    addressLocality: loc.city ?? "[City]",
    addressRegion: loc.state ?? "[State]",
  };
}

// ─── Content-type detection ─────────────────────────────────────────────────

/**
 * Infer which content type a keyword implies so the brief page can
 * pre-select the right schema set without asking the user. Caller can
 * always override via the content-type picker in the UI.
 */
export function detectContentType(keyword: string): ContentType {
  const kw = keyword.toLowerCase();

  // Condition / disease / symptom patterns — check first; they're the
  // most distinctive medical signal and win over other buckets.
  if (/\b(insufficiency|disease|syndrome|disorder|condition|symptoms?\s+of)\b/.test(kw)) return "condition";

  // Treatment / procedure patterns.
  if (/\b(treatment|procedure|surgery|therapy|ablation|stent|transplant|biopsy)\b/.test(kw)) return "service";

  // How-to / guide patterns.
  if (/\b(how\s+to|guide|steps|ways\s+to|tips\s+for|instructions\s+for)\b/.test(kw)) return "howto";

  // Explicit FAQ phrasing.
  if (/\b(what\s+is|what\s+are|can\s+you|should\s+i|is\s+it|why\s+does|when\s+should)\b/.test(kw)) return "faq";

  // Location-intent patterns.
  if (/\b(near\s+me|in\s+[a-z]+,?\s*(tx|texas|ca|ny|fl|il)|clinic|office|location)\b/.test(kw)) return "location";

  // Default — editorial / long-form content.
  return "blog";
}

// ─── SEO schemas ────────────────────────────────────────────────────────────

/**
 * Generate Google-facing rich-results schemas for the SEO brief. The
 * set returned varies by contentType — a blog post doesn't need the
 * MedicalProcedure schema, a condition page doesn't need HowTo, etc.
 * Breadcrumb + (optional) LocalBusiness are always included because
 * they help on every page type.
 */
export function generateSEOSchemas(briefData: BriefData): SchemaItem[] {
  const schemas: SchemaItem[] = [];
  const url = canonicalUrl(briefData.brand, briefData.keyword);

  // ── Article — editorial content ──────────────────────────────
  if (["blog", "article", "guide"].includes(briefData.contentType)) {
    schemas.push({
      name: "Article Schema",
      description: "Helps Google show rich results with author, publication date, and headline. The table stakes for any editorial content.",
      whyItHelps: "Pages with Article schema are ~30% more likely to appear as featured snippets and are eligible for Top Stories carousels.",
      json: {
        "@context": "https://schema.org",
        "@type": "Article",
        headline: `${briefData.topic} — ${briefData.brand.name}`,
        author: briefData.physicians[0]
          ? {
              "@type": "Physician",
              name: briefData.physicians[0].name,
              ...(briefData.physicians[0].credentials && { honorificSuffix: briefData.physicians[0].credentials }),
            }
          : { "@type": "Organization", name: briefData.brand.name },
        publisher: {
          "@type": "Organization",
          name: briefData.brand.name,
          logo: { "@type": "ImageObject", url: `https://${briefData.brand.domain}/logo.png` },
        },
        datePublished: todayIso(),
        dateModified: todayIso(),
        mainEntityOfPage: url,
        image: `https://${briefData.brand.domain}/images/${slugify(briefData.keyword)}.jpg`,
      },
    });
  }

  // ── MedicalProcedure — service / treatment pages ─────────────
  if (["service", "treatment", "procedure"].includes(briefData.contentType)) {
    schemas.push({
      name: "Medical Procedure Schema",
      description: "Tells Google this page describes a medical treatment or procedure. Matches service-intent queries like 'vein ablation cost' or 'stent procedure'.",
      whyItHelps: "Service pages with MedicalProcedure schema rank measurably higher for treatment-related queries and qualify for the Health Knowledge Panel.",
      json: {
        "@context": "https://schema.org",
        "@type": "MedicalProcedure",
        name: briefData.topic,
        procedureType: { "@type": "MedicalProcedureType", name: "[Diagnostic | Therapeutic | Surgical]" },
        howPerformed: "[Describe how the procedure is performed — 1-2 sentences]",
        preparation: "[Patient preparation steps — fasting, medications to avoid, etc.]",
        followup: "[Post-procedure care — recovery timeline, restrictions, warning signs]",
        status: "https://schema.org/ActiveActionStatus",
      },
    });
  }

  // ── MedicalCondition — disease / symptom pages ───────────────
  if (["condition", "disease", "symptom"].includes(briefData.contentType)) {
    schemas.push({
      name: "Medical Condition Schema",
      description: "Structures condition information for Google's medical knowledge graph — symptoms, treatments, risk factors, and anatomy.",
      whyItHelps: "Condition pages with this schema are more likely to appear in Google's Health Panel + featured snippets for symptom queries.",
      json: {
        "@context": "https://schema.org",
        "@type": "MedicalCondition",
        name: briefData.topic,
        alternateName: "[Alternate / common name]",
        associatedAnatomy: { "@type": "AnatomicalStructure", name: "[Affected body part — heart, veins, etc.]" },
        signOrSymptom: [
          { "@type": "MedicalSignOrSymptom", name: "[Symptom 1]" },
          { "@type": "MedicalSignOrSymptom", name: "[Symptom 2]" },
          { "@type": "MedicalSignOrSymptom", name: "[Symptom 3]" },
        ],
        possibleTreatment: [
          { "@type": "MedicalTherapy", name: "[Treatment 1]" },
          { "@type": "MedicalTherapy", name: "[Treatment 2]" },
        ],
        riskFactor: [
          { "@type": "MedicalRiskFactor", name: "[Risk factor 1]" },
          { "@type": "MedicalRiskFactor", name: "[Risk factor 2]" },
        ],
      },
    });
  }

  // ── HowTo — step-by-step guides ──────────────────────────────
  if (["howto", "tutorial", "guide"].includes(briefData.contentType)) {
    schemas.push({
      name: "HowTo Schema",
      description: "Shows step-by-step rich results in Google. Ideal for treatment preparation, recovery guides, and health instructions.",
      whyItHelps: "HowTo schema can show expandable steps directly in search results — adds vertical SERP real estate at near-zero effort.",
      json: {
        "@context": "https://schema.org",
        "@type": "HowTo",
        name: `How to ${briefData.topic}`,
        step: [
          { "@type": "HowToStep", name: "Step 1", text: "[Step 1 description]" },
          { "@type": "HowToStep", name: "Step 2", text: "[Step 2 description]" },
          { "@type": "HowToStep", name: "Step 3", text: "[Step 3 description]" },
        ],
      },
    });
  }

  // ── FAQ — any content with Q&A sections ──────────────────────
  if (briefData.faqQuestions.length > 0) {
    schemas.push({
      name: "FAQ Schema",
      description: "Shows FAQ rich results in Google — expandable Q&A directly in search results, adding huge SERP real estate.",
      whyItHelps: "FAQ schema can increase your visible SERP footprint 2-3× with expandable answers users don't even have to click to see.",
      json: {
        "@context": "https://schema.org",
        "@type": "FAQPage",
        mainEntity: briefData.faqQuestions.map((q) => ({
          "@type": "Question",
          name: q,
          acceptedAnswer: { "@type": "Answer", text: `[Definitive answer to: ${q}]` },
        })),
      },
    });
  }

  // ── LocalBusiness / MedicalClinic — when locations exist ─────
  const address = buildAddress(briefData.locations);
  if (address) {
    schemas.push({
      name: "Local Business Schema",
      description: "Connects this content to your physical practice locations. Critical for 'near me' and city-specific queries.",
      whyItHelps: "Local business schema is the strongest signal for Google's local pack and map results — no substitute for local intent.",
      json: {
        "@context": "https://schema.org",
        "@type": "MedicalClinic",
        name: briefData.brand.name,
        medicalSpecialty: briefData.physicians[0]?.specialty ?? "Cardiology",
        address,
        telephone: briefData.brand.phone ?? "[Phone]",
        url: `https://${briefData.brand.domain}/`,
      },
    });
  }

  // ── Breadcrumb — always useful ───────────────────────────────
  schemas.push({
    name: "Breadcrumb Schema",
    description: "Shows breadcrumb navigation in Google search results instead of the raw URL. Improves click-through rate and looks more professional.",
    whyItHelps: "Breadcrumbs replace the raw URL in search listings — A/B tests consistently show a small but real CTR uplift.",
    json: {
      "@context": "https://schema.org",
      "@type": "BreadcrumbList",
      itemListElement: [
        { "@type": "ListItem", position: 1, name: "Home", item: `https://${briefData.brand.domain}/` },
        { "@type": "ListItem", position: 2, name: "[Category]", item: `https://${briefData.brand.domain}/[category]/` },
        { "@type": "ListItem", position: 3, name: briefData.topic, item: url },
      ],
    },
  });

  return schemas;
}

// ─── LLMO schemas ───────────────────────────────────────────────────────────

/**
 * Generate AI-engine-facing schemas for the LLMO brief. These target
 * ChatGPT / Perplexity / Gemini / Claude rather than Google:
 *
 *   Speakable        — tells AI which selectors are "quotable" (ChatGPT,
 *                      Perplexity, Google Assistant read this).
 *   FAQPage          — every AI engine extracts Q&A pairs directly.
 *   MedicalWebPage   — authoritative medical content with explicit
 *                      author credentials + review dates (Claude +
 *                      ChatGPT weight this heavily for medical).
 *   MedicalClinic    — local-entity signal for "near me" AI answers.
 *
 * Intentionally leaner than the SEO set — AI engines don't care about
 * Breadcrumb / Article schemas, and including them dilutes signal.
 */
export function generateLLMOSchemas(briefData: BriefData): SchemaItem[] {
  const schemas: SchemaItem[] = [];
  const url = canonicalUrl(briefData.brand, briefData.keyword);

  // ── Speakable — always first, always included ────────────────
  schemas.push({
    name: "Speakable Schema",
    description: "Tells AI engines which parts of the page are quote-worthy. Use CSS selectors for your key answer paragraphs, TL;DR summary, FAQ answers, and expert quotes.",
    whyItHelps: "ChatGPT, Perplexity, and Google Assistant use speakable markup as a hint for which sentences are most citation-worthy.",
    json: {
      "@context": "https://schema.org",
      "@type": "WebPage",
      name: `${briefData.topic} — ${briefData.brand.name}`,
      speakable: {
        "@type": "SpeakableSpecification",
        cssSelector: [".key-answer", ".tldr-summary", "h1", ".faq-answer", ".expert-quote"],
      },
      url,
    },
  });

  // ── FAQ — AI engines LOVE extracting Q&A pairs ───────────────
  if (briefData.faqQuestions.length > 0) {
    schemas.push({
      name: "FAQ Schema",
      description: "AI engines extract these Q&A pairs as direct answers. Each question should be phrased exactly how users ask AI chatbots, not how they type into Google.",
      whyItHelps: "Perplexity and Gemini routinely pull FAQ answers into their responses verbatim — the single highest-leverage schema for AI citation.",
      json: {
        "@context": "https://schema.org",
        "@type": "FAQPage",
        mainEntity: briefData.faqQuestions.map((q) => ({
          "@type": "Question",
          name: q,
          acceptedAnswer: { "@type": "Answer", text: `[Your definitive answer to: ${q}]` },
        })),
      },
    });
  }

  // ── Medical authority — for medical/health topics ────────────
  // Heuristic detection on the topic string. The SEO version is
  // content-type-scoped; LLMO cares about medical authority regardless
  // of the specific page type (a medical blog post still benefits
  // from MedicalWebPage markup).
  const isMedical = /\b(cardiol|heart|vascular|vein|medical|health|treatment|symptom|condition|disease|therapy|procedure|blood|pressure|cholesterol|insuficiencia|circulaci[oó]n)\b/i.test(
    briefData.topic + " " + briefData.keyword,
  );
  if (isMedical) {
    const primaryPhysician = briefData.physicians[0];
    schemas.push({
      name: "Medical Authority Schema",
      description: "Establishes your practice as a medical authority with verified author credentials and an explicit review date.",
      whyItHelps: "Claude and ChatGPT weight medical content higher when it carries author credentials + lastReviewed dates — without these, AI engines default to Mayo Clinic / Cleveland Clinic as the authoritative source instead of you.",
      json: {
        "@context": "https://schema.org",
        "@type": "MedicalWebPage",
        name: briefData.topic,
        url,
        about: { "@type": "MedicalCondition", name: briefData.topic },
        author: primaryPhysician
          ? {
              "@type": "Physician",
              name: primaryPhysician.name,
              medicalSpecialty: { "@type": "MedicalSpecialty", name: primaryPhysician.specialty ?? "Cardiology" },
              affiliation: { "@type": "MedicalOrganization", name: briefData.brand.name },
            }
          : { "@type": "Organization", name: briefData.brand.name },
        lastReviewed: todayIso(),
        reviewedBy: primaryPhysician
          ? {
              "@type": "Physician",
              name: primaryPhysician.name,
              medicalSpecialty: { "@type": "MedicalSpecialty", name: primaryPhysician.specialty ?? "Cardiology" },
            }
          : { "@type": "Organization", name: briefData.brand.name },
        datePublished: todayIso(),
        dateModified: todayIso(),
      },
    });
  }

  // ── Local practice — for local-intent AI answers ─────────────
  const address = buildAddress(briefData.locations);
  if (address) {
    schemas.push({
      name: "Local Practice Schema",
      description: "Helps AI engines connect your content to your physical locations when users ask 'cardiologist near me in Houston' or similar local-intent questions.",
      whyItHelps: "AI engines serving local-intent queries need an explicit entity anchor to cite your specific practice rather than a generic provider list.",
      json: {
        "@context": "https://schema.org",
        "@type": "MedicalClinic",
        name: briefData.brand.name,
        medicalSpecialty: briefData.physicians[0]?.specialty ?? "Cardiology",
        address: briefData.locations.map((l) => ({
          "@type": "PostalAddress",
          streetAddress: l.address ?? "[Street address]",
          addressLocality: l.city ?? "[City]",
          addressRegion: l.state ?? "[State]",
        })),
        telephone: briefData.brand.phone ?? "[Phone]",
        url: `https://${briefData.brand.domain}/`,
      },
    });
  }

  return schemas;
}
