/* global React, ReactDOM, Nav, Footer, Breadcrumbs, IP_AUTHORS, IP_POSTS, IP_PLACEHOLDER_FAQ, IP_PLACEHOLDER_FAQ_FR */
const { useState: ipUseState, useEffect: ipUseEffect, useRef: ipUseRef } = React;

// ---- UI string table (EN + FR) ----
// Switched at the call site via the `lang` prop on InsightsPostApp.
// FR strings follow the editorial register used elsewhere in the FR site:
// vous form, direct and confident, no semicolons, no em-dashes in dialog.
const IP_STRINGS = {
  en: {
    home: 'Home',
    insights: 'Insights',
    by: 'By',
    published: 'Published',
    faqEyebrow: 'Frequently asked questions',
    faqH: 'Common questions',
    sourcesEyebrow: 'Sources',
    sourcesLink: 'Link',
    authorEyebrow: 'About the author',
    authorLink: 'More about the team →',
    relatedEyebrow: 'Read next',
    relatedH: 'More from Insights',
    ctaFallbackH: 'Want to talk about your collection?',
    ctaFallbackSub: "We work with contemporary brands across our 8-country network. If something here is relevant to what you're building, let's talk.",
    ctaFallbackBtn: 'Start a conversation',
    ctaSecondary: 'See our solutions →',
    newsletterH: 'Insights delivered',
    newsletterEm: 'monthly.',
    newsletterP: 'One email a month. No spam.',
    newsletterPlaceholder: 'your@email',
    newsletterEmailLabel: 'Email address',
    newsletterBtn: 'Subscribe',
    newsletterPrivacy: 'Unsubscribe anytime.',
    notFoundH: 'Article not found',
    notFoundP: 'We could not find this Insights piece.',
    notFoundLink: 'Back to all Insights →',
    placeholderBody: 'This article is being written. Check back soon — we publish new Insights monthly. In the meantime, you might be interested in:',
    placeholderLinks: [
      { href: '/solutions',  label: 'All solutions — five integrated capabilities' },
      { href: '/our-network', label: 'Our network — seven sourcing countries' },
      { href: '/about',      label: 'About Market Fit Group' },
    ],
    homeFile: '/',
    insightsFile: '/insights',
    solutionsFile: '/solutions',
    contactFile: '/contact',
    locale: 'en-GB',
  },
  fr: {
    home: 'Accueil',
    insights: 'Insights',
    by: 'Par',
    published: 'Publié le',
    faqEyebrow: 'Questions fréquentes',
    faqH: 'Questions courantes',
    sourcesEyebrow: 'Sources',
    sourcesLink: 'Lien',
    authorEyebrow: "À propos de l'auteur",
    authorLink: "En savoir plus sur l'équipe →",
    relatedEyebrow: 'À lire ensuite',
    relatedH: "Plus d'articles Insights",
    ctaFallbackH: "Envie d'échanger sur votre collection ?",
    ctaFallbackSub: 'Nous travaillons avec des marques contemporaines à travers notre réseau de sept pays. Si quelque chose ici résonne avec ce que vous construisez, parlons-en.',
    ctaFallbackBtn: 'Démarrer une conversation',
    ctaSecondary: 'Voir nos solutions →',
    newsletterH: 'Des Insights livrés',
    newsletterEm: 'chaque mois.',
    newsletterP: 'Un e-mail par mois. Pas de spam.',
    newsletterPlaceholder: 'votre@email',
    newsletterEmailLabel: 'Adresse e-mail',
    newsletterBtn: "S'abonner",
    newsletterPrivacy: 'Désabonnement à tout moment.',
    notFoundH: 'Article introuvable',
    notFoundP: "Nous n'avons pas trouvé cet article Insights.",
    notFoundLink: 'Retour à tous les articles Insights →',
    placeholderBody: 'Cet article est en cours de rédaction. Revenez bientôt — nous publions de nouveaux Insights chaque mois. En attendant, vous pourriez être intéressé par :',
    placeholderLinks: [
      { href: '/fr/solutions',     label: 'Toutes les solutions — cinq capacités intégrées' },
      { href: '/fr/notre-reseau',  label: 'Notre réseau — sept pays de sourcing' },
      { href: '/fr/a-propos',      label: 'À propos de Market Fit Group' },
    ],
    homeFile: '/fr',
    insightsFile: '/fr/insights',
    solutionsFile: '/fr/solutions',
    contactFile: '/fr/contact',
    locale: 'fr-FR',
  },
};

function ipT(lang) { return IP_STRINGS[lang] || IP_STRINGS.en; }

// ---- Reveal hook (matches pages.jsx pattern) ----
function ipUseReveal() {
  const ref = ipUseRef(null);
  ipUseEffect(() => {
    if (!ref.current) return;
    const els = ref.current.querySelectorAll('.pg-reveal');
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) e.target.classList.add('in'); });
    }, { threshold: 0.12, rootMargin: '0px 0px -10% 0px' });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);
  return ref;
}

// ---- Pretty date formatter ----
function ipFmtDate(iso, locale) {
  try {
    const d = new Date(iso + 'T00:00:00Z');
    return d.toLocaleDateString(locale || 'en-GB', {
      year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC',
    });
  } catch (e) { return iso; }
}

// ---- Reading-time localiser ----
// IP_POSTS stores readingTime as "8 minute read" (EN). For FR pages we
// transform to "8 min de lecture" so the byline and related cards don't leak EN.
function ipReadingTime(s, lang) {
  if (lang !== 'fr' || !s) return s;
  const m = s.match(/^(\d+)\s*minute\s*read$/i);
  return m ? m[1] + ' min de lecture' : s;
}

// ---- Category localiser ----
// post.category in IP_POSTS is in English. Translates to the FR labels used in
// pages-fr.jsx INS_CATS so the eyebrow and related-card category labels stay
// consistent on FR pages.
const IP_CATEGORY_FR = {
  'Sourcing strategy': 'Stratégie de sourcing',
  'Operational': 'Opérationnel',
  'Country guides': 'Guides pays',
  'Compliance & sustainability': 'Conformité & durabilité',
  'Fabric & trim': 'Tissu & accessoires',
};
function ipCategory(cat, lang) {
  if (lang !== 'fr' || !cat) return cat;
  return IP_CATEGORY_FR[cat] || cat;
}

// ---- Author display name ----
// Posts with authorType === 'Organization' (e.g., Market Fit Group as author)
// render the org name without an /about link and skip the IpAuthor bio block.
// Person-authored posts continue to read from IP_AUTHORS keyed by post.author.
function ipAuthorDisplayName(post, lang) {
  if (post.authorType === 'Organization') return post.orgAuthorName || 'Market Fit';
  const a = IP_AUTHORS[post.author];
  if (!a) return '';
  return (lang === 'fr' && a.nameFr) || a.name;
}

// ---- FAQ accordion ----
function IpFaq({ items, lang }) {
  const t = ipT(lang);
  const [open, setOpen] = ipUseState(0);
  if (!items || !items.length) return null;
  return (
    <div className="ip-faq">
      <div className="ip-faq-eyebrow">{t.faqEyebrow}</div>
      <h2 className="ip-faq-h">{t.faqH}</h2>
      <ul className="ip-faq-list">
        {items.map((it, i) => (
          <li key={i} className={'ip-faq-item' + (open === i ? ' open' : '')}>
            <button
              className="ip-faq-q"
              type="button"
              aria-expanded={open === i}
              onClick={() => setOpen(open === i ? -1 : i)}
            >
              <span>{it.q}</span>
              <span className="ip-faq-q-mark" aria-hidden="true" />
            </button>
            <div className="ip-faq-a">
              {it.a.split('\n\n').map((para, j) => <p key={j}>{para}</p>)}
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
}

// ---- Sources list ----
function IpSources({ items, lang }) {
  const t = ipT(lang);
  if (!items || !items.length) return null;
  return (
    <div className="ip-sources">
      <div className="ip-sources-eyebrow">{t.sourcesEyebrow}</div>
      <ol className="ip-sources-list">
        {items.map((s, i) => (
          <li key={i}>
            <strong>{s.org}</strong> — {s.title}.{' '}
            {s.url ? <a href={s.url} target="_blank" rel="noopener">{t.sourcesLink}</a> : null}
          </li>
        ))}
      </ol>
    </div>
  );
}

// ---- Author bio ----
function IpAuthor({ author, lang }) {
  const t = ipT(lang);
  // FR pages use the FR About link; the author.href in IP_AUTHORS targets EN.
  const aboutHref = lang === 'fr' ? '/fr/a-propos' : author.href;
  const name = (lang === 'fr' && author.nameFr) || author.name;
  const role = (lang === 'fr' && author.roleFr) || author.role;
  const bio  = (lang === 'fr' && author.bioFr)  || author.bio;
  return (
    <section className="ip-author">
      <div className="ip-author-inner">
        <div className="ip-author-portrait">
          {author.avatar ? (
            <img src={author.avatar} alt={name} width="320" height="320" loading="lazy" decoding="async" />
          ) : (
            <div className="ip-author-portrait-fallback">{author.initials}</div>
          )}
        </div>
        <div>
          <div className="ip-author-eyebrow">{t.authorEyebrow}</div>
          <h3 className="ip-author-name">{name}</h3>
          <div className="ip-author-role">{role} · {author.location}</div>
          <p className="ip-author-bio">{bio}</p>
          <a href={aboutHref} className="ip-author-link">{t.authorLink}</a>
        </div>
      </div>
    </section>
  );
}

// ---- Related posts (3 cards) ----
function IpRelated({ posts, lang }) {
  const t = ipT(lang);
  if (!posts || !posts.length) return null;
  return (
    <section className="ip-related">
      <div className="ip-related-inner">
        <div className="ip-related-eyebrow">{t.relatedEyebrow}</div>
        <h2 className="ip-related-h">{t.relatedH}</h2>
        <div className="ip-related-grid">
          {posts.map((p, i) => {
            const href = lang === 'fr' ? (p.frenchFile || p.file) : p.file;
            return (
              <article className="ins-card pg-reveal" key={p.slug} style={{ transitionDelay: (i * 60) + 'ms' }}>
                <div className="ins-card-img">
                  <img src={p.heroImage} alt={p.heroImageAlt} width="800" height="600" loading="lazy" decoding="async" />
                </div>
                <div className="ins-card-eyebrow">{ipCategory(p.category, lang)}</div>
                <h3 className="ins-card-h"><a href={href}>{p.title}</a></h3>
                <p className="ins-card-excerpt">{p.excerpt}</p>
                <div className="ins-card-meta">
                  {ipAuthorDisplayName(p, lang)} · {ipFmtDate(p.publishedDate, t.locale)} · {ipReadingTime(p.readingTime, lang)}
                </div>
              </article>
            );
          })}
        </div>
      </div>
    </section>
  );
}

// ---- End-of-post CTA ----
function IpCta({ post, lang }) {
  const t = ipT(lang);
  const headline = (lang === 'fr' && post.ctaHeadlineFr) || post.ctaHeadline || t.ctaFallbackH;
  const subcopy  = (lang === 'fr' && post.ctaSubcopyFr)  || post.ctaSubcopy  || t.ctaFallbackSub;
  const button   = (lang === 'fr' && post.ctaButtonFr)   || post.ctaButton   || t.ctaFallbackBtn;
  return (
    <section className="ip-cta">
      <div className="ip-cta-inner">
        <h2 className="ip-cta-h">{headline}</h2>
        <p className="ip-cta-sub">{subcopy}</p>
        <a href={lang === 'fr' ? (post.ctaLinkFr || t.contactFile) : (post.ctaLink || t.contactFile)} className="ip-cta-btn">
          {button} →
        </a>
        <a href={t.solutionsFile} className="ip-cta-secondary">{t.ctaSecondary}</a>
      </div>
    </section>
  );
}

// ---- Newsletter (single-line, subtle) ----
function IpNewsletter({ lang }) {
  const t = ipT(lang);
  return (
    <section className="pg-newsletter" style={{ paddingTop: 'var(--s-7)', paddingBottom: 'var(--s-7)' }}>
      <div className="pg-container">
        <div>
          <h2 className="pg-news-h" style={{ fontSize: 'clamp(1.4rem, 2vw, 1.8rem)' }}>
            {t.newsletterH} <em>{t.newsletterEm}</em>
          </h2>
          <p className="pg-news-p">{t.newsletterP}</p>
        </div>
        <form className="pg-news-form" onSubmit={(e) => e.preventDefault()}>
          <input type="email" placeholder={t.newsletterPlaceholder} aria-label={t.newsletterEmailLabel} />
          <button type="submit">{t.newsletterBtn}</button>
          <p className="pg-news-privacy">{t.newsletterPrivacy}</p>
        </form>
      </div>
    </section>
  );
}

// ---- Placeholder body (for the 6 launch posts) ----
function IpPlaceholderBody({ lang }) {
  const t = ipT(lang);
  return (
    <React.Fragment>
      <p>{t.placeholderBody}</p>
      <ul className="ip-soon-links">
        {t.placeholderLinks.map((l, i) => (
          <li key={i}><a href={l.href}>{l.label}</a></li>
        ))}
      </ul>
    </React.Fragment>
  );
}

// ---- Main template ----
function InsightsPostApp({ slug, body, faq, sources, lang }) {
  const ref = ipUseReveal();
  const language = lang === 'fr' ? 'fr' : 'en';
  const t = ipT(language);
  const post = IP_POSTS.find((p) => p.slug === slug);
  if (!post) {
    return (
      <div ref={ref}>
        <Nav />
        <main style={{ maxWidth: 720, margin: 'var(--s-9) auto', padding: '0 var(--s-5)' }}>
          <h1 className="ip-h1">{t.notFoundH}</h1>
          <p>{t.notFoundP} <a href={t.insightsFile}>{t.notFoundLink}</a></p>
        </main>
        <Footer />
      </div>
    );
  }

  const isOrgAuthor = post.authorType === 'Organization';
  const author = isOrgAuthor ? null : IP_AUTHORS[post.author];
  const authorDisplayName = ipAuthorDisplayName(post, language);
  const trail = [
    { label: t.home, href: t.homeFile },
    { label: t.insights, href: t.insightsFile },
    { label: post.title },
  ];

  // Related: 3 most recent in same category, fallback to most recent anywhere.
  const related = (() => {
    const pool = IP_POSTS.filter((p) => p.slug !== post.slug);
    const sameCat = pool.filter((p) => p.category === post.category)
      .sort((a, b) => b.publishedDate.localeCompare(a.publishedDate));
    if (sameCat.length >= 3) return sameCat.slice(0, 3);
    const others = pool.filter((p) => p.category !== post.category)
      .sort((a, b) => b.publishedDate.localeCompare(a.publishedDate));
    return [...sameCat, ...others].slice(0, 3);
  })();

  // FAQ items default to placeholder, picking the FR set when language === 'fr'.
  const defaultFaq = language === 'fr'
    ? (typeof IP_PLACEHOLDER_FAQ_FR !== 'undefined' ? IP_PLACEHOLDER_FAQ_FR : IP_PLACEHOLDER_FAQ)
    : IP_PLACEHOLDER_FAQ;
  const faqItems = faq || defaultFaq;

  return (
    <div ref={ref}>
      <Nav />
      <Breadcrumbs trail={trail} />

      {/* HEADER */}
      <header className="ip-header">
        <div className="ip-header-inner">
          <div className="ip-eyebrow pg-reveal">{ipCategory(post.category, language)}</div>
          <h1 className="ip-h1 pg-reveal" style={{ transitionDelay: '60ms' }}>{post.title}</h1>
          <p className="ip-subhead pg-reveal" style={{ transitionDelay: '120ms' }}>{post.excerpt}</p>
          <div className="ip-byline pg-reveal" style={{ transitionDelay: '180ms' }}>
            <span>{t.by} {isOrgAuthor
              ? authorDisplayName
              : <a href={language === 'fr' ? '/fr/a-propos' : author.href}>{authorDisplayName}</a>
            }</span>
            <span className="ip-byline-sep" />
            <span>{t.published} {ipFmtDate(post.publishedDate, t.locale)}</span>
            <span className="ip-byline-sep" />
            <span>{ipReadingTime(post.readingTime, language)}</span>
          </div>
        </div>
      </header>

      {/* HERO IMAGE */}
      <section className="ip-hero">
        <div className="ip-hero-frame">
          <div className="ip-hero-img">
            <img src={post.heroImage} alt={post.heroImageAlt} width="2400" height="1350"
                 loading="eager" fetchpriority="high" decoding="async" />
          </div>
        </div>
      </section>

      {/* BODY */}
      <section className="ip-body">
        <div className="ip-prose">
          {body || <IpPlaceholderBody lang={language} />}
        </div>
        <IpFaq items={faqItems} lang={language} />
        <IpSources items={sources} lang={language} />
      </section>

      {/* AUTHOR — hidden for Organization-authored posts */}
      {!isOrgAuthor && <IpAuthor author={author} lang={language} />}

      {/* RELATED */}
      <IpRelated posts={related} lang={language} />

      {/* CTA */}
      <IpCta post={post} lang={language} />

      {/* NEWSLETTER */}
      <IpNewsletter lang={language} />

      <Footer />
    </div>
  );
}

Object.assign(window, {
  InsightsPostApp,
  IpFaq, IpSources, IpAuthor, IpRelated, IpCta, IpNewsletter,
  IpPlaceholderBody,
  IP_STRINGS,
});
