/* Guide de la prospection B2B (21/10/2026) : le rendu commun de toutes les pages de la série
 * et de leur page d'accueil /guide-prospection-b2b.
 *
 * Une page du guide = un fichier de contenu guides/<slug>.json. scripts/build-guides.mjs en tire
 * <slug>.html (en-tête, JSON-LD, contenu embarqué dans <script id="guide-data">) et guides-index.js
 * (la liste des pages, lue ici, par le menu des pages du Ciblage et du Pack et par le sitemap).
 * Aucune page n'a son propre .jsx : modifier ce fichier modifie toute la série.
 *
 * Le texte n'est jamais injecté comme HTML : React l'échappe. Deux marques seulement sont lues
 * dans les paragraphes : [texte](/adresse) pour un lien et **texte** pour du gras. */

const { useEffect } = React;
const {
  ArrowUpRight, Check, FooterMin, SiteNav, Breadcrumb, CiblagePlan, PackPlan, appUrl,
  GuideIcone, useReveal, useMotionClock, motion, MOTION_STILL,
} = window.BMShared;

const D = JSON.parse(document.getElementById('guide-data').textContent);
const GUIDES = window.BM_GUIDES || [];
const HUB = { href: '/guide-prospection-b2b', label: 'Guide de la prospection' };

const OFFRES = {
  Ciblage: {
    nom: 'le Ciblage', page: '/ciblage-prospection', cta: 'Compter mon marché',
    note: 'Ton marché est compté gratuitement : tu paies seulement si tu le valides.',
  },
  Pack: {
    nom: 'le Pack', page: '/moteur-prospection', cta: 'Lancer ma prospection',
    note: 'Tu paies seulement si tu valides tes 10 premiers messages.',
  },
};

/* --- Texte : [lien](/adresse) et **gras**, rien d'autre ----------------------------------- */
const MARQUES = /\[([^\]]+)\]\(([^)\s]+)\)|\*\*([^*]+)\*\*/g;
const Txt = ({ s }) => {
  const out = [];
  let last = 0;
  let m;
  MARQUES.lastIndex = 0;
  while ((m = MARQUES.exec(s)) !== null) {
    if (m.index > last) out.push(s.slice(last, m.index));
    if (m[1]) {
      const ext = /^https?:/.test(m[2]);
      out.push(<a key={m.index} href={m[2]} {...(ext ? { target: '_blank', rel: 'noopener' } : {})}>{m[1]}</a>);
    } else {
      out.push(<strong key={m.index}>{m[3]}</strong>);
    }
    last = MARQUES.lastIndex;
  }
  if (last < s.length) out.push(s.slice(last));
  return <>{out}</>;
};

const Eyebrow = ({ children }) => (
  <div className="expertise-eyebrow eyebrow"><span className="pulse" />{children}</div>
);

const Titre = ({ h2, em, id }) => (
  <h2 className="expertises-cases-title" id={id}>{h2}{em ? <> <em>{em}</em></> : null}</h2>
);

const Paras = ({ list }) => (list || []).map((p, i) => <p className="gp-p" key={i}><Txt s={p} /></p>);

const dateFr = (iso) => {
  try {
    return new Date(iso + 'T12:00:00Z').toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' });
  } catch (e) { return iso; }
};

/* --- Les blocs d'une section ----------------------------------------------------------------- */
const Bloc = ({ s }) => (
  <>
    <Paras list={s.paragraphs} />
    {s.steps && s.steps.length ? (
      <ol className="uc-steps">
        {s.steps.map((st, i) => (
          <li className="uc-step" key={i}>
            <div className="uc-step-num">/ {String(i + 1).padStart(2, '0')}</div>
            <div className="uc-step-content"><h3>{st.title}</h3><p><Txt s={st.body} /></p></div>
          </li>
        ))}
      </ol>
    ) : null}
    {s.items && s.items.length ? (
      <ul className="uc-checklist">
        {s.items.map((it, i) => (
          <li key={i}><Check /><span>{it.strong ? <strong>{it.strong} </strong> : null}<Txt s={it.text} /></span></li>
        ))}
      </ul>
    ) : null}
    {s.table ? (
      <div className="uc-table-wrap">
        <table className="uc-table">
          <thead><tr>{s.table.columns.map((c, i) => <th key={i} scope="col">{c}</th>)}</tr></thead>
          <tbody>
            {s.table.rows.map((r, ri) => (
              <tr key={ri}>{r.map((cell, ci) => ci === 0
                ? <th scope="row" key={ci}><Txt s={cell} /></th>
                : <td key={ci}><Txt s={cell} /></td>)}</tr>
            ))}
          </tbody>
        </table>
      </div>
    ) : null}
    {s.callout ? (
      <div className="uc-callout">
        {s.callout.label ? <span className="uc-callout-label">{s.callout.label}</span> : null}
        <p><Txt s={s.callout.text} /></p>
      </div>
    ) : null}
    <Paras list={s.after} />
  </>
);

/* --- Cartes vers d'autres pages du guide ------------------------------------------------------ */
const CarteGuide = ({ g, i = 0 }) => (
  <a className={'gp-card reveal delay-' + (i % 4)} href={'/' + g.slug}>
    <span className="gp-card-icon"><GuideIcone nom={g.icone} /></span>
    <span className="gp-card-tag">{g.offre === 'Pack' ? 'Le Pack' : 'Le Ciblage'}</span>
    <span className="gp-card-title">{g.question}</span>
    <span className="gp-card-lead">{g.lead}</span>
    <span className="gp-card-more">Lire la réponse <ArrowUpRight size={13} /></span>
  </a>
);

/* Mêmes offre d'abord, puis les autres ; quatre au plus. */
const voisins = (slug, offre) => {
  const autres = GUIDES.filter((g) => g.slug !== slug);
  return [...autres.filter((g) => g.offre === offre), ...autres.filter((g) => g.offre !== offre)].slice(0, 4);
};

/* La page d'accueil du guide : une recherche tape tour à tour les questions du guide, puis la réponse
 * courte de la page apparaît, comme dans un moteur de recherche. Boucle de 7 s par question ; figée sur
 * la première question, réponse affichée, pour le pré-rendu et le mouvement réduit. */
const RechercheMotion = () => {
  const t = useMotionClock();
  const P = 7;
  const S = t / 1000;
  const n = GUIDES.length;
  if (!n) return null;
  const idx = MOTION_STILL ? 0 : Math.floor(S / P) % n;
  const m = motion.loop(S, P, 5);
  const g = GUIDES[idx];
  const q = motion.type(m, 0.3, 2.3, g.question);
  const tape = m < 2.5;
  return (
    <div className="gp-search" aria-label="Exemple : une question du guide et sa réponse courte">
      <div className="gp-search-bar">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7" /><path d="m20 20-4-4" /></svg>
        <span className="gp-search-q">{MOTION_STILL ? g.question : q}{tape && !MOTION_STILL ? <span className="gp-caret" /> : null}</span>
      </div>
      <a className="gp-search-result" href={'/' + g.slug} style={motion.fade(m, 2.7, 6.6, 14)}>
        <span className="gp-search-url"><span className="gp-card-icon gp-card-icon-sm"><GuideIcone nom={g.icone} size={16} /></span>boommaker.io › {g.slug}</span>
        <span className="gp-search-title">{g.question}</span>
        <span className="gp-search-label">La réponse courte</span>
        <span className="gp-search-snippet">{g.reponse}</span>
      </a>
      <div className="gp-search-dots" aria-hidden="true">
        {GUIDES.map((x, i) => <span key={x.slug} className={i === idx ? 'on' : undefined} />)}
      </div>
    </div>
  );
};

const Toc = ({ entries }) => (
  <aside className="expertises-toc" aria-label="Sommaire de la page">
    <span className="expertises-toc-label">Sommaire</span>
    <ol>
      {entries.map((e) => (
        <li key={e.href}>
          <a href={e.href}>
            <span className="expertises-toc-num">{e.n}</span>
            <span className="expertises-toc-title">{e.title}</span>
          </a>
        </li>
      ))}
    </ol>
  </aside>
);

/* Arrivée avec une ancre (#faq…) : les sections n'existent qu'après le montage de React. */
const useAncre = () => useEffect(() => {
  if (!window.location.hash) return undefined;
  const go = () => { const el = document.querySelector(window.location.hash); if (el) el.scrollIntoView({ block: 'start' }); };
  const t = setTimeout(go, 120);
  return () => clearTimeout(t);
}, []);

/* === Une page du guide ======================================================================== */
const GuidePage = () => {
  useAncre();
  useReveal();
  const moi = GUIDES.find((g) => g.slug === D.slug);
  const o = OFFRES[D.offre];
  const toc = [
    { href: '#reponse', n: '/ Réponse', title: 'La réponse courte' },
    ...D.sections.map((s, i) => ({ href: '#' + s.id, n: '/ ' + String(i + 1).padStart(2, '0'), title: s.toc })),
    { href: '#boommaker', n: '/ Boom Maker', title: D.boomMaker.toc || 'Ce que fait Boom Maker' },
    ...(D.faq && D.faq.length ? [{ href: '#faq', n: '/ FAQ', title: 'Questions fréquentes' }] : []),
  ];

  return (
    <div className="guide-page tarifs-page">
      <SiteNav />

      <article className="audit-hero gp-hero">
        <div className="container">
          <Breadcrumb items={[{ href: '/', label: 'Accueil' }, HUB, { label: D.breadcrumb }]} />
          <div className="gp-hero-split">
            <div>
              <span className="eyebrow"><span className="pulse" /> {D.eyebrow}</span>
              <h1>{D.h1}{D.h1Em ? <> <em>{D.h1Em}</em></> : null}</h1>
              <p className="lead">{D.lead}</p>
              <p className="gp-byline">
                Par <a href="/a-propos">Julia Levy</a>, fondatrice de Boom Maker · Mis à jour le {dateFr(D.dateModified || D.datePublished)} · {D.minutes} min de lecture
              </p>
            </div>
            <div className="gp-hero-art" aria-hidden="true">
              <span className="gp-orbit gp-orbit-1" /><span className="gp-orbit gp-orbit-2" />
              <span className="gp-hero-icon"><GuideIcone nom={D.icone || (moi && moi.icone)} size={64} /></span>
              <span className="gp-hero-chip gp-hero-chip-1">{D.offre === 'Pack' ? 'Le Pack' : 'Le Ciblage'}</span>
              <span className="gp-hero-chip gp-hero-chip-2">{D.minutes} min</span>
            </div>
          </div>
        </div>
      </article>

      <section className="expertises-content">
        <div className="container expertises-layout">
          <Toc entries={toc} />
          <div className="expertises-main">

            <section className="gp-answer" id="reponse" aria-labelledby="reponse-titre">
              <span className="gp-answer-label" id="reponse-titre">La réponse courte</span>
              <p><Txt s={D.reponse} /></p>
            </section>

            {D.sections.map((s) => (
              <section className="expertises-cases gp-section" id={s.id} key={s.id}>
                {s.eyebrow ? <Eyebrow>{s.eyebrow}</Eyebrow> : null}
                <Titre h2={s.h2} em={s.h2Em} />
                <Bloc s={s} />
              </section>
            ))}

            <section className="expertises-cases gp-bm" id="boommaker">
              <Eyebrow>Ce que fait Boom Maker</Eyebrow>
              <Titre h2={D.boomMaker.h2} em={D.boomMaker.h2Em} />
              <div className="gp-bm-split">
                <div>
                  <Paras list={D.boomMaker.paragraphs} />
                  {D.boomMaker.points && D.boomMaker.points.length ? (
                    <ul className="uc-checklist">
                      {D.boomMaker.points.map((p, i) => <li key={i}><Check /><span><Txt s={p} /></span></li>)}
                    </ul>
                  ) : null}
                  <p className="gp-src"><a href={o.page}>Voir le détail de {o.nom}</a></p>
                </div>
                <div className="pricing-grid gp-plan">{D.offre === 'Pack' ? <PackPlan /> : <CiblagePlan />}</div>
              </div>
            </section>

            {D.faq && D.faq.length ? (
              <section className="expertises-faq" id="faq" aria-labelledby="faq-title">
                <Eyebrow>Questions fréquentes</Eyebrow>
                <h2 className="expertises-faq-title" id="faq-title">Ce qu'on nous demande <em>aussi.</em></h2>
                <div className="expertises-faq-list">
                  {D.faq.map((f) => (
                    <details className="expertises-faq-item" key={f.q}>
                      <summary><span>{f.q}</span><span className="expertises-faq-caret" aria-hidden="true">+</span></summary>
                      <p>{f.a}</p>
                    </details>
                  ))}
                </div>
              </section>
            ) : null}

            {D.sources && D.sources.length ? (
              <section className="gp-sources" aria-labelledby="sources-titre">
                <span className="gp-sources-label" id="sources-titre">Sources</span>
                <ol>
                  {D.sources.map((s, i) => (
                    <li key={i}><a href={s.url} target="_blank" rel="noopener">{s.label}</a></li>
                  ))}
                </ol>
              </section>
            ) : null}

            <div className="expertises-cta-final">
              <h2>{D.cta.title}</h2>
              <p>{D.cta.text}</p>
              <div className="cta-row">
                <a href={appUrl(D.offre)} className="btn btn-glow">{o.cta} <ArrowUpRight /></a>
                <a href={o.page} className="btn btn-ghost">Découvrir {o.nom} <ArrowUpRight /></a>
              </div>
              <p className="gp-cta-note">{o.note}</p>
            </div>

            {voisins(D.slug, D.offre).length ? (
              <section className="gp-related" aria-labelledby="related-titre">
                <Eyebrow>Les autres questions</Eyebrow>
                <h2 className="expertises-cases-title" id="related-titre">Tu te demandes <em>peut-être aussi.</em></h2>
                <div className="gp-cards">
                  {voisins(D.slug, D.offre).map((g, i) => <CarteGuide g={g} i={i} key={g.slug} />)}
                </div>
                <p className="gp-src"><a href={HUB.href}>Toutes les questions du guide</a></p>
              </section>
            ) : null}

          </div>
        </div>
      </section>

      <FooterMin />
    </div>
  );
};

/* === La page d'accueil du guide ================================================================ */
const HubGroupe = ({ offre, titre, em, intro, num }) => {
  const list = GUIDES.filter((g) => g.offre === offre);
  if (!list.length) return null;
  const o = OFFRES[offre];
  return (
    <section className="expertises-cases gp-etape" id={offre.toLowerCase()}>
      <span className="gp-etape-num" aria-hidden="true">{num}</span>
      <Eyebrow>Étape {num} · {offre === 'Pack' ? 'Le Pack' : 'Le Ciblage'}</Eyebrow>
      <Titre h2={titre} em={em} />
      <p className="expertises-cases-lead">{intro}</p>
      <div className="gp-cards">{list.map((g, i) => <CarteGuide g={g} i={i} key={g.slug} />)}</div>
      <p className="gp-src"><a href={o.page}>Voir le détail de {o.nom}</a></p>
    </section>
  );
};

const HubPage = () => {
  useAncre();
  useReveal();
  return (
    <div className="guide-page tarifs-page">
      <SiteNav />
      <article className="audit-hero gp-hero">
        <div className="container">
          <Breadcrumb items={[{ href: '/', label: 'Accueil' }, { label: HUB.label }]} />
          <div className="gp-hero-split gp-hub-split">
            <div>
              <span className="eyebrow"><span className="pulse" /> {D.eyebrow}</span>
              <h1>{D.h1}{D.h1Em ? <> <em>{D.h1Em}</em></> : null}</h1>
              <p className="lead">{D.lead}</p>
              <div className="gp-hub-stats">
                <span><b>{GUIDES.length}</b> questions</span>
                <span><b>{GUIDES.filter((g) => g.offre === 'Ciblage').length}</b> pour trouver</span>
                <span><b>{GUIDES.filter((g) => g.offre === 'Pack').length}</b> pour écrire et relancer</span>
              </div>
            </div>
            <RechercheMotion />
          </div>
        </div>
      </article>

      <section className="expertises-content">
        <div className="container expertises-layout">
          <Toc entries={[
            ...(D.outil ? [{ href: '#outil', n: '/ Outil', title: 'Le simulateur' }] : []),
            { href: '#ciblage', n: '/ 01', title: 'Trouver qui contacter' },
            { href: '#pack', n: '/ 02', title: 'Écrire, envoyer, relancer' },
            ...(D.aussi && D.aussi.length ? [{ href: '#aussi', n: '/ 03', title: 'À lire aussi' }] : []),
          ]} />
          <div className="expertises-main">
            {D.outil ? (
              <a className="gp-outil reveal" id="outil" href={D.outil.href}>
                <span className="gp-outil-icon"><GuideIcone nom="calcul" size={40} /></span>
                <span className="gp-outil-body">
                  <span className="gp-outil-eyebrow">{D.outil.eyebrow}</span>
                  <span className="gp-outil-title">{D.outil.h2} <em>{D.outil.h2Em}</em></span>
                  <span className="gp-outil-text">{D.outil.texte}</span>
                  <span className="btn btn-glow gp-outil-cta">{D.outil.cta} <ArrowUpRight /></span>
                </span>
              </a>
            ) : null}

            <div className="gp-parcours">
              <HubGroupe num="01" offre="Ciblage" titre={D.ciblage.h2} em={D.ciblage.h2Em} intro={D.ciblage.intro} />
              <HubGroupe num="02" offre="Pack" titre={D.pack.h2} em={D.pack.h2Em} intro={D.pack.intro} />
            </div>

            {D.aussi && D.aussi.length ? (
              <section className="expertises-cases" id="aussi">
                <Eyebrow>À lire aussi</Eyebrow>
                <Titre h2="Outils, coûts et automatisation" em="de la prospection." />
                <ul className="gp-aussi">
                  {D.aussi.map((a) => (
                    <li key={a.href}><a href={a.href}>{a.label} <ArrowUpRight size={13} /></a></li>
                  ))}
                </ul>
              </section>
            ) : null}

            <div className="expertises-cta-final">
              <h2>{D.cta.title}</h2>
              <p>{D.cta.text}</p>
              <div className="cta-row">
                <a href={appUrl('Ciblage')} className="btn btn-ghost">Compter mon marché <ArrowUpRight /></a>
                <a href={appUrl('Pack')} className="btn btn-glow">Lancer ma prospection <ArrowUpRight /></a>
              </div>
            </div>
          </div>
        </div>
      </section>

      <FooterMin />
    </div>
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(D.kind === 'hub' ? <HubPage /> : <GuidePage />);
