// Clientelle hero video — director: timeline clock, cursor + camera keyframes,
// player chrome, mount. Depends on: Easing, interpolate, animate, clamp (animations.jsx)
// and CrmApp (crm-hero-app.jsx).

const HERO_DUR = 24;
const HERO_W = 1440, HERO_H = 900;

// ── click moments (canvas coords) ───────────────────────────────────────────
const HERO_CLICKS = [
  { t: 3.6,  x: 732,  y: 417 },  // Send text (reminder)
  { t: 5.5,  x: 875,  y: 566 },  // Send (composer)
  { t: 7.4,  x: 120,  y: 192 },  // sidebar Clients
  { t: 11.0, x: 120,  y: 292 },  // sidebar Gallery
  { t: 12.4, x: 420,  y: 164 },  // search field
  { t: 16.4, x: 120,  y: 142 },  // sidebar Dashboard
  { t: 18.6, x: 1085, y: 189 },  // Confirm booking
];

// ── cursor path ─────────────────────────────────────────────────────────────
const HERO_CT = [0, 1.2, 2.4, 2.9, 3.5, 4.4, 5.3, 6.3, 7.3, 8.2, 9.0, 10.0, 10.4, 11.0, 11.8, 12.4, 14.8, 15.5, 16.3, 17.7, 18.5, 19.8, 21.2, HERO_DUR];
const heroCx = interpolate(HERO_CT, [1180, 1180, 620, 620, 732, 732, 875, 875, 120, 120, 520, 545, 545, 120, 120, 420, 420, 420, 120, 120, 1085, 1085, 1180, 1180], Easing.easeInOutCubic);
const heroCy = interpolate(HERO_CT, [800, 800, 417, 417, 417, 417, 566, 566, 192, 192, 390, 480, 480, 292, 292, 164, 164, 164, 142, 142, 189, 189, 800, 800], Easing.easeInOutCubic);

// ── camera (lags the cursor slightly = damped follow) ───────────────────────
const HERO_KT = [0, 1.0, 2.7, 3.8, 4.5, 5.8, 6.4, 7.6, 8.4, 10.6, 11.3, 12.6, 14.9, 15.9, 16.7, 17.5, 19.3, 21.4, HERO_DUR];
const heroCamX = interpolate(HERO_KT, [720, 720, 600, 620, 720, 720, 700, 640, 560, 560, 540, 480, 600, 600, 720, 1020, 1020, 720, 720], Easing.easeInOutCubic);
const heroCamY = interpolate(HERO_KT, [450, 450, 430, 440, 450, 450, 440, 420, 400, 400, 320, 260, 320, 320, 450, 220, 220, 450, 450], Easing.easeInOutCubic);
const heroCamS = interpolate(HERO_KT, [1, 1.04, 1.5, 1.5, 1.32, 1.32, 1.38, 1.38, 1.5, 1.5, 1.55, 1.62, 1.5, 1.5, 1.12, 1.5, 1.5, 1, 1], Easing.easeInOutCubic);

// ── derived UI state from playhead ──────────────────────────────────────────
function heroDerive(t) {
  const view = t < 7.4 ? 'dashboard' : t < 11.0 ? 'clients' : t < 16.4 ? 'gallery' : 'dashboard';
  const switchT = t < 7.4 ? 0 : t < 11.0 ? 7.4 : t < 16.4 ? 11.0 : 16.4;
  const openP = clamp((t - 3.7) / 0.45, 0, 1);
  const closeP = clamp((t - 5.7) / 0.3, 0, 1);
  return {
    t,
    view,
    viewFade: switchT === 0 ? 1 : (t - switchT) / 0.45,
    moneyCount: animate({ from: 0, to: 4820, start: 0.6, end: 2.0, ease: Easing.easeOutExpo })(t),
    hoverReminder: t > 2.4 && t < 3.7,
    composerP: openP * (1 - closeP),
    toastP: t < 5.9 ? 0 : t < 7.3 ? clamp((t - 5.9) / 0.4, 0, 1) : clamp(1 - (t - 7.3) / 0.3, 0, 1),
    reminderSent: t >= 5.6,
    searchFocus: t >= 12.4 && t < 16.4,
    typedChars: clamp(Math.floor((t - 12.7) / 0.17), 0, 10),
    filterP: Easing.easeInOutCubic(clamp((t - 14.5) / 0.6, 0, 1)),
    notifP: clamp((t - 17.0) / 0.5, 0, 1),
    confirmP: clamp((t - 18.7) / 0.35, 0, 1),
    newBookingP: Easing.easeOutCubic(clamp((t - 19.2) / 0.5, 0, 1)),
  };
}

// ── small world-space pieces ────────────────────────────────────────────────
function HeroRipple({ t, click }) {
  const p = clamp((t - click.t) / 0.45, 0, 1);
  if (p <= 0 || p >= 1) return null;
  const e = Easing.easeOutCubic(p);
  return (
    <div style={{
      position: 'absolute', left: click.x - 36 * e, top: click.y - 36 * e,
      width: 72 * e, height: 72 * e, borderRadius: '50%',
      border: '3px solid var(--accent)', opacity: 0.7 * (1 - p), pointerEvents: 'none', zIndex: 60,
    }}></div>
  );
}

function HeroCursor({ x, y, pressed }) {
  return (
    <div style={{ position: 'absolute', left: x, top: y, transform: `scale(${pressed ? 0.8 : 1})`, transformOrigin: '4px 4px', zIndex: 70, filter: 'drop-shadow(0 2px 5px rgba(42,33,38,0.4))' }}>
      <svg width="30" height="36" viewBox="0 0 17 20">
        <path d="M2 1 L2 16 L6 12.5 L8.7 19 L11.4 17.9 L8.7 11.5 L14 11 Z" fill="#fff" stroke="#2A2126" strokeWidth="1.2" strokeLinejoin="round"></path>
      </svg>
    </div>
  );
}

// ── clock ───────────────────────────────────────────────────────────────────
function useHeroClock(duration) {
  const [time, setTime] = React.useState(() => {
    try {
      const v = parseFloat(localStorage.getItem('clientelle-hero:t') || '0');
      return isFinite(v) ? clamp(v, 0, duration) : 0;
    } catch { return 0; }
  });
  const [playing, setPlaying] = React.useState(true);
  const raf = React.useRef(null);
  const last = React.useRef(null);

  React.useEffect(() => {
    try { localStorage.setItem('clientelle-hero:t', String(time)); } catch {}
  }, [time]);

  React.useEffect(() => {
    if (!playing) { last.current = null; return; }
    const step = (ts) => {
      if (last.current == null) last.current = ts;
      const dt = (ts - last.current) / 1000;
      last.current = ts;
      setTime((t) => (t + dt) % duration);
      raf.current = requestAnimationFrame(step);
    };
    raf.current = requestAnimationFrame(step);
    return () => { cancelAnimationFrame(raf.current); last.current = null; };
  }, [playing, duration]);

  return { time, playing, setPlaying, setTime };
}

// ── beat captions (under the video) ─────────────────────────────────────────
const HERO_BEATS = [
  { until: 3.0,  label: 'your day, at a glance' },
  { until: 7.2,  label: 'rebook reminder — prefilled, one tap to send' },
  { until: 10.8, label: 'client profile — tags, categorized notes, history' },
  { until: 16.2, label: 'photo library — search by tag' },
  { until: 21.0, label: 'booking request — confirm in one click' },
  { until: 99,   label: 'everything in one place. and it\u2019s yours.' },
];

// ── player ──────────────────────────────────────────────────────────────────
function HeroPlayer() {
  const { time: t, playing, setPlaying, setTime } = useHeroClock(HERO_DUR);
  const wrapRef = React.useRef(null);
  const [w, setW] = React.useState(1140);

  React.useEffect(() => {
    if (!wrapRef.current) return;
    const measure = () => setW(wrapRef.current.clientWidth);
    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);

  const scale = w / HERO_W;
  const d = heroDerive(t);
  const cx = heroCx(t), cy = heroCy(t);
  const s = heroCamS(t);
  let tx = HERO_W / 2 - heroCamX(t) * s;
  let ty = HERO_H / 2 - heroCamY(t) * s;
  tx = clamp(tx, HERO_W - HERO_W * s, 0);
  ty = clamp(ty, HERO_H - HERO_H * s, 0);
  const pressed = HERO_CLICKS.some(c => t > c.t && t < c.t + 0.18);

  // loop-seam fade
  const seam = Math.max(clamp((t - (HERO_DUR - 0.6)) / 0.6, 0, 1), clamp(1 - t / 0.5, 0, 1));
  const beat = HERO_BEATS.find(b => t < b.until) || HERO_BEATS[HERO_BEATS.length - 1];
  const pct = (t / HERO_DUR) * 100;

  const seek = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    setTime(clamp((e.clientX - rect.left) / rect.width, 0, 1) * HERO_DUR);
  };

  return (
    <div ref={wrapRef} style={{ width: '100%' }}>
      {/* video frame */}
      <div
        onClick={() => setPlaying(p => !p)}
        style={{
          width: '100%', height: HERO_H * scale, position: 'relative', overflow: 'hidden',
          borderRadius: 'calc(var(--radius) * 1.25)', border: '1px solid var(--line)',
          boxShadow: '0 40px 100px -20px rgba(42,33,38,0.28)', cursor: 'pointer',
          background: '#FBF8F4',
        }}
      >
        <div style={{ width: HERO_W, height: HERO_H, transform: `scale(${scale})`, transformOrigin: '0 0', position: 'absolute' }}>
          {/* camera world */}
          <div style={{ position: 'absolute', inset: 0, transform: `translate(${tx}px, ${ty}px) scale(${s})`, transformOrigin: '0 0' }}>
            <CrmApp d={d} />
            {HERO_CLICKS.map((c, i) => <HeroRipple key={i} t={t} click={c} />)}
            <HeroCursor x={cx} y={cy} pressed={pressed} />
          </div>
          {/* loop seam */}
          <div style={{ position: 'absolute', inset: 0, background: '#FBF8F4', opacity: seam, pointerEvents: 'none' }}></div>
          {/* paused badge */}
          {!playing && (
            <div style={{
              position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%, -50%)',
              width: 110, height: 110, borderRadius: '50%', background: 'rgba(42,33,38,0.72)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <svg width="36" height="36" viewBox="0 0 14 14"><path d="M4 2l8 5-8 5V2z" fill="#FAF7F2"></path></svg>
            </div>
          )}
        </div>
      </div>

      {/* control strip */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginTop: 18, fontFamily: "'JetBrains Mono', monospace" }}>
        <button
          onClick={() => setPlaying(p => !p)}
          aria-label="Play or pause"
          style={{
            width: 34, height: 34, borderRadius: '50%', border: '1px solid var(--line)',
            background: 'var(--surface)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 0, flexShrink: 0,
          }}
        >
          {playing
            ? <svg width="11" height="11" viewBox="0 0 14 14"><rect x="3" y="2" width="3" height="10" fill="#2A2126"></rect><rect x="8" y="2" width="3" height="10" fill="#2A2126"></rect></svg>
            : <svg width="11" height="11" viewBox="0 0 14 14"><path d="M3 2l9 5-9 5V2z" fill="#2A2126"></path></svg>}
        </button>
        <div onClick={seek} style={{ flex: 1, height: 20, display: 'flex', alignItems: 'center', cursor: 'pointer', position: 'relative' }}>
          <div style={{ position: 'absolute', left: 0, right: 0, height: 3, borderRadius: 2, background: 'var(--line)' }}></div>
          <div style={{ position: 'absolute', left: 0, width: pct + '%', height: 3, borderRadius: 2, background: 'var(--accent)' }}></div>
        </div>
        <div style={{ fontSize: 12.5, color: 'var(--ink-soft)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '52%' }}>
          {beat.label}
        </div>
      </div>
    </div>
  );
}

const heroRoot = document.getElementById('hero-video');
if (heroRoot) ReactDOM.createRoot(heroRoot).render(<HeroPlayer />);
