/* ============================================================
   Comportements client (bundlés par Astro).
   Le thème initial est posé AVANT le paint par le script inline
   du <head> (cf. Base.astro) pour éviter tout flash.
   Tout respecte prefers-reduced-motion.
   ============================================================ */

const reduced =
  window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;

/* ---------- Bascule de thème (persistée) ---------- */
function applyTheme(theme: "light" | "dark"): void {
  if (theme === "light") document.documentElement.setAttribute("data-theme", "light");
  else document.documentElement.removeAttribute("data-theme");
  const meta = document.querySelector('meta[name="theme-color"]');
  if (meta) meta.setAttribute("content", theme === "light" ? "#fafafa" : "#09090b");
}
function setupThemeToggle(): void {
  const btn = document.getElementById("theme-toggle");
  if (!btn) return;
  btn.addEventListener("click", () => {
    const isLight = document.documentElement.getAttribute("data-theme") === "light";
    const next = isLight ? "dark" : "light";
    applyTheme(next);
    try { localStorage.setItem("jl-theme", next); } catch {}
  });
}

/* ---------- Effet machine à écrire (mockup terminal) ---------- */
function setupTyping(): void {
  const el = document.getElementById("typed");
  if (!el) return;
  const full = el.textContent ?? ""; // le contenu HTML sert d'état final (no-JS friendly)
  if (reduced) return;               // mouvement réduit : on garde l'état final
  el.textContent = "";
  let i = 0;
  const tick = () => {
    i += 1;
    el.textContent = full.slice(0, i);
    if (i < full.length) {
      const ch = full.charAt(i - 1);
      let d = 16;
      if (ch === "\n") d = 80;
      else if (ch === "{" || ch === "}") d = 40;
      window.setTimeout(tick, d);
    }
  };
  window.setTimeout(tick, 480);
}

/* ---------- Apparition des sections au scroll ---------- */
function setupReveal(): void {
  const els = document.querySelectorAll<HTMLElement>(".reveal");
  if (reduced || !("IntersectionObserver" in window)) {
    els.forEach((el) => el.classList.add("is-visible"));
    return;
  }
  const io = new IntersectionObserver(
    (entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add("is-visible");
          io.unobserve(e.target);
        }
      });
    },
    { threshold: 0.1, rootMargin: "0px 0px -7% 0px" }
  );
  els.forEach((el) => io.observe(el));
}

/* ---------- Surlignage de la nav selon la section visible ---------- */
function setupActiveNav(): void {
  if (!("IntersectionObserver" in window)) return;
  const sections = document.querySelectorAll<HTMLElement>("section[id]");
  const io = new IntersectionObserver(
    (entries) => {
      entries.forEach((e) => {
        if (!e.isIntersecting) return;
        const id = e.target.id;
        document.querySelectorAll<HTMLElement>("[data-nav]").forEach((link) => {
          link.classList.toggle("is-active", link.getAttribute("data-nav") === id);
        });
      });
    },
    { rootMargin: "-45% 0px -50% 0px" }
  );
  sections.forEach((s) => io.observe(s));
}

/* ---------- Menu mobile ---------- */
function setupMobileMenu(): void {
  const burger = document.getElementById("burger");
  const menu = document.getElementById("mobile-menu");
  if (!burger || !menu) return;
  const close = () => {
    menu.classList.remove("is-open");
    burger.setAttribute("aria-expanded", "false");
  };
  burger.addEventListener("click", () => {
    const open = menu.classList.toggle("is-open");
    burger.setAttribute("aria-expanded", open ? "true" : "false");
  });
  menu.querySelectorAll("a").forEach((a) => a.addEventListener("click", close));
  window.addEventListener("resize", () => {
    if (window.innerWidth >= 820) close();
  });
}

function init(): void {
  setupThemeToggle();
  setupTyping();
  setupReveal();
  setupActiveNav();
  setupMobileMenu();
}

if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init);
else init();
