/**
 * Schema.org JSON-LD generator — TypeScript port of Rank Math's schema module.
 * Source: includes/modules/schema/snippets/*.php
 *
 * Builds an @graph that combines Article + Organization + WebSite + WebPage
 * + BreadcrumbList. Tuned for a finance news site (Article subtype = NewsArticle
 * for posts in "Tin Nóng" / freshly-published items, otherwise plain Article).
 */

export interface SchemaInput {
  /** Site URL (no trailing slash). */
  siteUrl: string;
  /** Site title. */
  siteName: string;
  /** Site description. */
  siteDescription: string;
  /** Logo URL (Organization.logo). */
  logoUrl: string;
  /** Default cover/social image when an article has none. */
  defaultImage?: string;
  /** Twitter handle including the leading "@" (optional). */
  twitterHandle?: string;
  /** Facebook URL (optional). */
  facebookUrl?: string;
}

export interface ArticleSchemaInput {
  url: string;
  title: string;
  description: string;
  coverImage?: string | null;
  publishedAt: Date | string;
  updatedAt: Date | string;
  authorName: string;
  authorUrl?: string;
  categoryName?: string;
  categoryUrl?: string;
  tagNames?: string[];
  /** Use NewsArticle instead of Article. */
  isNews?: boolean;
  /** Used to set wordCount in schema. */
  wordCount?: number;
  /** ISO language code (defaults to vi-VN). */
  inLanguage?: string;
}

export interface BreadcrumbItem {
  name: string;
  url: string;
}

function iso(d: Date | string): string {
  return typeof d === "string" ? d : d.toISOString();
}

export function buildOrganization(site: SchemaInput) {
  const sameAs: string[] = [];
  if (site.facebookUrl) sameAs.push(site.facebookUrl);
  if (site.twitterHandle)
    sameAs.push(`https://twitter.com/${site.twitterHandle.replace(/^@/, "")}`);
  return {
    "@type": "Organization",
    "@id": `${site.siteUrl}/#organization`,
    name: site.siteName,
    url: site.siteUrl,
    logo: {
      "@type": "ImageObject",
      "@id": `${site.siteUrl}/#logo`,
      url: site.logoUrl,
      contentUrl: site.logoUrl,
      caption: site.siteName,
      inLanguage: "vi-VN",
    },
    image: { "@id": `${site.siteUrl}/#logo` },
    sameAs,
  };
}

export function buildWebSite(site: SchemaInput) {
  return {
    "@type": "WebSite",
    "@id": `${site.siteUrl}/#website`,
    url: site.siteUrl,
    name: site.siteName,
    description: site.siteDescription,
    publisher: { "@id": `${site.siteUrl}/#organization` },
    potentialAction: [
      {
        "@type": "SearchAction",
        target: {
          "@type": "EntryPoint",
          urlTemplate: `${site.siteUrl}/tim-kiem?q={search_term_string}`,
        },
        "query-input": "required name=search_term_string",
      },
    ],
    inLanguage: "vi-VN",
  };
}

export function buildBreadcrumbs(site: SchemaInput, items: BreadcrumbItem[]) {
  const list = [
    { name: "Trang chủ", url: site.siteUrl },
    ...items,
  ];
  return {
    "@type": "BreadcrumbList",
    "@id": `${items[items.length - 1]?.url ?? site.siteUrl}/#breadcrumb`,
    itemListElement: list.map((it, i) => ({
      "@type": "ListItem",
      position: i + 1,
      name: it.name,
      item: it.url,
    })),
  };
}

export function buildArticleGraph(
  site: SchemaInput,
  article: ArticleSchemaInput,
  breadcrumbs: BreadcrumbItem[],
) {
  const orgId = `${site.siteUrl}/#organization`;
  const articleType = article.isNews ? "NewsArticle" : "Article";
  const inLanguage = article.inLanguage ?? "vi-VN";
  const image = article.coverImage ?? site.defaultImage ?? site.logoUrl;

  const webPage = {
    "@type": "WebPage",
    "@id": `${article.url}/#webpage`,
    url: article.url,
    name: article.title,
    description: article.description,
    isPartOf: { "@id": `${site.siteUrl}/#website` },
    primaryImageOfPage: image
      ? {
          "@type": "ImageObject",
          url: image,
          contentUrl: image,
          inLanguage,
        }
      : undefined,
    datePublished: iso(article.publishedAt),
    dateModified: iso(article.updatedAt),
    breadcrumb: { "@id": `${article.url}/#breadcrumb` },
    inLanguage,
    potentialAction: [
      {
        "@type": "ReadAction",
        target: [article.url],
      },
    ],
  };

  const articleNode: Record<string, unknown> = {
    "@type": articleType,
    "@id": `${article.url}/#article`,
    isPartOf: { "@id": `${article.url}/#webpage` },
    mainEntityOfPage: { "@id": `${article.url}/#webpage` },
    headline: article.title,
    description: article.description,
    datePublished: iso(article.publishedAt),
    dateModified: iso(article.updatedAt),
    publisher: { "@id": orgId },
    author: {
      "@type": "Person",
      name: article.authorName,
      url: article.authorUrl,
    },
    inLanguage,
    image: image
      ? {
          "@type": "ImageObject",
          url: image,
          contentUrl: image,
        }
      : undefined,
    articleSection: article.categoryName,
    keywords: article.tagNames && article.tagNames.length ? article.tagNames.join(", ") : undefined,
  };
  if (article.wordCount) articleNode.wordCount = article.wordCount;

  return {
    "@context": "https://schema.org",
    "@graph": [
      buildOrganization(site),
      buildWebSite(site),
      webPage,
      buildBreadcrumbs(site, breadcrumbs),
      articleNode,
    ],
  };
}

export function buildFaqPageGraph(faqs: Array<{ q: string; a: string }>) {
  return {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    mainEntity: faqs.map((it) => ({
      "@type": "Question",
      name: it.q,
      acceptedAnswer: { "@type": "Answer", text: it.a },
    })),
  };
}

export function buildHowToGraph(input: {
  title: string;
  description: string;
  steps: Array<{ name: string; text: string; image?: string }>;
  totalTimeMinutes?: number;
}) {
  return {
    "@context": "https://schema.org",
    "@type": "HowTo",
    name: input.title,
    description: input.description,
    totalTime: input.totalTimeMinutes ? `PT${input.totalTimeMinutes}M` : undefined,
    step: input.steps.map((s, i) => ({
      "@type": "HowToStep",
      position: i + 1,
      name: s.name,
      text: s.text,
      image: s.image,
    })),
  };
}
