// Hero: 「くらら」 — 3文字がフォント/色/サイズ/動きで自由に踊る
const { useState, useEffect, useRef, useCallback } = React;

const FONTS = [
  '"Noto Serif JP", serif',
  '"Noto Sans JP", sans-serif',
  '"Zen Old Mincho", serif',
  '"Shippori Mincho", serif',
  '"Klee One", cursive',
  '"Zen Maru Gothic", sans-serif',
  '"RocknRoll One", sans-serif',
  '"Yuji Mai", serif',
  '"Yuji Syuku", serif',
  '"Reggae One", cursive',
  '"Dela Gothic One", serif',
  '"DotGothic16", sans-serif',
  '"Kaisei Decol", serif',
  '"Hachi Maru Pop", cursive',
  '"Stick", sans-serif',
  '"Train One", serif',
];

const WEIGHTS = [400, 500, 700, 900];

const PALETTES = {
  warm: [
    'oklch(0.18 0.01 85)',
    'oklch(0.55 0.18 30)',
    'oklch(0.65 0.14 60)',
    'oklch(0.45 0.12 20)',
    'oklch(0.78 0.09 85)',
    'oklch(0.35 0.05 70)',
    'oklch(0.88 0.05 80)',
  ],
  cool: [
    'oklch(0.22 0.03 260)',
    'oklch(0.55 0.15 240)',
    'oklch(0.65 0.12 200)',
    'oklch(0.45 0.08 180)',
    'oklch(0.35 0.04 230)',
    'oklch(0.75 0.06 220)',
  ],
  mono: [
    'oklch(0.12 0 0)',
    'oklch(0.25 0 0)',
    'oklch(0.45 0 0)',
    'oklch(0.65 0 0)',
    'oklch(0.82 0 0)',
  ],
  vivid: [
    'oklch(0.55 0.22 25)',
    'oklch(0.65 0.18 145)',
    'oklch(0.55 0.2 265)',
    'oklch(0.75 0.16 85)',
    'oklch(0.5 0.22 330)',
    'oklch(0.2 0.02 265)',
  ],
};

const CHARS = ['く', 'ら', 'ら'];

const rand = (a, b) => a + Math.random() * (b - a);
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
const clamp = (v, a, b) => Math.max(a, Math.min(b, v));

function makeParticle(w, h, palette) {
  const size = Math.pow(Math.random(), 1.8) * 260 + 28;
  return {
    id: Math.random().toString(36).slice(2),
    ch: CHARS[Math.floor(Math.random() * 3)],
    font: pick(FONTS),
    weight: pick(WEIGHTS),
    color: pick(PALETTES[palette]),
    size,
    x: Math.random() * w,
    y: Math.random() * h,
    vx: rand(-0.6, 0.6),
    vy: rand(-0.6, 0.6),
    rot: rand(-25, 25),
    vr: rand(-0.4, 0.4),
    opacity: rand(0.35, 1),
    orbitR: rand(80, Math.min(w, h) * 0.45),
    orbitA: rand(0, Math.PI * 2),
    orbitSpeed: rand(0.002, 0.012) * (Math.random() < 0.5 ? -1 : 1),
    bouncePhase: rand(0, Math.PI * 2),
    hx: 0, hy: 0,
    node: null,
  };
}

function Hero() {
  const [tweaks, setTweaks] = useState(() => window.__TWEAKS);
  const [tweaksOpen, setTweaksOpen] = useState(false);
  const stageRef = useRef(null);
  const particlesRef = useRef([]);
  const mouseRef = useRef({ x: -9999, y: -9999, active: false });
  const rafRef = useRef(null);
  const [, forceRender] = useState(0);

  // Tweaks host protocol (for design tool integration)
  useEffect(() => {
    const onMsg = (e) => {
      const d = e.data || {};
      if (d.type === '__activate_edit_mode') setTweaksOpen(true);
      if (d.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);

  const persist = useCallback((patch) => {
    setTweaks(t => {
      const next = { ...t, ...patch };
      window.parent.postMessage({ type: '__edit_mode_set_keys', edits: patch }, '*');
      return next;
    });
  }, []);

  const initParticles = useCallback(() => {
    const el = stageRef.current;
    if (!el) return;
    const w = el.clientWidth;
    const h = el.clientHeight;
    const list = [];
    for (let i = 0; i < tweaks.density; i++) {
      const p = makeParticle(w, h, tweaks.palette);
      p.cx = w / 2;
      p.cy = h / 2;
      p.hx = p.x;
      p.hy = p.y;
      list.push(p);
    }
    particlesRef.current = list;
    forceRender(n => n + 1);
  }, [tweaks.density, tweaks.palette]);

  useEffect(() => {
    initParticles();
    const onResize = () => initParticles();
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, [initParticles]);

  // Animation loop — writes directly to DOM for performance
  useEffect(() => {
    let last = performance.now();
    const tick = (t) => {
      const dt = Math.min(50, t - last);
      last = t;
      const el = stageRef.current;
      if (!el) { rafRef.current = requestAnimationFrame(tick); return; }
      const w = el.clientWidth;
      const h = el.clientHeight;
      const { speed, mode } = tweaks;
      const m = mouseRef.current;

      for (const p of particlesRef.current) {
        if (mode === 'float') {
          p.x += p.vx * speed * dt * 0.06;
          p.y += p.vy * speed * dt * 0.06;
          p.rot += p.vr * speed * dt * 0.02;
          if (p.x < -p.size) p.x = w + p.size;
          if (p.x > w + p.size) p.x = -p.size;
          if (p.y < -p.size) p.y = h + p.size;
          if (p.y > h + p.size) p.y = -p.size;
        } else if (mode === 'chaos') {
          p.vx += rand(-0.3, 0.3) * speed;
          p.vy += rand(-0.3, 0.3) * speed;
          p.vx = clamp(p.vx, -6, 6);
          p.vy = clamp(p.vy, -6, 6);
          p.x += p.vx * speed * dt * 0.08;
          p.y += p.vy * speed * dt * 0.08;
          p.rot += p.vr * speed * dt * 0.1;
          if (p.x < 0 || p.x > w) p.vx *= -1;
          if (p.y < 0 || p.y > h) p.vy *= -1;
          p.x = clamp(p.x, 0, w);
          p.y = clamp(p.y, 0, h);
        } else if (mode === 'orbit') {
          p.orbitA += p.orbitSpeed * speed * dt * 0.8;
          p.x = w / 2 + Math.cos(p.orbitA) * p.orbitR - p.size / 2;
          p.y = h / 2 + Math.sin(p.orbitA) * p.orbitR - p.size / 2;
          p.rot = (p.orbitA * 180 / Math.PI) % 360;
        } else if (mode === 'bounce') {
          p.bouncePhase += 0.004 * speed * dt;
          p.x += p.vx * speed * dt * 0.05;
          p.y = p.hy + Math.sin(p.bouncePhase) * 80;
          p.rot = Math.sin(p.bouncePhase) * 20;
          if (p.x < -p.size) p.x = w + p.size;
          if (p.x > w + p.size) p.x = -p.size;
        } else if (mode === 'swarm') {
          const cx = p.x + p.size / 2;
          const cy = p.y + p.size / 2;
          const dx = cx - m.x;
          const dy = cy - m.y;
          const d2 = dx * dx + dy * dy;
          const r = 200;
          if (m.active && d2 < r * r && d2 > 1) {
            const d = Math.sqrt(d2);
            const force = (1 - d / r) * 3;
            p.vx += (dx / d) * force * 0.5;
            p.vy += (dy / d) * force * 0.5;
          }
          p.vx += (p.hx - p.x) * 0.002;
          p.vy += (p.hy - p.y) * 0.002;
          p.vx *= 0.94;
          p.vy *= 0.94;
          p.x += p.vx * speed * dt * 0.1;
          p.y += p.vy * speed * dt * 0.1;
          p.rot += p.vr * speed * dt * 0.05;
        }

        if (p.node) {
          p.node.style.transform = `translate3d(${p.x}px, ${p.y}px, 0) rotate(${p.rot}deg)`;
        }
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [tweaks.mode, tweaks.speed]);

  // Mouse tracking for swarm mode
  useEffect(() => {
    const el = stageRef.current;
    if (!el) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      mouseRef.current = { x: e.clientX - r.left, y: e.clientY - r.top, active: true };
    };
    const onLeave = () => { mouseRef.current.active = false; };
    el.addEventListener('mousemove', onMove);
    el.addEventListener('mouseleave', onLeave);
    return () => {
      el.removeEventListener('mousemove', onMove);
      el.removeEventListener('mouseleave', onLeave);
    };
  }, []);

  const modeLabels = {
    float:  'ふわり',
    chaos:  'ざわめき',
    orbit:  'めぐり',
    bounce: 'はずみ',
    swarm:  'むれ',
  };

  return (
    <>
      {/* Animated glyph stage */}
      <div className="stage" ref={stageRef} onClick={() => initParticles()}>
        {particlesRef.current.map((p) => (
          <span
            key={p.id}
            className="glyph"
            ref={(el) => { if (el) p.node = el; }}
            style={{
              fontFamily: p.font,
              fontWeight: p.weight,
              fontSize: `${p.size}px`,
              color: p.color,
              opacity: p.opacity,
            }}
          >
            {p.ch}
          </span>
        ))}
      </div>

      {/* Static chrome overlay */}
      <div className="chrome">
        <div className="top">
          <div className="mark">
            <span className="dot" />
            <span>KLARA&nbsp;&nbsp;/&nbsp;&nbsp;くらら</span>
          </div>
          <div className="top-right">
            <nav className="nav">
              <a href="#">Work</a>
              <a href="#">About</a>
              <a href="#">Journal</a>
              <a href="#">Contact</a>
            </nav>
            <div className="socials">
              <a href="https://x.com/KKKKKKKKKULA" target="_blank" rel="noopener noreferrer" aria-label="X">
                <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true">
                  <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231L18.244 2.25Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z"/>
                </svg>
              </a>
              <a href="https://www.facebook.com/krfatos" target="_blank" rel="noopener noreferrer" aria-label="Facebook">
                <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true">
                  <path d="M13.5 21.95v-8.3h2.79l.42-3.24H13.5V8.34c0-.94.26-1.58 1.6-1.58h1.71V3.87a22.9 22.9 0 0 0-2.49-.13c-2.47 0-4.16 1.5-4.16 4.27v2.38H7.36v3.24h2.8v8.3c.6.08 1.21.13 1.84.13.5 0 1-.03 1.5-.11Z"/>
                </svg>
              </a>
              <a href="https://note.com/krfatos" target="_blank" rel="noopener noreferrer" aria-label="note">
                <svg viewBox="0 0 493 493" width="16" height="16" fill="currentColor" aria-hidden="true">
                  <path d="m139.57,142.06c41.19,0,97.6-2.09,138.1-1.04,54.34,1.39,74.76,25.06,75.45,83.53.69,33.06,0,127.73,0,127.73h-58.79c0-82.83.35-96.5,0-122.6-.69-22.97-7.25-33.92-24.9-36.01-18.69-2.09-71.07-.35-71.07-.35v158.96h-58.79v-210.22Z"/>
                </svg>
              </a>
            </div>
          </div>
        </div>
        <div className="bottom">
          <div className="meta">
            <div><span className="k">index</span>&nbsp;&nbsp;001 / hero</div>
            <div><span className="k">mode</span>&nbsp;&nbsp;{tweaks.mode} — {modeLabels[tweaks.mode]}</div>
            <div><span className="k">glyphs</span>&nbsp;&nbsp;{tweaks.density}</div>
            <div style={{marginTop: 8, opacity: .6}}>click to reshuffle</div>
          </div>
        </div>
      </div>

      {/* Scroll hint */}
      <div className="scroll-hint">
        <span>SCROLL</span>
        <span className="line" />
      </div>

      {/* Tweaks panel */}
      <div className={`tweaks ${tweaksOpen ? 'on' : ''}`}>
        <h4>Tweaks <span className="tag">HERO / KLARA</span></h4>

        <div className="row">
          <label>Motion mode</label>
          <div className="modes">
            {Object.keys(modeLabels).map(m => (
              <button
                key={m}
                className={tweaks.mode === m ? 'active' : ''}
                onClick={() => persist({ mode: m })}
              >
                {modeLabels[m]}
              </button>
            ))}
          </div>
        </div>

        <div className="row">
          <label>Density <span className="value">{tweaks.density}</span></label>
          <input
            type="range" min="8" max="120" step="1"
            value={tweaks.density}
            onChange={e => persist({ density: +e.target.value })}
          />
        </div>

        <div className="row">
          <label>Speed <span className="value">{tweaks.speed.toFixed(2)}×</span></label>
          <input
            type="range" min="0.1" max="3" step="0.05"
            value={tweaks.speed}
            onChange={e => persist({ speed: +e.target.value })}
          />
        </div>

        <div className="row">
          <label>Palette</label>
          <div className="palette">
            {Object.keys(PALETTES).map(pk => (
              <button
                key={pk}
                className={tweaks.palette === pk ? 'active' : ''}
                style={{
                  background: `linear-gradient(90deg, ${PALETTES[pk].slice(0, 4).join(',')})`
                }}
                onClick={() => persist({ palette: pk })}
                title={pk}
              />
            ))}
          </div>
        </div>

        <div className="row" style={{marginTop: 16, paddingTop: 12, borderTop: '1px solid var(--rule)'}}>
          <button
            onClick={() => initParticles()}
            style={{
              width: '100%', padding: '10px', fontFamily: 'inherit',
              border: '1px solid var(--ink)', background: 'var(--ink)', color: 'var(--bg)',
              borderRadius: 6, fontSize: 11, letterSpacing: '.15em', cursor: 'pointer'
            }}
          >
            RESHUFFLE
          </button>
        </div>
      </div>
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Hero />);
