// seo.jsx — <head> manager for the client router.
//
// One export: updateSeo(spec). Each page-component calls it from a useEffect
// keyed on the props that affect the page's meta. Mutates the existing tags in
// place (never duplicates), so the baseline values in index.html act as the
// fallback whenever a field is omitted.

(function () {
  const SITE = 'Top Natural Tips';

  function ensureMeta(attr, key) {
    let el = document.head.querySelector('meta[' + attr + '="' + key + '"]');
    if (!el) {
      el = document.createElement('meta');
      el.setAttribute(attr, key);
      document.head.appendChild(el);
    }
    return el;
  }

  function setMeta(attr, key, content) {
    if (content == null) return;            // omitted → leave the baseline as-is
    ensureMeta(attr, key).setAttribute('content', content);
  }

  function ensureLink(rel) {
    let el = document.head.querySelector('link[rel="' + rel + '"]');
    if (!el) {
      el = document.createElement('link');
      el.setAttribute('rel', rel);
      document.head.appendChild(el);
    }
    return el;
  }

  // updateSeo({ title, description, canonical, ogImage, ogType, jsonLd, lang,
  //             noindex, exact })
  // - title gets " — Top Natural Tips" appended unless exact:true
  // - null/undefined fields are skipped (tag keeps its index.html baseline)
  // - idempotent: same payload twice mutates to the same values
  function updateSeo(opts) {
    opts = opts || {};

    if (opts.title != null) {
      const full = opts.exact ? opts.title : (opts.title + ' — ' + SITE);
      if (document.title !== full) document.title = full;
      setMeta('property', 'og:title', full);
      setMeta('name', 'twitter:title', full);
    }

    if (opts.description != null) {
      setMeta('name', 'description', opts.description);
      setMeta('property', 'og:description', opts.description);
      setMeta('name', 'twitter:description', opts.description);
    }

    if (opts.canonical != null) {
      ensureLink('canonical').setAttribute('href', opts.canonical);
      setMeta('property', 'og:url', opts.canonical);
    }

    if (opts.ogImage != null) {
      setMeta('property', 'og:image', opts.ogImage);
      setMeta('name', 'twitter:image', opts.ogImage);
    }

    if (opts.ogType != null) setMeta('property', 'og:type', opts.ogType);

    if (opts.lang != null) document.documentElement.setAttribute('lang', opts.lang);

    // robots — reflected on every call so a 404's noindex is cleared the next
    // time we land on an indexable view. Only an explicit truthy noindex blocks.
    const robots = document.head.querySelector('meta[name="robots"]');
    if (opts.noindex) {
      ensureMeta('name', 'robots').setAttribute('content', 'noindex, follow');
    } else if (robots) {
      robots.remove();
    }

    // JSON-LD — a single managed <script id="seo-jsonld">.
    if (opts.jsonLd != null) {
      let s = document.getElementById('seo-jsonld');
      if (!s) {
        s = document.createElement('script');
        s.type = 'application/ld+json';
        s.id = 'seo-jsonld';
        document.head.appendChild(s);
      }
      const serialized = JSON.stringify(opts.jsonLd);
      if (s.textContent !== serialized) s.textContent = serialized;
    }
  }

  // Shared helpers for building canonical URLs + JSON-LD nodes.
  const ORIGIN = 'https://topnaturaltips.com';
  function url(path) {
    if (!path) return ORIGIN + '/';
    if (/^https?:\/\//i.test(path)) return path;
    return ORIGIN + (path[0] === '/' ? path : '/' + path);
  }

  window.updateSeo = updateSeo;
  window.SEO = {
    ORIGIN,
    url,
    org: () => ({
      '@type': 'Organization',
      name: SITE,
      url: ORIGIN + '/',
      logo: ORIGIN + '/logo.png',
    }),
    person: () => ({ '@type': 'Person', name: 'Paola Duran Kawamoto' }),
  };
})();
