// book.jsx — Le composant Book : scroll → tournes de pages
// Repose sur les composants exposés par book-content.jsx

// ─── Définition des spreads (double-pages) ───────────────────────────────────

function getSpreads(onGoTo) {
  // Chaque entrée = état d'une double-page.
  // Entre spread i et i+1, la "page tournante" affiche :
  //   face avant  = spreads[i].right
  //   face arrière = spreads[i+1].left
  return [
    // spread 0 — livre fermé (couverture seule visible côté droit)
    { id: "cover",    label: "Couverture",         left: null,                            right: <Cover/> },
    // spread 1 — ouverture : page de garde / sommaire
    { id: "front",    label: "Sommaire",           left: <HalfTitle/>,                    right: <TOC onGoTo={onGoTo}/> },
    // spread 2 — Chapitre I : Qui suis-je
    { id: "about",    label: "Qui suis-je",        left: <ChapterIntro num="I"  title="Qui suis-je"
                                                              head="Chapitre I" folio="9" dropcap="J"
                                                              lead="e n'ai jamais cessé de penser qu'un texte attend qu'on le regarde. Pas qu'on le juge — qu'on l'écoute, vraiment. C'est ce que je tente de faire, manuscrit après manuscrit."/>,
                                                    right: <AboutBody/> },
    // spread 3 — Chapitre II : Services
    { id: "services", label: "Mes services",       left: <ChapterIntro num="II" title="Mes services"
                                                              head="Chapitre II" folio="21" dropcap="C"
                                                              lead="haque texte a son chantier. Le mien, c'est de trouver les gestes justes — légers ou plus marqués — pour que le vôtre s'épanouisse sans jamais se trahir."/>,
                                                    right: <ServicesBody/> },
    // spread 4 — Chapitre III : Tarifs
    { id: "pricing",  label: "Mes tarifs",         left: <ChapterIntro num="III" title="Mes tarifs"
                                                              head="Chapitre III" folio="37" dropcap="L"
                                                              lead="es tarifs sont clairs, parce que la confiance commence là. Mais chaque manuscrit étant unique, le devis l'est aussi — toujours discuté, jamais imposé."/>,
                                                    right: <PricingBody/> },
    // spread 5 — Chapitre IV : Méthode
    { id: "process",  label: "Ma méthode",         left: <ChapterIntro num="IV" title="Ma méthode"
                                                              head="Chapitre IV" folio="53" dropcap="C"
                                                              lead="inq étapes, comme cinq respirations. De notre premier échange à la remise du texte, je m'engage à une transparence totale — vous savez où vous en êtes."/>,
                                                    right: <ProcessBody/> },
    // spread 6 — Chapitre V : FAQ
    { id: "faq",      label: "Questions",          left: <ChapterIntro num="V"  title="Questions fréquentes"
                                                              head="Chapitre V" folio="71" dropcap="V"
                                                              lead="oici les questions qu'on me pose le plus souvent. Si la vôtre n'y figure pas, elle a sa place dans le prochain chapitre — il s'intitule simplement « Écrivons-nous »."/>,
                                                    right: <FAQBody/> },
    // spread 7 — Chapitre VI : Contact
    { id: "contact",  label: "Écrivons-nous",      left: <ContactSideInfo/>,              right: <ContactBody/> },
    // spread 8 — Fin
    { id: "end",      label: "Fin",                left: <EndPage/>,                      right: <BackCover/> },
  ];
}

// ─── La page qui tourne ──────────────────────────────────────────────────────

function TurningPage({ frontNode, backNode, rotation, mode }) {
  // rotation: 0 = page à droite (face avant visible), -180 = page à gauche (face arrière visible)
  const absRot = Math.abs(rotation);
  const turningShadow = Math.sin((absRot / 180) * Math.PI); // 0 → 1 → 0

  if (mode === "fade") {
    // simple cross-fade : la face arrière apparaît, la face avant disparaît
    const fadeFront = 1 - absRot / 180;
    const fadeBack  = absRot / 180;
    return (
      <>
        <div className="turning-page turning-flat" style={{ opacity: fadeFront }}>
          <div className="page-face front">{frontNode}</div>
        </div>
        <div className="turning-page turning-flat turning-left" style={{ opacity: fadeBack }}>
          <div className="page-face back-flat">{backNode}</div>
        </div>
      </>
    );
  }

  if (mode === "slide") {
    // glissement : la page glisse vers la gauche en s'estompant
    const t = absRot / 180;
    const xFront = -t * 100; // %
    const xBack  = (1 - t) * 100;
    return (
      <>
        <div className="turning-page turning-flat" style={{ transform: `translateX(${xFront}%)`, opacity: 1 - t * 0.4 }}>
          <div className="page-face front">{frontNode}</div>
        </div>
        <div className="turning-page turning-flat turning-left" style={{ transform: `translateX(${xBack - 100}%)`, opacity: 1 - (1 - t) * 0.4 }}>
          <div className="page-face back-flat">{backNode}</div>
        </div>
      </>
    );
  }

  // mode "realistic" — 3D
  // Les deux faces sont dans le même conteneur 3D. Le dos utilise rotateY(180deg)
  // (standard CSS) mais overflow est retiré de .page-face pour ne pas briser
  // le contexte preserve-3d — le clipping est délégué à .page-face-inner.
  const frontOn = absRot <= 90;
  return (
    <div
      className="turning-page"
      style={{ transform: `rotateY(${rotation}deg)` }}
    >
      <div className="page-face front" style={{ visibility: frontOn ? "visible" : "hidden" }}>
        <div className="page-face-inner">{frontNode}</div>
        <div className="page-curl-shadow front-shadow" style={{ opacity: Math.sin((absRot/180)*Math.PI) * 0.35 }}/>
      </div>
      <div className="page-face back" style={{ visibility: frontOn ? "hidden" : "visible" }}>
        <div className="page-face-inner">{backNode}</div>
        <div className="page-curl-shadow back-shadow" style={{ opacity: Math.sin((absRot/180)*Math.PI) * 0.35 }}/>
      </div>
    </div>
  );
}

// ─── Le livre ────────────────────────────────────────────────────────────────

function Book({ progress, spreads, mode, dark }) {
  // progress: réel de 0 à (spreads.length - 1)
  const total = spreads.length;
  const idx   = Math.min(total - 2, Math.max(0, Math.floor(progress)));
  const frac  = Math.min(1, Math.max(0, progress - idx));

  const current = spreads[idx];
  const next    = spreads[idx + 1];

  // Courbe d'easing : la page bascule vite au début, ce qui dévoile la
  // nouvelle page à droite presque immédiatement (cubic ease-out).
  const easedFrac = mode === "realistic"
    ? 1 - Math.pow(1 - frac, 3)
    : frac;
  const rotation = -180 * easedFrac;

  // Livre fermé : couverture seule visible (pas de page gauche) au début,
  // 4e de couverture seule (pas de page droite) à la fin.
  const hideLeftPage  = current.left  == null;
  const hideRightPage = next.right    == null;

  // Décalage horizontal du livre pour centrer la couverture quand fermée,
  // et l'animer doucement vers la position "spread complet" pendant la 1ère ouverture.
  let bookOffsetPct = 0;
  if (idx === 0) {
    // début : décalage -25% (cover centrée) qui revient à 0 pendant l'ouverture
    bookOffsetPct = -25 * (1 - easedFrac);
  }

  // ombres d'épaisseur — pages restantes à gauche / droite
  const pagesLeft  = idx;
  const pagesRight = total - idx - 2;

  return (
    <div className={`book-stage ${dark ? "book-dark" : ""}`}>
      <div
        className={`book ${hideLeftPage ? "book-no-left" : ""} ${hideRightPage ? "book-no-right" : ""}`}
        style={{ transform: `rotateX(2deg) translateX(${bookOffsetPct}%)` }}
      >
        {/* Tranche / épaisseur des pages encore non tournées (à droite) */}
        {!hideRightPage && (
          <div className="book-edge book-edge-right" style={{
            width: `${Math.min(14, 4 + pagesRight * 1.4)}px`,
          }}/>
        )}
        {/* Tranche des pages déjà tournées (à gauche) */}
        {!hideLeftPage && (
          <div className="book-edge book-edge-left" style={{
            width: `${Math.min(14, 4 + pagesLeft * 1.4)}px`,
          }}/>
        )}

        {/* Page de gauche statique : c'est la gauche de la spread courante */}
        {!hideLeftPage && (
          <div className="page-static page-left">
            {current.left}
            <div className="page-gutter-shadow gutter-left"/>
          </div>
        )}

        {/* Page de droite statique : c'est la droite de la spread suivante (révélée derrière la page qui tourne) */}
        {!hideRightPage && (
          <div className="page-static page-right">
            {next.right}
            <div className="page-gutter-shadow gutter-right"/>
          </div>
        )}

        {/* Page qui tourne — face avant = right de la spread courante, face arrière = left de la spread suivante */}
        <TurningPage
          frontNode={current.right}
          backNode={next.left}
          rotation={rotation}
          mode={mode}
        />

        {/* Ombre centrale (reliure) — masquée quand pas de page gauche/droite */}
        {!hideLeftPage && !hideRightPage && <div className="book-spine"/>}
      </div>
    </div>
  );
}

// ─── Marque-page ─────────────────────────────────────────────────────────────

function Bookmark({ progress, total, currentLabel }) {
  // position horizontale : remonte le long du bord supérieur du livre
  const pct = Math.min(1, progress / Math.max(1, total - 2));
  return (
    <div className="bookmark-wrap">
      <div className="bookmark-progress">
        <span className="bookmark-label">{currentLabel}</span>
        <span className="bookmark-pct">{Math.round(pct * 100)}%</span>
      </div>
      <div className="bookmark-rail">
        <div className="bookmark-fill" style={{ width: `${pct * 100}%` }}/>
        <div className="bookmark-ribbon" style={{ left: `calc(${pct * 100}% - 8px)` }}>
          <div className="bookmark-ribbon-body"/>
          <div className="bookmark-ribbon-notch"/>
        </div>
      </div>
    </div>
  );
}

// ─── Sommaire flottant ───────────────────────────────────────────────────────

function FloatingTOC({ open, onClose, spreads, currentIdx, onGoTo }) {
  return (
    <div className={`ftoc-overlay ${open ? "is-open" : ""}`} onClick={onClose}>
      <div className="ftoc-card" onClick={(e) => e.stopPropagation()}>
        <div className="ftoc-header">
          <div className="ftoc-eyebrow">Sommaire</div>
          <button className="ftoc-close" onClick={onClose} aria-label="Fermer">×</button>
        </div>
        <ol className="ftoc-list">
          {spreads.map((s, i) => {
            // n'expose pas la "back cover" finale
            if (s.id === "end") return null;
            const isActive = i === currentIdx;
            return (
              <li key={s.id} className={isActive ? "is-active" : ""}>
                <button onClick={() => { onGoTo(i); onClose(); }}>
                  <span className="ftoc-num">{String(i).padStart(2, "0")}</span>
                  <span className="ftoc-label">{s.label}</span>
                </button>
              </li>
            );
          })}
        </ol>
        <div className="ftoc-foot">
          <em>Cliquez pour ouvrir le livre à la page choisie.</em>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { getSpreads, Book, Bookmark, FloatingTOC });
