/* ============================================================
   daystory.jsx — scroll-driven "day in the life" section
   PERF: rendered ONCE, then driven by direct DOM writes in a
   single rAF loop. No React state updates while scrolling.
   ============================================================ */
const { useRef: useDRef, useEffect: useDEffect } = React;

const clamp = (v, a = 0, b = 1) => Math.max(a, Math.min(b, v));
const lerp = (a, b, t) => a + (b - a) * t;
const smooth = (x, a, b) => { const t = clamp((x - a) / (b - a)); return t * t * (3 - 2 * t); };

/* day-sky keyframes (oklch L C H for top & bottom) */
const SKY = [
  { p: 0.00, t: [0.90, 0.05, 250], b: [0.94, 0.06, 75] },
  { p: 0.30, t: [0.78, 0.11, 240], b: [0.92, 0.06, 215] },
  { p: 0.58, t: [0.74, 0.11, 70],  b: [0.86, 0.13, 45] },
  { p: 0.80, t: [0.42, 0.12, 285], b: [0.56, 0.13, 40] },
  { p: 1.00, t: [0.20, 0.06, 272], b: [0.27, 0.06, 280] },
];
function skyAt(p) {
  let i = 0;
  while (i < SKY.length - 2 && p > SKY[i + 1].p) i++;
  const a = SKY[i], b = SKY[i + 1];
  const k = clamp((p - a.p) / (b.p - a.p));
  const mix = (x, y) => x.map((v, j) => lerp(v, y[j], k));
  const top = mix(a.t, b.t), bot = mix(a.b, b.b);
  const css = (c) => `oklch(${c[0].toFixed(3)} ${c[1].toFixed(3)} ${c[2].toFixed(1)})`;
  return `linear-gradient(180deg, ${css(top)} 0%, ${css(bot)} 100%)`;
}

const SCENE_IMG = ["assets/day-01-werf.jpg", "assets/day-02-klant.jpg", "assets/day-03-onderweg.jpg", "assets/day-04-avond.jpg"];

function DayStory({ variant = "cinematic" }) {
  const { t } = window.LU.useLang();
  const { Icon } = window.UI;
  const ref = useDRef(null);
  const scenes = t.story.scenes;
  const minimal = variant === "minimal";
  const cinematic = variant === "cinematic";

  /* ---- the rAF-driven scroll engine (set up once per lang/variant) ---- */
  useDEffect(() => {
    const root = ref.current;
    if (!root) return;
    const q = (s) => root.querySelector(s);
    const qa = (s) => Array.from(root.querySelectorAll(s));

    const stage = q("[data-stage]");
    const blob = q("[data-blob]");
    const eyebrow = q("[data-eyebrow]");
    const eyeDot = q("[data-eyedot]");
    const title = q("[data-title]");
    const photos = qa("[data-photo]");
    const chipWrap = q("[data-chipwrap]");
    const chipBox = q("[data-chip]");
    const chipPlace = q("[data-place]");
    const chipNote = q("[data-note]");
    const cue = q("[data-cue]");
    const cardWrap = q("[data-cardwrap]");
    const card = q("[data-card]");
    const stDot = q("[data-stdot]");
    const stPing = q("[data-stping]");
    const stLabel = q("[data-stlabel]");
    const stTime = q("[data-sttime]");
    const avatar = q("[data-avatar]");
    const icoPhone = q("[data-ico-phone]");
    const icoCheck = q("[data-ico-check]");
    const icoFwd = q("[data-ico-fwd]");
    const ringPulse = q("[data-ringpulse]");
    const num = q("[data-num]");
    const metaText = q("[data-metatext]");
    const metaEq = q("[data-metaeq]");
    const reasonWrap = q("[data-reasonwrap]");
    const reasonText = q("[data-reasontext]");
    const doneRow = q("[data-donerow]");
    const tagEl = q("[data-tag]");
    const doneLabel = q("[data-donelabel]");
    const doneIcoCheck = q("[data-doneico-check]");
    const doneIcoFwd = q("[data-doneico-fwd]");
    const doneText = q("[data-donetext]");
    const finale = q("[data-finale]");
    const arcWrap = q("[data-arcwrap]");
    const sun = q("[data-sun]");
    const sunGlow = q("[data-sunglow]");
    const sunDisc = q("[data-sundisc]");
    const icoSun = q("[data-ico-sun]");
    const icoMoon = q("[data-ico-moon]");
    const counter = q("[data-counter]");
    const arcTrack = q("[data-arctrack]");
    const arcFill = q("[data-arcfill]");
    const arcTicks = qa("[data-tick]");
    const hint = q("[data-hint]");

    const span = 0.86 / scenes.length;
    const startP = 0.07;
    let lastIdx = -1, lastPhase = "", lastNight = null, lastDark = null, lastCaught = -1;
    let raf = 0;

    const setText = (el, v) => { if (el && el.textContent !== v) el.textContent = v; };

    function applyScene(idx) {
      const sc = scenes[idx];
      const fwd = sc.status === "forwarded";
      setText(chipPlace, sc.place);
      setText(chipNote, sc.note);
      setText(stTime, sc.time);
      setText(num, sc.num);
      setText(reasonText, sc.reason);
      setText(tagEl, sc.tag);
      // tag colour
      tagEl.className = "text-[11px] px-2 py-1 rounded-full border font-medium whitespace-nowrap " +
        (fwd ? "bg-destructive/10 text-destructive border-destructive/20" : "bg-teal-soft text-teal border-teal/20");
      // done label colour + icon
      doneLabel.className = "inline-flex items-center gap-1 text-xs font-semibold " + (fwd ? "text-amber" : "text-teal");
      setText(doneText, fwd ? t.story.forwarded : t.story.caught);
      doneIcoCheck.style.display = fwd ? "none" : "";
      doneIcoFwd.style.display = fwd ? "" : "none";
    }

    function applyPhase(phase, idx) {
      const sc = scenes[idx];
      const fwd = sc.status === "forwarded";
      // status label
      setText(stLabel, phase === "ring" ? t.story.incoming : phase === "handling" ? t.story.handling : (fwd ? t.story.forwarded : t.story.caught));
      // status dot colour + ping
      const dotCol = fwd && phase === "done" ? "bg-amber" : "bg-teal";
      stDot.className = "relative inline-flex rounded-full h-1.5 w-1.5 " + dotCol;
      stPing.className = "absolute inline-flex h-full w-full rounded-full " + dotCol + (phase === "ring" ? " ping-soft" : "");
      // avatar
      if (phase === "done") {
        avatar.className = "relative w-11 h-11 rounded-xl grid place-items-center shadow-glow " + (fwd ? "bg-amber text-white" : "bg-teal text-white");
        icoPhone.style.display = "none";
        icoCheck.style.display = fwd ? "none" : "";
        icoFwd.style.display = fwd ? "" : "none";
      } else {
        avatar.className = "relative w-11 h-11 rounded-xl grid place-items-center shadow-glow bg-gradient-brand text-brand-foreground";
        icoPhone.style.display = "";
        icoCheck.style.display = "none";
        icoFwd.style.display = "none";
      }
      ringPulse.style.display = phase === "ring" ? "" : "none";
      // meta: handling => equalizer, else text (logged on done, place otherwise)
      metaEq.style.display = phase === "handling" ? "" : "none";
      metaText.style.display = phase === "handling" ? "none" : "";
      if (phase !== "handling") setText(metaText, phase === "done" ? t.story.logged : sc.place);
    }

    function frame() {
      raf = 0;
      const rect = root.getBoundingClientRect();
      const vh = window.innerHeight;
      const total = rect.height - vh;
      const p = total > 0 ? clamp(-rect.top / total) : 0;

      // sky
      if (!minimal) stage.style.background = skyAt(p);
      const dark = cinematic ? p > 0.66 : false;

      const idx = clamp(Math.floor((p - startP) / span), 0, scenes.length - 1);
      const local = clamp(((p - startP) / span) - idx);
      const isLast = idx === scenes.length - 1;
      const sceneOpacity = isLast ? smooth(local, 0, 0.12) : smooth(local, 0, 0.12) * (1 - smooth(local, 0.9, 1));
      const appear = smooth(local, 0.10, 0.30);
      const phase = local < 0.34 ? "ring" : local < 0.66 ? "handling" : "done";
      const finaleP = smooth(p, 0.9, 0.99);
      const caught = scenes.filter((_, i) => p >= startP + i * span + span * 0.66).length;

      // scene content (only on change)
      if (idx !== lastIdx) { applyScene(idx); lastIdx = idx; lastPhase = ""; }
      if (phase !== lastPhase) { applyPhase(phase, idx); lastPhase = phase; }

      // photo layers
      for (let i = 0; i < photos.length; i++) {
        photos[i].style.opacity = i === idx ? clamp(sceneOpacity + 0.2) : 0;
      }

      // chip + note
      const chipO = clamp(sceneOpacity + 0.2);
      chipWrap.style.opacity = chipO;
      chipWrap.style.transform = `translateY(${lerp(-10, 0, chipO)}px)`;
      // cue
      cue.style.opacity = clamp(sceneOpacity) * (phase === "ring" ? 1 : 0);
      // card
      cardWrap.style.opacity = clamp(sceneOpacity);
      card.style.opacity = appear;
      card.style.transform = `translateY(${lerp(22, 0, appear)}px) scale(${lerp(0.96, 1, appear)})`;
      reasonWrap.style.opacity = local > 0.4 ? 1 : 0;
      doneRow.style.opacity = phase === "done" ? 1 : 0;

      // dark-mode text colours (only on change)
      if (dark !== lastDark) {
        title.style.color = dark ? "#fff" : "oklch(0.18 0.04 264)";
        eyebrow.style.color = dark ? "oklch(0.72 0.13 188)" : "oklch(0.55 0.21 264)";
        eyeDot.style.background = dark ? "oklch(0.72 0.13 188)" : "oklch(0.55 0.21 264)";
        if (blob) blob.style.background = dark ? "oklch(0.55 0.21 264 / 0.4)" : "oklch(1 0 0 / 0.4)";
        arcTrack.style.color = dark ? "#fff" : "oklch(0.18 0.04 264)";
        counter.style.color = dark ? "#fff" : "oklch(0.18 0.04 264)";
        arcTicks.forEach((tk) => { tk.style.color = dark ? "oklch(1 0 0 / 0.6)" : "oklch(0.5 0.03 257)"; });
        lastDark = dark;
      }

      // finale
      finale.style.opacity = finaleP;
      finale.style.display = finaleP > 0.01 ? "" : "none";
      finale.querySelector("[data-finaleinner]").style.transform = `translateY(${lerp(24, 0, finaleP)}px)`;

      // arc
      arcWrap.style.opacity = 1 - finaleP;
      sun.style.left = `${lerp(4, 96, p)}%`;
      arcFill.style.width = `${p * 100}%`;
      const night = p > 0.78;
      if (night !== lastNight) {
        sunGlow.style.background = night ? "oklch(0.85 0.04 250 / 0.5)" : "oklch(0.85 0.16 80 / 0.7)";
        sunDisc.style.background = night ? "oklch(0.92 0.03 250)" : "oklch(0.85 0.16 80)";
        icoSun.style.display = night ? "none" : "";
        icoMoon.style.display = night ? "" : "none";
        lastNight = night;
      }
      if (caught !== lastCaught) { setText(counter, String(caught)); lastCaught = caught; }
      if (hint) hint.style.opacity = p < 0.04 ? 1 : 0;
    }

    const onScroll = () => { if (!raf) raf = requestAnimationFrame(frame); };
    frame();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
    // eslint-disable-next-line
  }, [t, variant]);

  const s0 = scenes[0];
  return (
    <section id="verhaal" ref={ref} style={{ height: "380vh" }} className="relative">
      <div data-stage className="sticky top-0 h-screen overflow-hidden day-sky" style={{ background: minimal ? "oklch(0.985 0.005 250)" : skyAt(0), willChange: "background" }}>
        {!minimal && (
          <>
            <div className="absolute inset-0 grid-bg opacity-[0.06]" />
            <div data-blob className="absolute -top-20 -right-20 w-96 h-96 rounded-full blur-3xl" style={{ background: "oklch(1 0 0 / 0.4)" }} />
          </>
        )}

        <div className="relative h-full mx-auto max-w-7xl px-6 flex flex-col justify-between py-8 sm:py-10">
          {/* header */}
          <div className="text-center">
            <p data-eyebrow className="inline-flex items-center gap-2 text-sm font-semibold" style={{ color: "oklch(0.55 0.21 264)" }}>
              <span data-eyedot className="h-1 w-1 rounded-full" style={{ background: "oklch(0.55 0.21 264)" }} /> {t.story.eye}
            </p>
            <h2 data-title className="mt-2 text-3xl sm:text-5xl font-display font-bold track-tight" style={{ color: "oklch(0.18 0.04 264)" }}>{t.story.h2}</h2>
          </div>

          {/* stage */}
          <div className="relative flex-1 my-6 min-h-0">
            <div className="relative h-full max-w-5xl mx-auto rounded-3xl overflow-hidden border shadow-card" style={{ borderColor: "oklch(0.92 0.012 250)" }}>
              {/* scene photos */}
              {scenes.map((sc, i) => (
                <div key={i} data-photo className="absolute inset-0" style={{ opacity: i === 0 ? 1 : 0, willChange: "opacity" }}>
                  <img src={SCENE_IMG[i]} alt={sc.ph} loading={i === 0 ? "eager" : "lazy"} className="w-full h-full object-cover" draggable="false" />
                </div>
              ))}
              {/* gradient floor */}
              <div className="absolute inset-0 pointer-events-none" style={{ background: "linear-gradient(180deg, oklch(0.1 0.03 264 / 0.1) 0%, transparent 35%, oklch(0.1 0.03 264 / 0.55) 100%)" }} />

              {/* chip + note */}
              <div data-chipwrap className="absolute top-4 left-4 max-w-[55%]" style={{ willChange: "opacity, transform" }}>
                <div data-chip className="inline-flex items-center gap-2 rounded-full pl-3 pr-4 py-1.5 border border-white/15" style={{ background: "oklch(0.16 0.03 264 / 0.72)" }}>
                  <Icon name="map-pin" className="w-3.5 h-3.5 text-teal" />
                  <span data-place className="text-white font-semibold text-xs sm:text-sm truncate">{s0.place}</span>
                </div>
                <p data-note className="mt-2 ml-1 text-white/70 text-xs sm:text-sm max-w-[200px] sm:max-w-xs">{s0.note}</p>
              </div>

              {/* phone-off cue */}
              <div data-cue className="absolute bottom-5 left-5 flex items-center gap-2 text-white/70 text-xs" style={{ opacity: 0 }}>
                <Icon name="phone-off" className="w-4 h-4 text-destructive" /> <span className="font-medium">{t.story.incoming}</span>
              </div>

              {/* call card */}
              <div data-cardwrap className="absolute bottom-4 right-4" style={{ opacity: 0 }}>
                <div data-card className="w-[230px] sm:w-[290px] md:w-[340px] bg-card rounded-2xl border border-border shadow-card overflow-hidden" style={{ willChange: "opacity, transform" }}>
                  <div className="flex items-center justify-between px-4 py-2.5 border-b border-border/70">
                    <div className="flex items-center gap-2 text-[11px] font-semibold text-slate">
                      <span className="relative flex h-1.5 w-1.5">
                        <span data-stping className="absolute inline-flex h-full w-full rounded-full bg-teal ping-soft" />
                        <span data-stdot className="relative inline-flex rounded-full h-1.5 w-1.5 bg-teal" />
                      </span>
                      <span data-stlabel>{t.story.incoming}</span>
                    </div>
                    <span data-sttime className="text-[10px] text-slate tabular">{s0.time}</span>
                  </div>
                  <div className="p-4">
                    <div className="flex items-center gap-3">
                      <div className="relative shrink-0">
                        <span data-ringpulse className="absolute inset-0 rounded-xl bg-brand/30 pulse-ring" />
                        <div data-avatar className="relative w-11 h-11 rounded-xl grid place-items-center shadow-glow bg-gradient-brand text-brand-foreground">
                          <span data-ico-phone><Icon name="phone" className="w-5 h-5" /></span>
                          <span data-ico-check style={{ display: "none" }}><Icon name="check" className="w-5 h-5" /></span>
                          <span data-ico-fwd style={{ display: "none" }}><Icon name="phone-forwarded" className="w-5 h-5" /></span>
                        </div>
                      </div>
                      <div className="min-w-0 flex-1">
                        <p data-num className="font-display font-semibold text-navy leading-tight tabular">{s0.num}</p>
                        <p data-metatext className="text-xs text-slate truncate">{s0.place}</p>
                        <div data-metaeq className="flex items-end gap-0.5 h-4 mt-1" style={{ display: "none" }}>
                          {[0,1,2,3,4,5].map((i) => <span key={i} className="eq-bar w-0.5 rounded-full bg-teal" style={{ animationDelay: `${i*0.1}s`, height: "40%" }} />)}
                        </div>
                      </div>
                    </div>
                    <div data-reasonwrap className="mt-3" style={{ opacity: 0, transition: "opacity .3s" }}>
                      <div className="rounded-xl bg-warm border border-border px-3 py-2.5">
                        <p className="text-[10px] uppercase tracking-widest text-slate font-semibold mb-0.5">{t.mReason}</p>
                        <p data-reasontext className="text-sm text-navy font-medium">{s0.reason}</p>
                      </div>
                    </div>
                    <div data-donerow className="mt-2.5 flex items-center justify-between" style={{ opacity: 0, transition: "opacity .3s" }}>
                      <span data-tag className="text-[11px] px-2 py-1 rounded-full border font-medium whitespace-nowrap bg-teal-soft text-teal border-teal/20">{s0.tag}</span>
                      <span data-donelabel className="inline-flex items-center gap-1 text-xs font-semibold text-teal">
                        <span data-doneico-check><Icon name="check-circle-2" className="w-3.5 h-3.5" /></span>
                        <span data-doneico-fwd style={{ display: "none" }}><Icon name="phone-forwarded" className="w-3.5 h-3.5" /></span>
                        <span data-donetext>{t.story.caught}</span>
                      </span>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            {/* FINALE */}
            <div data-finale className="absolute inset-0 grid place-items-center px-4" style={{ opacity: 0, display: "none" }}>
              <div className="absolute inset-0" style={{ background: "oklch(0.14 0.03 264 / 0.86)" }} />
              <div data-finaleinner className="relative text-center max-w-2xl">
                <p className="inline-flex items-center gap-2 text-sm font-semibold text-teal"><span className="h-1 w-1 rounded-full bg-teal" /> {t.story.finaleEye}</p>
                <h3 className="mt-2 text-4xl sm:text-6xl font-display font-bold text-white track-tight">{t.story.finaleH}</h3>
                <p className="mt-4 text-lg text-white/75 text-pretty">{t.story.finaleSub}</p>
                <div className="mt-8 grid grid-cols-3 gap-3 max-w-lg mx-auto">
                  {t.story.fstats.map(([v, l], i) => (
                    <div key={i} className="rounded-2xl border border-white/12 p-4" style={{ background: "oklch(0.24 0.04 264 / 0.6)" }}>
                      <p className="font-display text-3xl sm:text-4xl text-white font-bold tabular">{v}</p>
                      <p className="text-xs text-white/65 mt-1">{l}</p>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          </div>

          {/* day arc */}
          <div data-arcwrap className="relative">
            <div className="w-full max-w-4xl mx-auto">
              <div className="relative h-14">
                <div data-arctrack className="absolute left-0 right-0 top-1/2 h-px opacity-20" style={{ background: "currentColor", color: "oklch(0.18 0.04 264)" }} />
                <div data-arcfill className="absolute left-0 top-1/2 h-px bg-gradient-brand" style={{ width: "0%" }} />
                <div data-sun className="absolute -translate-x-1/2 -translate-y-1/2 top-1/2" style={{ left: "4%", willChange: "left" }}>
                  <div className="relative grid place-items-center">
                    <span data-sunglow className="absolute w-10 h-10 rounded-full blur-md" style={{ background: "oklch(0.85 0.16 80 / 0.7)" }} />
                    <div data-sundisc className="relative w-7 h-7 rounded-full grid place-items-center shadow-lg" style={{ background: "oklch(0.85 0.16 80)" }}>
                      <span data-ico-sun><Icon name="sun" className="w-4 h-4 text-navy" /></span>
                      <span data-ico-moon style={{ display: "none" }}><Icon name="moon" className="w-4 h-4 text-navy" /></span>
                    </div>
                  </div>
                </div>
              </div>
              <div className="flex justify-between mt-1 px-0.5">
                {["08","11","14","17","20","22"].map((tk) => (
                  <span key={tk} data-tick className="text-[10px] font-medium tabular" style={{ color: "oklch(0.5 0.03 257)" }}>{tk}u</span>
                ))}
              </div>
              <div className="mt-3 flex items-center justify-center gap-2 text-sm font-semibold" style={{ color: "oklch(0.18 0.04 264)" }}>
                <span data-counter className="font-display text-2xl tabular" style={{ color: "inherit" }}>0</span>
                <span className="opacity-70">/ {scenes.length} {(t.story.caught || "").toLowerCase()}</span>
              </div>
            </div>
            <div data-hint className="absolute -top-7 left-1/2 -translate-x-1/2 flex items-center gap-1.5 text-xs text-slate animate-bounce" style={{ opacity: 1 }}>
              <Icon name="arrow-down" className="w-3.5 h-3.5" /> {t.story.hint}
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { DayStory });
