// sections-top.jsx — Hero, About, Services, MoreThanTraffic
// All strings come from i18n via t(key). Pass t down from App.

// Small icon set used by service/mtt bullet rows. Cycles by row index
// so each bullet picks up a glyph in the reference style.
// Single icon for every bullet across Services + MTT: the 6px purple dot —
// the only "icon" the brand allows. The `i` prop is kept so existing call
// sites don't need to change; we just ignore it now.
function RowIcon() {
  return <span className="row-icon row-dot" aria-hidden="true" />;
}

// Single phone with a vertically auto-scrolling reel of creative thumbs.
// Replaces the old PhoneMockup in the Creatives section. The reel is purely
// CSS-animated, hovering pauses, and no turquoise/green appears inside
// (turquoise is reserved for the CTA pill elsewhere).
function ReelMockup() {
  const reel = [
    { tag: "PLAYABLE", title: "Tap to spin",         body: "iGaming · 0:15", bg: "#3a2a5a", w: "62%" },
    { tag: "VIDEO",    title: "First win, ten seconds", body: "Crypto · 0:10", bg: "#1a3052", w: "44%" },
    { tag: "STATIC",   title: "30M+ users",          body: "Fintech · ROAS 240%", bg: "#451a45", w: "78%" },
    { tag: "VIDEO",    title: "Live trading reel",   body: "Ecom · 0:20",    bg: "#1f3a32", w: "55%" },
    { tag: "PLAYABLE", title: "Build & deploy",      body: "Mobile · 0:18",  bg: "#3a3625", w: "33%" },
  ];
  return (
    <div className="reel-wrap" aria-hidden="true">
      <div className="reel-phone">
        <div className="reel-notch" />
        <div className="reel-screen">
          <div className="reel-track">
            {[...reel, ...reel].map((c, i) => (
              <div className="reel-card" style={{ "--bg": c.bg }} key={i}>
                <span className="reel-tag">{c.tag}</span>
                <div className="reel-meta">
                  <div className="reel-title">{c.title}</div>
                  <div className="reel-body">{c.body}</div>
                  <div className="reel-bar"><i style={{ width: c.w }} /></div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// (No AnimatedNum component — KpiDashMockup drives counter ticks directly
// via DOM refs in its play-effect to avoid any React state propagation
// issues inside the Babel-standalone iframe preview.)

// Mini KPI dashboard alongside a live creative on a phone — "perf marketing
// in real time". Replaces the older ReelMockup for the Creatives block.
// The phone loops one of the real case-library mp4s muted; the panel shows
// three KPI tiles + a 7-day conversion sparkline. All numbers tick up and
// the chart line draws in once the block enters the viewport.
function KpiDashMockup() {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const root = ref.current;
    if (!root) return;
    let cancelled = false;
    let started = false;
    // Tile spec — duplicated here for the DOM-driven tick. textContent is
    // written into <span data-num> spans below.
    const tiles = [
      { sel: '[data-k="ctr"]', target: 4.2,  pre: "",  suf: "%" },
      { sel: '[data-k="cpi"]', target: 1.80, pre: "$", suf: "" },
      { sel: '[data-k="cvr"]', target: 12,   pre: "",  suf: "%" },
    ];

    const start = () => {
      if (started) return; started = true;
      root.classList.add("is-playing");
      // Manually drive SVG stroke-dashoffset + opacity via setInterval —
      // CSS transitions on SVG presentation attributes don't fire
      // reliably inside the preview iframe.
      const lineEl = root.querySelector(".kpi-chart-line");
      const fillEl = root.querySelector(".kpi-chart-fill");
      const dotEls = root.querySelectorAll(".kpi-chart-dot");
      const lineDur = 1800;
      const t0 = Date.now();
      const lineId = setInterval(() => {
        if (cancelled) { clearInterval(lineId); return; }
        const p = Math.min(1, (Date.now() - t0) / lineDur);
        const ease = 1 - Math.pow(1 - p, 3);
        if (lineEl) lineEl.setAttribute("stroke-dashoffset", String(600 - 600 * ease));
        if (fillEl) fillEl.setAttribute("opacity", String(p > 0.3 ? (p - 0.3) / 0.7 : 0));
        dotEls.forEach((d, i) => {
          const dotStart = 0.3 + i * 0.05;
          const dotP = Math.max(0, Math.min(1, (p - dotStart) / 0.15));
          d.setAttribute("opacity", String(dotP));
          d.style.transform = `scale(${0.4 + 0.6 * dotP})`;
          d.style.transformOrigin = "center";
        });
        if (p >= 1) clearInterval(lineId);
      }, 33);
      const dur = 1600;
      const step = 30; // ms — ~33 frames per animation
      const easeOut = (t) => 1 - Math.pow(1 - t, 3);
      let elapsed = 0;
      const id = setInterval(() => {
        if (cancelled) { clearInterval(id); return; }
        elapsed += step;
        const p = Math.min(1, elapsed / dur);
        const e = easeOut(p);
        tiles.forEach(t => {
          const el = root.querySelector(t.sel);
          if (!el) return;
          const v = e * t.target;
          const text = Number.isInteger(t.target)
            ? String(Math.round(v))
            : v.toFixed(2);
          el.textContent = t.pre + text + t.suf;
        });
        if (p >= 1) clearInterval(id);
      }, step);
    };

    // Poll until the mockup is in view, then start once.
    const check = () => {
      if (cancelled || started) return;
      const r = root.getBoundingClientRect();
      if (r.top < window.innerHeight * 0.85 && r.bottom > 0) start();
      else setTimeout(check, 200);
    };
    check();
    return () => { cancelled = true; };
  }, []);

  const tiles = [
    { label: "CTR", key: "ctr", initial: "0%",  delta: "+0.6 pp" },
    { label: "CPI", key: "cpi", initial: "$0",  delta: "-12%"    },
    { label: "CVR", key: "cvr", initial: "0%",  delta: "+1.8 pp" },
  ];
  const linePts = [[0,92],[40,80],[80,76],[120,60],[160,66],[200,46],[240,50],[280,30],[320,20],[360,12]];
  const pathD = linePts.map((p,i) => `${i===0?'M':'L'} ${p[0]} ${p[1]}`).join(' ');
  const fillD = `${pathD} L 360 120 L 0 120 Z`;
  return (
    <div className="kpi-mockup" ref={ref} aria-hidden="true">
      <div className="kpi-panel">
        <div className="kpi-row">
          {tiles.map(t => (
            <div className="kpi-tile" key={t.label}>
              <div className="kpi-tile-label">{t.label}</div>
              <div className="kpi-tile-value">
                <span data-k={t.key}>{t.initial}</span>
              </div>
              <div className="kpi-tile-delta">{t.delta}</div>
            </div>
          ))}
        </div>
        <div className="kpi-chart">
          <div className="kpi-chart-head">
            <div className="kpi-chart-title">Conversions · last 7 days</div>
            <div className="kpi-chart-meta">+18% WoW</div>
          </div>
          <div className="kpi-chart-stage">
            <svg className="kpi-chart-svg" viewBox="0 0 360 120" preserveAspectRatio="none">
              <defs>
                <linearGradient id="kpi-fill" x1="0" y1="0" x2="0" y2="1">
                  <stop offset="0%" stopColor="#7a4ee0" stopOpacity="0.36"/>
                  <stop offset="100%" stopColor="#7a4ee0" stopOpacity="0"/>
                </linearGradient>
              </defs>
              {/* horizontal grid lines */}
              {[0,30,60,90].map(y => (
                <line key={y} x1="0" x2="360" y1={y+15} y2={y+15}
                      stroke="rgba(255,255,255,0.06)" strokeWidth="1"/>
              ))}
              {/* Filled gradient — fades in with the line */}
              <path className="kpi-chart-fill" d={fillD} fill="url(#kpi-fill)" />
              {/* Stroke path — animated via stroke-dasharray. */}
              <path className="kpi-chart-line" d={pathD} stroke="#7a4ee0"
                    strokeWidth="2" fill="none" strokeLinecap="round"
                    strokeLinejoin="round" />
              {/* Dots inside SVG — share the same coordinate system as the line,
                  eliminating any alignment drift when the chart is resized. */}
              {linePts.map((p, i) => (
                <circle key={i} className="kpi-chart-dot"
                  cx={p[0]} cy={p[1]} r="4" style={{ "--i": i }} />
              ))}
            </svg>
          </div>
        </div>
      </div>
    </div>
  );
}

// CSS-3D phone mockup with a tiny ad + stats UI inside.
// Lives inside Creatives as a feature decoration on the right.
function PhoneMockup() {
  return (
    <div className="mtt-phone-wrap" aria-hidden="true">
      <div className="phone3d">
        <div className="phone-frame">
          <div className="phone-notch" />
          <div className="phone-screen">
            <div className="phone-ad">
              <div className="phone-ad-tag">SPONSORED · IN-APP</div>
              <div className="phone-ad-title">Win Big Every<br/>Day — Install Now</div>
              <button type="button" className="phone-ad-btn">Install Free</button>
            </div>
            <div className="phone-stats">
              <div className="phone-stat"><span>4.2%</span><em>CTR</em></div>
              <div className="phone-stat"><span>$1.8</span><em>CPI</em></div>
              <div className="phone-stat"><span>12%</span><em>CVR</em></div>
            </div>
            <div className="phone-progress"><i /></div>
            <div className="phone-bars">
              <i style={{ "--h": "40%" }} />
              <i style={{ "--h": "58%" }} />
              <i style={{ "--h": "72%" }} className="acc" />
              <i style={{ "--h": "48%" }} />
              <i style={{ "--h": "88%" }} />
              <i style={{ "--h": "96%" }} />
            </div>
          </div>
        </div>
        <div className="phone-shadow" />
      </div>
      <div className="mtt-phone-caption">
        <strong>In-App</strong> <span>· performance · real installs</span>
      </div>
    </div>
  );
}

function Hero({ t, onLeaveRequest }) {
  // Scroll parallax: after entrance anims complete, content drifts up + fades out
  React.useEffect(() => {
    const hero = document.getElementById("hero");
    if (!hero) return;
    let raf = null;
    let ready = false;
    const timer = setTimeout(() => { ready = true; }, 1400);
    const onScroll = () => {
      if (!ready) return;
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        const h = hero.offsetHeight;
        const p = Math.min(1, window.scrollY / h);
        const inner = hero.querySelector(".hero-inner");
        const video = hero.querySelector(".hero-video");
        if (inner) {
          inner.style.transform = `translateY(${p * 72}px)`;
          inner.style.opacity = String(Math.max(0, 1 - p * 1.75));
        }
        if (video) video.style.transform = `scale(${1 + p * 0.08})`;
      });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => {
      clearTimeout(timer);
      cancelAnimationFrame(raf);
      window.removeEventListener("scroll", onScroll);
    };
  }, []);

  // Threshold-based exit fade for all sections except hero.
  // Uses bottom < 0 so tall sections (case library) don't fade while user is still inside them.
  React.useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (!entry.isIntersecting && entry.boundingClientRect.bottom < 0) {
          entry.target.classList.add("section-exited");
        } else {
          entry.target.classList.remove("section-exited");
        }
      });
    }, { threshold: 0 });
    document.querySelectorAll("section:not(#hero)").forEach(sec => observer.observe(sec));
    return () => observer.disconnect();
  }, []);

  // Word-by-word reveal — split the title at <br/> and within each line, by words.
  // The h1 carries class .hero-title; child spans carry .hw with --i for stagger.
  const title = t("hero.title"); // contains <em> + <br/>
  // Build an array of token nodes. Keep <em> markers intact.
  const buildLine = (line, lineIdx) => {
    // Replace <em>…</em> wrappers with sentinels, split words, restore em on chunks.
    const parts = line.split(/(<em>.*?<\/em>)/g).filter(Boolean);
    let wordIdx = 0;
    return parts.map((part, i) => {
      const emMatch = /^<em>(.*?)<\/em>$/.exec(part);
      const text = emMatch ? emMatch[1] : part;
      const words = text.split(/(\s+)/);
      const els = words.map((w, j) => {
        if (/^\s+$/.test(w)) return <span key={`${lineIdx}-${i}-${j}`}>{w}</span>;
        const span = <span key={`${lineIdx}-${i}-${j}`} className="hw" style={{ "--i": wordIdx }}>{w}</span>;
        wordIdx++;
        return span;
      });
      return emMatch
        ? <em key={`${lineIdx}-${i}`}>{els}</em>
        : <React.Fragment key={`${lineIdx}-${i}`}>{els}</React.Fragment>;
    });
  };
  const lines = title.split(/<br\/?>/);

  return (
    <section className="hero" id="hero" data-screen-label="01 Hero">
      <video
        className="hero-video"
        src="hero-block-2.mp4"
        autoPlay
        muted
        loop
        playsInline
        preload="auto"
        aria-hidden="true"
      />
      <div className="hero-aura" aria-hidden="true">
        <span /><span /><span />
      </div>
      <div className="hero-inner">
        <DotLabel className="reveal hero-kicker" style={{ marginBottom: 40 }}>
          {t("hero.kicker")}
        </DotLabel>
        <h1 className="hero-title reveal">
          {lines.map((ln, i) => (
            <span className="hero-line" key={i} style={{ "--li": i }}>
              {buildLine(ln, i)}
            </span>
          ))}
        </h1>
        {t("hero.sub") && t("hero.sub") !== "hero.sub" && (
          <p className="hero-sub reveal" style={{ "--rv-d": "700ms" }}>{t("hero.sub")}</p>
        )}
        {t("hero.stat") && t("hero.stat") !== "hero.stat" && (
          <div className="hero-stat reveal" style={{ "--rv-d": "900ms" }} dangerouslySetInnerHTML={{ __html: t("hero.stat") }} />
        )}
        <div className="hero-cta-row reveal" style={{ "--rv-d": "1100ms" }}>
          <CTA variant="huge" onClick={onLeaveRequest}>{t("contacts.cta")}</CTA>
        </div>
      </div>
    </section>
  );
}

function About({ t }) {
  return (
    <section className="section about" id="about" data-screen-label="02 About">
      <SectionRule />
      <div className="section-inner about-inner">
        <DotLabel className="about-label reveal">{t("about.label")}</DotLabel>
        <div className="about-body glass-target">
          <p className="reveal"
             dangerouslySetInnerHTML={{ __html: t("about.lead") }} />
          {t("about.lead2") && t("about.lead2") !== "about.lead2" && (
            <p className="reveal" style={{ "--rv-d": "120ms" }}
               dangerouslySetInnerHTML={{ __html: t("about.lead2") }} />
          )}
        </div>
      </div>
    </section>
  );
}

function Services({ t }) {
  // Cards are always expanded — no collapse, no chevron.
  const services = [1, 2, 3, 4, 5].map(i => ({
    n: String(i).padStart(2, "0"),
    title: t(`services.${i}.title`),
    bullets: ["b1", "b2", "b3", "b4"]
      .map(k => ({ key: `services.${i}.${k}`, val: t(`services.${i}.${k}`) }))
      .filter(b => b.val && b.val !== b.key)
      .map(b => b.val),
    payoff: t(`services.${i}.pay`),
  }));
  return (
    <section className="section services" id="services" data-screen-label="03 Services">
      <SectionRule />
      <div className="section-inner">
        <div className="services-head reveal">
          <DotLabel>{t("services.kicker")}</DotLabel>
          <h2 dangerouslySetInnerHTML={{ __html: t("services.title") }} />
        </div>
        <div className="glass-target">
          {services.map((s) => (
            <div className="service-row reveal is-open" key={s.n}>
              <div className="service-num">{s.n}</div>
              <div className="service-body">
                <h3>{s.title}</h3>
                <ul className="service-bullets">
                  {s.bullets.map((b, j) => (
                    <li key={j}>
                      <RowIcon i={j} />
                      <span className="row-text">{b}</span>
                    </li>
                  ))}
                </ul>
                <div className="service-payoff">{s.payoff}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function MoreThanTraffic({ t }) {
  const items = [1, 2, 3].map(i => ({
    title: t(`mtt.${i}.title`),
    bullets: ["b1", "b2", "b3"]
      .map(k => ({ key: `mtt.${i}.${k}`, val: t(`mtt.${i}.${k}`) }))
      .filter(b => b.val && b.val !== b.key)
      .map(b => b.val),
    pay: t(`mtt.${i}.pay`),
  }));
  return (
    <section className="section mtt" id="more" data-screen-label="04 More Than Traffic">
      <SectionRule />
      <div className="section-inner">
        <div className="mtt-head reveal">
          <DotLabel>{t("mtt.kicker")}</DotLabel>
          <h2>{t("mtt.title")}</h2>
          <div className="sub">{t("mtt.sub")}</div>
        </div>
        <div className="mtt-grid glass-target">
          {items.map((m) => (
            <div className="mtt-item reveal" key={m.title}>
              <h3>{m.title}</h3>
              <ul>{m.bullets.map((b, j) => (
                <li key={j}>
                  <RowIcon i={j} />
                  <span className="row-text">{b}</span>
                </li>
              ))}</ul>
              <div className="pay">{m.pay}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { Hero, About, Services, MoreThanTraffic, PhoneMockup, ReelMockup, KpiDashMockup });
