// ============================================================
// SECTION STORY — Scroll-driven 6-phase narrative
// • Photo + text alternating layouts (Bahan Alami / Multimanfaat / Praktis)
// • Hero certification reveal that morphs into "Yojea" + description
// • Final phase: photo slides left, purchase channels appear right
// • Background colors transition between phases via interpolation
// • SVG wave dividers replace flat horizontal section boundaries
// ============================================================

// ─── CircularSeal — a rotating "deal sticker" with curved text ──
// SVG textPath rides a hidden circle so the label loops; the
// outer wrapper spins via CSS using --spin (duration) and --dir.
function CircularSeal({ label, main, sub, style, color, bg }) {
  const id = React.useId();
  return (
    <div className="story-seal" style={style}>
      <svg className="story-seal-svg" viewBox="0 0 200 200">
        <defs>
          <path
            id={'sealpath-' + id}
            d="M 100,100 m -78,0 a 78,78 0 1,1 156,0 a 78,78 0 1,1 -156,0"
            fill="none"
          />
        </defs>
        <circle cx="100" cy="100" r="92" fill={bg} stroke={color} strokeOpacity="0.18" strokeWidth="1" />
        <circle cx="100" cy="100" r="58" fill="none" stroke={color} strokeOpacity="0.20" strokeWidth="1" strokeDasharray="2 3" />
        <text fill={color} fontFamily="ui-monospace, 'JetBrains Mono', monospace" fontSize="13" fontWeight="700" letterSpacing="2">
          <textPath href={'#sealpath-' + id} startOffset="0">
            {label} {label}
          </textPath>
        </text>
      </svg>
      <div className="story-seal-core" style={{ color }}>
        <span className="story-seal-main">{main}</span>
        <span className="story-seal-sub">{sub}</span>
      </div>
    </div>
  );
}

function SectionStory() {
  const sectionRef = React.useRef(null);
  const buyRef = React.useRef(null);
  const [progress, setProgress] = React.useState(0);   // 0..1 across full scroll
  const [isMobile, setIsMobile] = React.useState(false);
  const [buyH, setBuyH] = React.useState(300);          // measured buy-box height (mobile seal anchor)

  // ─── Mobile flag (collapses some layouts to single column) ──
  React.useEffect(() => {
    const mq = window.matchMedia('(max-width: 760px)');
    const update = () => setIsMobile(mq.matches);
    update();
    if (mq.addEventListener) mq.addEventListener('change', update);
    else mq.addListener(update);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', update);
      else mq.removeListener(update);
    };
  }, []);

  // ─── Measure the buy box so mobile seals sit just above it ───
  React.useEffect(() => {
    if (!isMobile) return;
    const measure = () => {
      if (buyRef.current) setBuyH(buyRef.current.offsetHeight || 300);
    };
    measure();
    window.addEventListener('resize', measure);
    const t = setTimeout(measure, 400);   // after fonts/layout settle
    return () => { window.removeEventListener('resize', measure); clearTimeout(t); };
  }, [isMobile]);

  // ─── Scroll progress — drives every phase, computed via rAF ──
  React.useEffect(() => {
    let raf = 0;
    const compute = () => {
      raf = 0;
      if (!sectionRef.current) return;
      const rect = sectionRef.current.getBoundingClientRect();
      const total = rect.height - window.innerHeight;
      if (total <= 0) { setProgress(0); return; }
      const p = Math.max(0, Math.min(1, -rect.top / total));
      setProgress(p);
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(compute); };
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll, { passive: true });
    compute();
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);

  // ─── Phase math ──────────────────────────────────────────────
  // 6 phases evenly distributed across progress (0..1).
  // For each phase we compute "presence" — how fully visible it is
  // (peaks at the center of its scroll window, fades at edges).
  const PHASE_COUNT = 5;
  const phaseLocal = (i) => {
    // 0..1 within this phase's own scroll range
    const span = 1 / PHASE_COUNT;
    return Math.max(0, Math.min(1, (progress - i * span) / span));
  };
  // Bell curve: 0 at edges, 1 in the middle 30-70% of the phase
  const presence = (i) => {
    const t = phaseLocal(i);
    if (t <= 0 || t >= 1) return 0;
    // Smooth in/out with a 25% ramp on each side
    if (t < 0.25) return t / 0.25;
    if (t > 0.75) return (1 - t) / 0.25;
    return 1;
  };

  // ─── Background color interpolation ──────────────────────────
  // 6 stops, one per phase. Smooth crossfade based on progress.
  const BG_STOPS = [
    '#F4ECDD',  // 0 — Bahan Alami: warm cream
    '#EAD9C0',  // 1 — Multimanfaat: deeper cream
    '#F0E1CB',  // 2 — Praktis: peachy beige
    '#E8D5BC',  // 3 — Photo right: warm sand (matches photo 5 bg)
    '#F1E1C8',  // 4 — Bingung Beli: slightly lighter to lift CTA
  ];
  const bgColor = (() => {
    const t = progress * (BG_STOPS.length - 1);
    const i = Math.min(BG_STOPS.length - 2, Math.floor(t));
    const local = t - i;
    return mixHex(BG_STOPS[i], BG_STOPS[i + 1], local);
  })();

  // ─── Phase data (first 3 alternating photo/text rows) ────────
  const ROWS = [
    {
      img: 'assets/story-natural.webp',
      side: 'left',
      kicker: '01 · Filosofi',
      title: ['Bahan', 'Alami'],
      body: 'Diramu dari bahan-bahan herbal Indonesia pilihan. Persis seperti racikan nenek dulu, hanya saja lebih bersih dan terstandar.',
    },
    {
      img: 'assets/story-multi.webp',
      side: 'right',
      kicker: '02 · Manfaat',
      title: ['Multi', 'manfaat'],
      body: 'Satu sachet, banyak manfaat. Membantu meredakan nyeri haid, menjaga keseimbangan hormon, mengurangi keputihan, dan mendukung kesehatan kulit dari dalam.',
    },
    {
      img: 'assets/story-praktis.webp',
      side: 'left',
      kicker: '03 · Ritual',
      title: ['', 'Praktis'],
      body: 'Tidak perlu rebus, tidak perlu saring. Cukup sobek, minum. Cocok untuk wanita modern yang aktif — kapan saja, di mana saja.',
    },
  ];

  // ─── Phase 3-5 (cert hero, morph, buy where) ─────────────────
  const certPresence  = presence(3);
  const buyPresence   = presence(4);
  // Photo 5 stays mounted from phase 3 onward and morphs across the
  // sub-range (3/6 .. 6/6 of total). The photo travels:
  //   Phase 4 — centered low | Phase 5 — RIGHT | Phase 6 — LEFT
  // so the Teruji text (left, persisting from phase 4 through phase 5)
  // gets clear space, then in phase 6 the buy block + seals take over.
  const certStart = 3 / PHASE_COUNT;
  const certEnd   = 1.0;
  const cP = Math.max(0, Math.min(1, (progress - certStart) / (certEnd - certStart)));
  let photoX = 50;        // % from left
  let photoScale = 1.0;   // scale multiplier
  let photoY = 60;        // % from top (anchored bottom-ish)
  // Speed-up: phase 4 holds the photo for part of cP, then transitions
  // into phase 5. On MOBILE the hand-off happens earlier (0.5) so the
  // photo lift, buy block, and seals all animate in together cleanly.
  const SWEEP_AT = isMobile ? 0.5 : 0.7;
  if (cP < SWEEP_AT) {
    // Phase 4 — photo holds on the RIGHT. Slight drift + zoom for life.
    const local = cP / SWEEP_AT;
    photoX = isMobile ? 50 : (70 + local * 2);   // 70% → 72%
    photoY = 60;
    photoScale = 1.0 + local * 0.02;
  } else {
    // Phase 5 — quick sweep across to the LEFT, scaling slightly down so
    // the buy block (right) has visual breathing room. The sweep COMPLETES
    // by SWEEP_END (before the section ends) and then HOLDS fully-left, so
    // there's a stable "fully moved, no phase-4 text" zone for the Beli
    // Sekarang button to land in while content is still pinned.
    const SWEEP_END = SWEEP_AT + (1 - SWEEP_AT) * 0.62;   // desktop ≈ 0.886
    const local = Math.min(1, (cP - SWEEP_AT) / (SWEEP_END - SWEEP_AT));
    // ease-out so motion is fast at start and settles
    const eased = 1 - Math.pow(1 - local, 2);
    photoX = 72 - eased * (isMobile ? 22 : 38);
    photoY = 62 + eased * (isMobile ? 6 : 0);
    photoScale = 1.02 - eased * (isMobile ? 0.22 : 0.08);
  }

  // ─── Photo inline style ─────────────────────────────────────
  // DESKTOP: photo travels right→left (top/left/scale interpolated above).
  // MOBILE: photo is centred & anchored to the BOTTOM. In phase 4 it stands
  //   big at the bottom and rises in from below; in phase 5 it lifts UP so
  //   the "cara beli" block has room beneath it.
  let photoInlineStyle;
  if (isMobile) {
    // Rise-in entrance over the first slice of the finale.
    const riseIn = Math.max(0, 1 - cP / 0.12);   // 1 → 0
    const riseY = riseIn * 110;                   // px up-from-below
    let bottomPct = 0;                            // glued to bottom in phase 4
    let mScale = 1.0;
    if (cP >= SWEEP_AT) {
      const local = (cP - SWEEP_AT) / (1 - SWEEP_AT);
      const eased = 1 - Math.pow(1 - local, 2);
      // Lift just enough that her feet land on TOP of the buy box (which
      // sits ~32% up from the bottom on phones). Less shrink so she stays
      // big and clearly "stands on" the box rather than floating.
      bottomPct = eased * 33;
      mScale = 1.0 - eased * 0.06;
    }
    photoInlineStyle = {
      left: '50%',
      bottom: bottomPct + '%',
      top: 'auto',
      transform: `translate(-50%, ${riseY}px) scale(${mScale})`,
      opacity: 1 - riseIn * 0.95,
    };
  } else {
    photoInlineStyle = {
      left: photoX + '%',
      top: photoY + '%',
      transform: `translate(-50%, -50%) scale(${photoScale})`,
    };
  }

  // Phase 4 "Teruji & Tersertifikasi" overlay — visible only while photo
  // is on the right (before the sweep). Fades in/out with certPresence;
  // positioned on the LEFT so it doesn't fight the photo on the right.
  const certOverlayOpacity = cP < SWEEP_AT
    ? Math.min(1, certPresence * 1.0)
    : Math.max(0, 1 - (cP - SWEEP_AT) / (1 - SWEEP_AT) * 2);

  // ─── Certification seal positions ───────────────────────────
  // DESKTOP: stacked vertically on the left over the photo.
  // MOBILE: small, tight, in a single horizontal row near the top.
  const sealStyles = isMobile
    ? [
        { top: 'auto', bottom: (buyH + 28) + 'px', left: '15%', width: 64, height: 64, '--spin': '14s' },
        { top: 'auto', bottom: (buyH + 28) + 'px', left: '38%', width: 64, height: 64, '--spin': '11s', '--dir': 'reverse' },
        { top: 'auto', bottom: (buyH + 28) + 'px', left: '61%', width: 64, height: 64, '--spin': '16s' },
      ]
    : [
        { top: '22%', left: '4%', width: 120, height: 120, '--spin': '14s' },
        { top: '42%', left: '4%', width: 120, height: 120, '--spin': '11s', '--dir': 'reverse' },
        { top: '62%', left: '4%', width: 120, height: 120, '--spin': '16s' },
      ];

  // ─── Purchase channels ───────────────────────────────────────
  const CHANNELS = [
    {
      key: 'tokopedia',
      label: 'Tokopedia',
      sub: 'Yojea Official Store',
      color: '#02AC4F',
      href: 'https://www.tokopedia.com/yojeaindonesia/jamu-modern-khusus-wanita-ampuh-mengatasi-keputihan-siklus-tidak-lancar-dan-nyeri-haid-1730831920192980029',
      icon: (
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path d="M4 7l8-4 8 4v10l-8 4-8-4V7z" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
          <path d="M4 7l8 4 8-4M12 11v10" stroke="currentColor" strokeWidth="1.6"/>
        </svg>
      ),
    },
    {
      key: 'shopee',
      label: 'Shopee',
      sub: 'Yojea Indonesia',
      color: '#EE4D2D',
      href: 'https://shopee.co.id/product/1361327312/44651499746',
      icon: (
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path d="M5 8h14l-1.2 11.2A2 2 0 0 1 15.8 21H8.2a2 2 0 0 1-2-1.8L5 8z" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
          <path d="M9 8a3 3 0 1 1 6 0" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
        </svg>
      ),
    },
    {
      key: 'tiktok',
      label: 'TikTok Shop',
      sub: '@yojea.id',
      color: '#1F1612',
      href: 'https://vt.tokopedia.com/t/ZS9YEUtpYtaWs-JzrXk/',
      icon: (
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path d="M14 3v11.5a3.5 3.5 0 1 1-3.5-3.5h.5V8.5h-.5A6.5 6.5 0 1 0 17 15V8.4a6.7 6.7 0 0 0 4 1.3V6.6A4.6 4.6 0 0 1 17 3h-3z" fill="currentColor"/>
        </svg>
      ),
    },
    {
      key: 'web',
      featured: true,
      label: 'Web Yojea',
      sub: 'Dapatkan harga terbaik!',
      marquee: 'Beli di website lebih hemat karena tidak terkena biaya administrasi.',
      reveal: 'Dapatkan Yojea Dengan Harga Paling Hemat!',
      color: '#C8612B',
      href: 'https://yojea.id/checkout/',
      icon: (
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="1.6"/>
          <path d="M3 12h18M12 3c2.5 2.4 3.9 5.6 4 9-.1 3.4-1.5 6.6-4 9-2.5-2.4-3.9-5.6-4-9 .1-3.4 1.5-6.6 4-9z" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
        </svg>
      ),
    },
  ];

  return (
    <section
      ref={sectionRef}
      className="story"
      id="story"
      style={{ '--story-bg': bgColor }}
    >
      {/* Top wave divider — organic transition from the previous section */}
      <div className="story-divider story-divider-top" aria-hidden="true">
        <svg viewBox="0 0 1440 120" preserveAspectRatio="none">
          <path d="M0,60 C240,110 480,10 720,40 C960,70 1200,120 1440,80 L1440,0 L0,0 Z" fill="currentColor"/>
        </svg>
      </div>

      <div className="story-sticky">
        {/* ─── Phases 1-3: photo + text alternating ─────────── */}
        {ROWS.map((row, i) => {
          const p = presence(i);
          const local = phaseLocal(i);
          // Direction: slide image in from its side, text from opposite
          const imgFrom = row.side === 'left' ? -60 : 60;
          const txtFrom = row.side === 'left' ? 60 : -60;
          // Subtle parallax once peak presence is reached
          const drift = (local - 0.5) * 20;
          return (
            <div
              key={row.kicker}
              className={'story-row story-row-' + row.side}
              style={{
                opacity: p,
                pointerEvents: p > 0.5 ? 'auto' : 'none',
              }}
              aria-hidden={p < 0.5}
            >
              <div
                className="story-row-img"
                style={{
                  transform: `translate(${imgFrom * (1 - p)}px, ${drift}px)`,
                }}
              >
                <img src={row.img} alt={row.title.filter(Boolean).join(' ')} loading="lazy" />
                <span className="story-row-img-tag">{row.kicker}</span>
              </div>
              <div
                className="story-row-text"
                style={{
                  transform: `translate(${txtFrom * (1 - p)}px, ${-drift * 0.6}px)`,
                }}
              >
                <span className="story-row-kicker">{row.kicker}</span>
                <h2 className="story-row-title">
                  {row.title[0] && <>{row.title[0]}<br/></>}
                  <em>{row.title[1]}</em>
                </h2>
                <p className="story-row-body">{row.body}</p>
              </div>
            </div>
          );
        })}

        {/* ─── Phase 4-6: shared photo 5 that morphs ────────── */}
        {(certPresence > 0 || buyPresence > 0 || cP > 0) && (
          <div className="story-finale" aria-hidden={cP <= 0}>
            {/* Photo (stays mounted, transforms via inline style) */}
            <div
              className="story-cert-img"
              style={photoInlineStyle}
            >
              <img src="assets/story-cert.webp" alt="Yojea — Teruji dan Tersertifikasi" loading="lazy" />
              {/* Soft warm halo so the cut-out photo grounds in the bg */}
              <span className="story-cert-halo" aria-hidden="true" />
            </div>

            {/* Phase 4 — "Teruji & Tersertifikasi" overlay on LEFT while
                 the photo sits on the RIGHT. Fades out as cP crosses 0.5
                 (transition into the brand/buy phase). */}
            <div
              className="story-cert-overlay"
              style={{ opacity: certOverlayOpacity }}
              aria-hidden={certOverlayOpacity < 0.1}
            >
              <span className="story-cert-eyebrow">
                <span className="story-cert-dot" />
                04 · Kualitas
              </span>
              <h2 className="story-cert-title">
                Teruji &amp;<br/>
                <em>Tersertifikasi.</em>
              </h2>
              <div className="story-cert-stamps">
                <span className="story-cert-stamp">BPOM</span>
                <span className="story-cert-stamp">Halal MUI</span>
                <span className="story-cert-stamp">Lab Tested</span>
              </div>
            </div>

            {/* (Phase 5 brand block — "Yojea" + tagline — removed per spec) */}

            {/* Phase 5 — Spinning certification seals overlay the photo */}
            <div
              className="story-seals"
              style={{
                opacity: cP < 0.50 ? 0 :
                         cP < 0.62 ? (cP - 0.50) / 0.12 : 1,
                pointerEvents: 'none',
              }}
              aria-hidden={cP < 0.50}
            >
              <CircularSeal
                label="★ TERDAFTAR BPOM · TERDAFTAR BPOM ·"
                main="BPOM"
                sub="TR246062651"
                style={sealStyles[0]}
                color="#1F1612"
                bg="#fff"
              />
              <CircularSeal
                label="★ HALAL MUI · SERTIFIKASI HALAL ·"
                main="HALAL"
                sub="MUI Cert."
                style={sealStyles[1]}
                color="#fff"
                bg="#0C7A3E"
              />
              <CircularSeal
                label="★ LAB TESTED 2025 · SIG ·"
                main="LAB"
                sub="Tested 2025"
                style={sealStyles[2]}
                color="#fff"
                bg="#C84A14"
              />
            </div>

            {/* Phase 5 — "Bingung Beli Yojea Dimana?" + buy channels */}
            <div
              className="story-buy"
              ref={buyRef}
              style={{
                opacity: cP < 0.50 ? 0 :
                         cP < 0.62 ? (cP - 0.50) / 0.12 : 1,
                transform: `translateX(${cP < 0.62 ? 30 - Math.min(1, (cP - 0.50) / 0.12) * 30 : 0}px)`,
                pointerEvents: cP >= 0.56 ? 'auto' : 'none',
              }}
            >
              <span className="story-buy-eyebrow">
                <span className="story-buy-line" /> Beli Yojea
              </span>
              <h2 className="story-buy-title">
                Bingung beli Yojea <em>di mana?</em>
              </h2>
              <p className="story-buy-sub">
                Kamu bisa beli Yojea melalui distributor resmi dan platform e-commerce digital favorit kamu.
              </p>
              <div className="story-buy-grid">
                {CHANNELS.map((c) => (
                  <a
                    key={c.key}
                    href={c.href}
                    target="_blank"
                    rel="noopener noreferrer"
                    className={'story-buy-card' + (c.featured ? ' story-buy-card--featured' : '')}
                    style={{ '--ch-color': c.color }}
                  >
                    {c.featured && <span className="story-buy-shine" aria-hidden="true" />}
                    {c.reveal && (
                      <span className="story-buy-reveal" aria-hidden="true">{c.reveal}</span>
                    )}
                    <span className="story-buy-card-icon">{c.icon}</span>
                    <span className="story-buy-card-text">
                      <span className="story-buy-card-label">
                        {c.label}
                        {c.featured && <span className="story-buy-badge">Hemat</span>}
                      </span>
                      <span className="story-buy-card-sub">{c.sub}</span>
                    </span>
                    <span className="story-buy-card-arrow" aria-hidden="true">
                      <svg viewBox="0 0 16 16" fill="none">
                        <path d="M5 3l5 5-5 5M3 8h7" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
                      </svg>
                    </span>
                    {c.marquee && (
                      <span className="story-buy-marquee" aria-hidden="true">
                        <span className="story-buy-marquee-track">
                          <span>{c.marquee}</span>
                          <span>{c.marquee}</span>
                          <span>{c.marquee}</span>
                          <span>{c.marquee}</span>
                        </span>
                      </span>
                    )}
                  </a>
                ))}
              </div>
            </div>
          </div>
        )}

        {/* Phase rail — small indicator showing progress through 6 phases */}
        <div className="story-rail" aria-hidden="true">
          {Array.from({ length: PHASE_COUNT }).map((_, i) => {
            const active = progress >= i / PHASE_COUNT && progress < (i + 1) / PHASE_COUNT;
            const passed = progress >= (i + 1) / PHASE_COUNT;
            return (
              <span
                key={i}
                className={'story-rail-dot' + (active ? ' is-active' : '') + (passed ? ' is-passed' : '')}
              >
                <span className="story-rail-num">{String(i + 1).padStart(2, '0')}</span>
              </span>
            );
          })}
        </div>
      </div>

      {/* Bottom wave divider — into the next section */}
      <div className="story-divider story-divider-bottom" aria-hidden="true">
        <svg viewBox="0 0 1440 120" preserveAspectRatio="none">
          <path d="M0,40 C240,0 480,100 720,70 C960,40 1200,0 1440,50 L1440,120 L0,120 Z" fill="currentColor"/>
        </svg>
      </div>
    </section>
  );
}

// ─── Helper: interpolate between two hex colors ───────────────
function mixHex(a, b, t) {
  const pa = parseInt(a.slice(1), 16);
  const pb = parseInt(b.slice(1), 16);
  const ar = (pa >> 16) & 0xff, ag = (pa >> 8) & 0xff, ab = pa & 0xff;
  const br = (pb >> 16) & 0xff, bg = (pb >> 8) & 0xff, bb = pb & 0xff;
  const r = Math.round(ar + (br - ar) * t);
  const g = Math.round(ag + (bg - ag) * t);
  const b2 = Math.round(ab + (bb - ab) * t);
  return '#' + ((1 << 24) | (r << 16) | (g << 8) | b2).toString(16).slice(1);
}

Object.assign(window, { SectionStory, CircularSeal });
