/**
 * schema.org structured-data (JSON-LD) builders.
 *
 * Mirrors what Shopware's default storefront emits in <head>: Product +
 * Offer + AggregateRating on product detail pages, BreadcrumbList for the
 * navigation trail, and Organization / WebSite site-wide. Improves how the
 * store appears in search results (rich snippets, sitelinks search box).
 */
import type { ShopwareProduct } from './shopware-api';
import { getStorefrontUrl, getActiveCurrencyIso } from './shopware-api';

function siteOrigin(): string {
  return (getStorefrontUrl() || '').replace(/\/+$/, '');
}

/** Resolve a path or relative URL to an absolute URL when an origin is known. */
function abs(pathOrUrl: string): string {
  const origin = siteOrigin();
  if (!pathOrUrl) return origin;
  if (/^https?:\/\//.test(pathOrUrl)) return pathOrUrl;
  if (!origin) return pathOrUrl;
  return `${origin}${pathOrUrl.startsWith('/') ? '' : '/'}${pathOrUrl}`;
}

function stripHtml(html: string | null | undefined): string {
  if (!html) return '';
  return html.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
}

export function buildProductJsonLd(opts: {
  product: ShopwareProduct;
  name: string;
  description: string | null;
  price: number;
  images: string[];
  path: string;
  reviewCount?: number;
}): object {
  const { product, name, description, price, images, path, reviewCount } = opts;
  const url = abs(path);
  const inStock = !(product.isCloseout && (product.availableStock ?? 0) <= 0);

  const data: Record<string, unknown> = {
    '@context': 'https://schema.org/',
    '@type': 'Product',
    name,
    productID: product.id,
    sku: product.productNumber,
    url,
  };

  const desc = stripHtml(description);
  if (desc) data.description = desc;
  if (images.length) data.image = images.map(abs);
  if (product.manufacturer?.name) {
    data.brand = { '@type': 'Brand', name: product.manufacturer.name };
  }
  if (price > 0) {
    data.offers = {
      '@type': 'Offer',
      url,
      priceCurrency: getActiveCurrencyIso(),
      price: price.toFixed(2),
      availability: inStock
        ? 'https://schema.org/InStock'
        : 'https://schema.org/OutOfStock',
      itemCondition: 'https://schema.org/NewCondition',
    };
  }
  if (product.ratingAverage && reviewCount && reviewCount > 0) {
    data.aggregateRating = {
      '@type': 'AggregateRating',
      ratingValue: Number(product.ratingAverage).toFixed(1),
      reviewCount,
      bestRating: 5,
      worstRating: 1,
    };
  }
  return data;
}

export function buildBreadcrumbJsonLd(
  items: Array<{ name: string; path: string }>
): object | null {
  if (items.length === 0) return null;
  return {
    '@context': 'https://schema.org/',
    '@type': 'BreadcrumbList',
    itemListElement: items.map((it, i) => ({
      '@type': 'ListItem',
      position: i + 1,
      name: it.name,
      item: abs(it.path),
    })),
  };
}

export function buildOrganizationJsonLd(): object {
  const origin = siteOrigin();
  const data: Record<string, unknown> = {
    '@context': 'https://schema.org/',
    '@type': 'Organization',
    name: process.env.NEXT_PUBLIC_STORE_NAME || 'ReactWare',
  };
  if (origin) data.url = origin;
  const logo =
    process.env.NEXT_PUBLIC_LOGO_DESKTOP || process.env.NEXT_PUBLIC_FAVICON_URL;
  if (logo) data.logo = logo;
  return data;
}

export function buildWebSiteJsonLd(): object {
  const origin = siteOrigin();
  const data: Record<string, unknown> = {
    '@context': 'https://schema.org/',
    '@type': 'WebSite',
    name: process.env.NEXT_PUBLIC_STORE_NAME || 'ReactWare',
  };
  if (origin) {
    data.url = origin;
    data.potentialAction = {
      '@type': 'SearchAction',
      target: `${origin}/search?q={search_term_string}`,
      'query-input': 'required name=search_term_string',
    };
  }
  return data;
}
