// ProjectsLog — projets.html v2 : « Le registre des expéditions ».
// Index éditorial du carnet : chaque projet de window.EXPEDITION est une
// ligne du registre (titre display, colonnes mono, tampon biome), un aperçu
// polaroid suit le curseur au survol, la fiche (ProjectModal, partagée avec
// l'accueil via ProjectsExpedition.jsx) s'ouvre au clic.
// Styles : projets.css (base partagée dans styles.css).

// NB : ne jamais nommer une constante « EXPEDITION » ici — Babel compile les
// const en `var` globales et cela écraserait window.EXPEDITION.
const LOG_STEPS = window.EXPEDITION || [];

// "+600 M" → 600 (dénivelé cumulé du registre)
const LOG_ALT = LOG_STEPS.reduce(
  (sum, e) => sum + (parseInt(String(e.alt).replace(/\D/g, ""), 10) || 0), 0
);

// Biomes dans l'ordre d'apparition (onglets de classement)
const LOG_BIOMES = LOG_STEPS.reduce(
  (list, e) => (list.includes(e.biome) ? list : [...list, e.biome]), []
);

const LOG_HOME = "Vincent%20Morin%20Portfolio.html#projets";
const LOG_REDUCE = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

// Projet mis en vitrine sur la couverture (le polaroid « dernier projet »).
// Pour en mettre un autre en avant : changez l'id ci-dessous.
const LOG_LATEST = LOG_STEPS.find(e => e.id === "plane-3d") || LOG_STEPS[0];

// Payload de la fiche modale — même forme que sur l'accueil
const logToCard = (e) => ({
  id: e.id, title: e.title, img: e.img, video: e.video,
  date: e.subtitle.split(" · ")[1] || "",
  stamp: e.n, role: e.subtitle, desc: e.desc, tags: e.tags, url: e.url || "#",
});

/* ---------- Nav : retour au carnet ---------- */
function LogNav() {
  const [stuck, setStuck] = React.useState(false);
  const [dark, setDark] = React.useState(true);
  React.useEffect(() => {
    const onScroll = () => {
      const y = window.scrollY;
      setStuck(y > 40);
      // Crème tant qu'on est sur la photo de l'en-tête, forest ensuite
      const head = document.querySelector(".vpl-head");
      setDark(y < (head ? head.offsetHeight - 130 : 400));
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, []);
  const cls = `vm-topnav vpl-nav ${dark ? "is-dark" : "is-light"} ` +
              `${stuck ? "is-stuck" : ""} ${stuck && dark ? "is-dark-stuck" : ""}`;
  return (
    <header className={cls}>
      <a className="vpl-back" href={LOG_HOME}>
        <span aria-hidden="true">←</span> Retour au carnet
      </a>
      <span className="vpl-nav-title">
        REGISTRE DES EXPÉDITIONS · 2024 — 2026
      </span>
    </header>
  );
}

/* ---------- Une ligne du registre ---------- */
function LogRow({ e, idx, onOpen, onHover }) {
  const open = () => onOpen(logToCard(e));

  return (
    <li>
      <button
        type="button"
        className="vpl-row"
        aria-label={`Ouvrir la fiche : ${e.title}`}
        onClick={open}
        onMouseEnter={() => onHover(e)}
        onMouseLeave={() => onHover(null)}
        onFocus={() => onHover(e)}
        onBlur={() => onHover(null)}
      >
        <span className="vpl-num">
          N°{String(idx + 1).padStart(2, "0")}
        </span>

        <span className="vpl-thumb" aria-hidden="true">
          <img src={e.img} alt="" loading="lazy" />
        </span>

        <span className="vpl-main">
          <h3 className="vpl-title">{e.title}</h3>
          <span className="vpl-sub">{e.subtitle}</span>
          <ul className="vpl-tags">
            {e.tags.slice(0, 4).map(t => <li key={t}>{t}</li>)}
            {e.tags.length > 4 && <li>+{e.tags.length - 4}</li>}
          </ul>
        </span>

        <span className="vpl-meta">
          <span className="vpl-biome">{e.biome}</span>
          <span className="vpl-mono">{e.durée}</span>
          <span className="vpl-arrow" aria-hidden="true">→</span>
        </span>
      </button>
    </li>
  );
}

/* ---------- Page ---------- */
function ProjectsLogApp() {
  const [open, setOpen] = React.useState(null);
  const [biome, setBiome] = React.useState("TOUS");
  const [preview, setPreview] = React.useState(null);
  const previewRef = React.useRef(null);
  const firstRender = React.useRef(true);

  const steps = biome === "TOUS"
    ? LOG_STEPS
    : LOG_STEPS.filter(e => e.biome === biome);

  // La couverture s'enfonce et s'estompe quand le registre passe par-dessus
  // (même effet que le hero de l'accueil, piloté ici par un simple scroll)
  React.useEffect(() => {
    if (!window.gsap || LOG_REDUCE) return;
    const inner = document.querySelector(".vpl-head-inner");
    if (!inner) return;
    const yTo = gsap.quickTo(inner, "yPercent", { duration: 0.3, ease: "power1.out" });
    const oTo = gsap.quickTo(inner, "opacity", { duration: 0.3, ease: "power1.out" });
    const onScroll = () => {
      const p = Math.min(1, Math.max(0, window.scrollY / (window.innerHeight * 0.9)));
      yTo(-12 * p);
      oTo(1 - 0.75 * p);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  // L'aperçu polaroid suit le curseur (quickTo = fluide, sans re-render)
  React.useEffect(() => {
    if (!window.gsap || !previewRef.current) return;
    const xTo = gsap.quickTo(previewRef.current, "x", { duration: 0.5, ease: "power3" });
    const yTo = gsap.quickTo(previewRef.current, "y", { duration: 0.5, ease: "power3" });
    const move = (ev) => { xTo(ev.clientX + 30); yTo(ev.clientY - 110); };
    window.addEventListener("mousemove", move, { passive: true });
    return () => window.removeEventListener("mousemove", move);
  }, []);

  // Apparition / disparition de l'aperçu
  React.useEffect(() => {
    if (!window.gsap || !previewRef.current) return;
    gsap.to(previewRef.current, {
      autoAlpha: preview ? 1 : 0,
      scale: preview ? 1 : 0.85,
      rotation: preview ? 0 : -5,
      duration: 0.35, ease: "power3.out", overwrite: true,
    });
  }, [preview ? preview.id : null]);

  // Entrée de page + cascade des lignes (rejouée à chaque classement).
  // La révélation au scroll passe par IntersectionObserver (natif) : fiable
  // même sur un saut instantané (ancre, touche Fin), là où un batch
  // ScrollTrigger peut rater des lignes.
  React.useEffect(() => {
    if (!window.gsap || LOG_REDUCE) return;
    if (firstRender.current) {
      firstRender.current = false;
      gsap.from(".vpl-head-kicker, .vpl-head-title, .vpl-head-lead", {
        y: 44, autoAlpha: 0, duration: 0.9, stagger: 0.12, ease: "power4.out",
      });
      // Le polaroid n'est pas animé : il est simplement là dès l'ouverture.
      gsap.from(".vpl-stat", {
        y: 26, autoAlpha: 0, duration: 0.6, stagger: 0.08,
        delay: 0.35, ease: "power3.out",
      });

      const rows = gsap.utils.toArray(".vpl-row");
      gsap.set(rows, { autoAlpha: 0, y: 40 });
      const io = new IntersectionObserver((entries) => {
        entries.filter(en => en.isIntersecting).forEach((en, i) => {
          gsap.to(en.target, {
            autoAlpha: 1, y: 0, duration: 0.7, delay: i * 0.09,
            ease: "power3.out", overwrite: true,
          });
          io.unobserve(en.target);
        });
      }, { rootMargin: "0px 0px -5% 0px" });
      rows.forEach(r => io.observe(r));
    } else {
      gsap.fromTo(".vpl-row",
        { autoAlpha: 0, y: 26 },
        { autoAlpha: 1, y: 0, duration: 0.5, stagger: 0.06,
          ease: "power3.out", overwrite: true, clearProps: "transform" });
    }
  }, [biome]);

  return (
    <>
      <LogNav />

      <header className="vpl-head">
        <div className="vpl-head-inner">
        <div className="vpl-head-kicker">
          <span className="vpl-kicker-dot" aria-hidden="true"></span>
          <span>REGISTRE OUVERT</span>
          <span className="vpl-kicker-sep" aria-hidden="true">/</span>
          <span>2024 — 2026</span>
        </div>

        <div className="vpl-head-top">
          {/* Druk Trial (display) n'a pas les glyphes accentués — comme sur
              l'accueil (« Decouvre »), les textes en display évitent les
              accents ; les textes en mono/body les gardent. */}
          <h1 className="vpl-head-title">
            Le registre<br /><em>des projets.</em>
          </h1>

          {/* Polaroid scotché : le dernier projet, en vitrine sur la couverture */}
          {LOG_LATEST && (
            <button
              type="button"
              className="vpl-polaroid"
              aria-label={`Découvrir le dernier projet : ${LOG_LATEST.title}`}
              onClick={() => setOpen(logToCard(LOG_LATEST))}
            >
              <span className="vpl-pol-tape" aria-hidden="true"></span>
              <span className="vpl-pol-photo">
                {LOG_LATEST.video
                  ? <video src={LOG_LATEST.video} poster={LOG_LATEST.img} autoPlay loop muted playsInline />
                  : <img src={LOG_LATEST.img} alt="" />}
              </span>
              <span className="vpl-pol-cap">
                <span className="vpl-pol-kicker">
                  <span className="vpl-pol-dot" aria-hidden="true"></span>
                  Dernier projet · {LOG_LATEST.subtitle.split(" · ")[1] || LOG_LATEST.biome}
                </span>
                <span className="vpl-pol-title">{LOG_LATEST.title}</span>
                <span className="vpl-pol-cta">
                  Découvrir la fiche <span className="vpl-pol-arrow" aria-hidden="true">→</span>
                </span>
              </span>
            </button>
          )}
        </div>

        <div className="vpl-head-grid">
          <p className="vpl-head-lead">
            Tout ce qui a été gravi depuis 2024 est consigné ici, ligne par
            ligne : l'entreprise, l'agence, les cours et les explorations en
            solo. <strong>Survolez une ligne</strong> pour l'aperçu,
            <strong> cliquez</strong> pour ouvrir la fiche de l'étape.
          </p>
          <dl className="vpl-stats">
            <div className="vpl-stat"><dt>ÉTAPES</dt><dd>{LOG_STEPS.length}</dd></div>
            <div className="vpl-stat"><dt>PÉRIODE</dt><dd>2024 - 2026</dd></div>
          </dl>
        </div>
        </div>
      </header>

      {/* .vpl-body glisse par-dessus la couverture fixe (cf. accueil) */}
      <div className="vpl-body">

      <nav className="vpl-bar" aria-label="Classement du registre">
        <div className="vpl-filters" role="group" aria-label="Filtrer par biome">
          {["TOUS", ...LOG_BIOMES].map(b => {
            const n = b === "TOUS"
              ? LOG_STEPS.length
              : LOG_STEPS.filter(e => e.biome === b).length;
            return (
              <button
                key={b}
                type="button"
                className={`vpl-filter ${biome === b ? "is-on" : ""}`}
                aria-pressed={biome === b}
                onClick={() => setBiome(b)}
              >
                {b}<span className="n">{n}</span>
              </button>
            );
          })}
        </div>
        <span className="vpl-count">
          {steps.length} / {LOG_STEPS.length} ÉTAPES AFFICHÉES
        </span>
      </nav>

      <ul className="vpl-list">
        {steps.map(e => (
          <LogRow
            key={e.id}
            e={e}
            idx={LOG_STEPS.indexOf(e)}
            onOpen={setOpen}
            onHover={setPreview}
          />
        ))}
      </ul>

      <div className="vpl-end">
        <a className="vme-summit vme-summit-link" href={LOG_HOME}>
          <span className="vme-summit-stamp">FIN DU REGISTRE — MERCI !</span>
          <span className="vme-summit-coord">
            <span aria-hidden="true">←</span> Redescendre au camp de base
          </span>
        </a>
      </div>

      </div>{/* /.vpl-body */}

      {/* aperçu polaroid flottant — masqué sur écrans tactiles */}
      <div className="vpl-preview" ref={previewRef} aria-hidden="true">
        <div className="vpl-preview-frame">
          <img src={preview ? preview.img : (LOG_STEPS[0] && LOG_STEPS[0].img)} alt="" />
          <span className="vpl-preview-cap">
            {preview ? `${preview.n} · ${preview.biome}` : ""}
          </span>
        </div>
      </div>

      {open && <ProjectModal project={open} onClose={() => setOpen(null)} />}
    </>
  );
}

ReactDOM.createRoot(document.getElementById("app")).render(<ProjectsLogApp />);
