export interface BreadcrumbItem {
  name: string
  url: string
}

export interface OrganizationInput {
  name: string
  url: string
  logo?: string
}

export interface WebSiteInput {
  name: string
  url: string
  searchUrlTemplate?: string
}

// Hoisted (R3): RegExp compiled once at module load, not rebuilt per call on the hot path.
const LS_RE = /\u2028/g
const PS_RE = /\u2029/g

/**
 * XSS-safe JSON-LD serializer — security-union escape (trance escape-all + U+2028/U+2029).
 * Escaping every `<` subsumes `</script`, `<!--`, and case/spacing variants.
 */
export function serializeJsonLd(obj: unknown): string {
  return JSON.stringify(obj)
    .replace(/</g, '\\u003c')
    .replace(/>/g, '\\u003e')
    .replace(/&/g, '\\u0026')
    .replace(LS_RE, '\\u2028')
    .replace(PS_RE, '\\u2029')
}

export function buildBreadcrumbList(items: BreadcrumbItem[]): Record<string, unknown> {
  return {
    '@context': 'https://schema.org',
    '@type': 'BreadcrumbList',
    itemListElement: items.map((item, index) => ({
      '@type': 'ListItem',
      position: index + 1,
      name: item.name,
      item: item.url,
    })),
  }
}

export function buildOrganization(input: OrganizationInput): Record<string, unknown> {
  const org: Record<string, unknown> = {
    '@context': 'https://schema.org',
    '@type': 'Organization',
    name: input.name,
    url: input.url,
  }
  if (input.logo) org.logo = input.logo
  return org
}

export function buildWebSite(input: WebSiteInput): Record<string, unknown> {
  const site: Record<string, unknown> = {
    '@context': 'https://schema.org',
    '@type': 'WebSite',
    name: input.name,
    url: input.url,
  }
  if (input.searchUrlTemplate) {
    site.potentialAction = {
      '@type': 'SearchAction',
      target: input.searchUrlTemplate,
      'query-input': 'required name=search_term_string',
    }
  }
  return site
}

/** Framework-agnostic inline JSON-LD script tag (serialized payload cannot break out). */
export function renderJsonLdScript(obj: unknown): string {
  return `<script type="application/ld+json">${serializeJsonLd(obj)}</script>`
}
