// ── COMPONENTS ──────────────────────────────────────────────────────────

const { useState, useEffect, useRef, useCallback } = React;

// ── Custom cursor with glitch trail ────────────────────────────────────
function Cursor({ enabled }) {
  const dotRef = useRef(null);
  const trailRef = useRef(null);
  const [glitches, setGlitches] = useState([]);

  useEffect(() => {
    if (!enabled) return;
    document.body.classList.add('cursor-on');
    let raf;
    const pos = { x: -100, y: -100 };
    const trail = { x: -100, y: -100 };

    const onMove = (e) => {
      pos.x = e.clientX;pos.y = e.clientY;
      const tgt = e.target;
      const link = tgt && tgt.closest && tgt.closest('a, button, [role="button"], .rel-card, .rel-row, .artist-card, .shop-item, .menu-list li');
      if (dotRef.current) {
        dotRef.current.classList.toggle('over-link', !!link);
      }
      // sprinkle occasional glitch token
      if (Math.random() < 0.04) {
        const txt = ['x', '>', '//', 'err', '01', 'SOK', '▌', '░', '╳', '{}', '??', '!!', '◌'][Math.floor(Math.random() * 13)];
        const id = Math.random().toString(36).slice(2);
        const dx = (Math.random() - 0.5) * 80;
        const dy = (Math.random() - 0.5) * 80;
        setGlitches((g) => [...g, { id, x: e.clientX + dx, y: e.clientY + dy, txt }]);
        setTimeout(() => setGlitches((g) => g.filter((it) => it.id !== id)), 380);
      }
    };

    const tick = () => {
      trail.x += (pos.x - trail.x) * 0.18;
      trail.y += (pos.y - trail.y) * 0.18;
      if (dotRef.current) {
        dotRef.current.style.transform = `translate3d(${pos.x}px, ${pos.y}px, 0)`;
      }
      if (trailRef.current) {
        trailRef.current.style.transform = `translate3d(${trail.x}px, ${trail.y}px, 0)`;
      }
      raf = requestAnimationFrame(tick);
    };

    window.addEventListener('mousemove', onMove);
    raf = requestAnimationFrame(tick);
    return () => {
      window.removeEventListener('mousemove', onMove);
      cancelAnimationFrame(raf);
      document.body.classList.remove('cursor-on');
    };
  }, [enabled]);

  if (!enabled) return null;
  return (
    <React.Fragment>
      <div ref={trailRef} className="cur-trail"></div>
      <div ref={dotRef} className="cur"></div>
      {glitches.map((g) =>
      <div key={g.id} className="cur-glitch" style={{ left: g.x, top: g.y }}>{g.txt}</div>
      )}
    </React.Fragment>);

}

// ── Edge chrome (MENU, CONTACT, marker, etc.) ─────────────────────────
function EdgeChrome({ page, setPage, openMenu, currentLabel }) {
  const isHome = page === 'home';
  const [scrolled, setScrolled] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 60);
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <React.Fragment>
      {!isHome &&
      <div className={`edge edge-tl edge-tl-static ${scrolled ? 'is-hidden' : ''}`}>
          <button className="mark" onClick={() => setPage('home')} aria-label="home">
            <img src={(typeof window !== 'undefined' && window.__resources && window.__resources.avaImg) || 'assets/ava.jpg'} alt="shi o kiku" />
          </button>
          <div className="meta">
            <b>[ SHI O KIKU ]</b><br />
          internet label · krd · est 2024
          </div>
        </div>}

      <button className="edge edge-tr" onClick={openMenu} style={{ fontSize: "14px" }}>
        <span className="dot"></span>
        <span style={{ fontSize: "14px", lineHeight: "2" }}>menu</span>
      </button>

      <div className="edge edge-rb">
        {page === 'events' ? (
          <button onClick={() => setPage('home')} className="ln" style={{ fontSize: "14px" }}>
            ← go home
          </button>
        ) : (
          <button onClick={() => setPage('events')} className="ln" style={{ fontSize: "14px" }}>
            next show · kazan 20.06
          </button>
        )}
      </div>

      {isHome && (
        <div className="edge edge-bl">
          <div className="row">
            <span>demos</span>
            <button onClick={() => setPage('contact')} className="ln">demo@shiokiku.ru</button>
          </div>
          <div className="row">
            <span>booking</span>
            <a className="ln" href="mailto:book@shiokiku.ru">book@shiokiku.ru</a>
          </div>
        </div>
      )}

      {isHome && (
        <div className="edge edge-bc">
          <span className="blink"></span>
          {currentLabel} / next show 20.06 · kazan
        </div>
      )}
    </React.Fragment>);

}

// ── Marquee ────────────────────────────────────────────────────────────
function Marquee({ items, position = 'top' }) {
  const seq = [...items, ...items, ...items];
  return (
    <div className={`marquee marquee-${position}`}>
      <div className="marquee-track">
        {seq.map((it, i) =>
        <React.Fragment key={i}>
            <span>{it}</span>
            <span className="sep">/</span>
          </React.Fragment>
        )}
      </div>
    </div>);

}

// ── Menu overlay ──────────────────────────────────────────────────────
function MenuOverlay({ open, onClose, page, setPage }) {
  useEffect(() => {
    const onKey = (e) => {if (e.key === 'Escape') onClose();};
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  return (
    <div className={`menu-overlay ${open ? 'open' : ''}`}>
      <button className="menu-close" onClick={onClose}>close [esc]</button>
      <div>
        <h2>// navigate</h2>
        <ul className="menu-list">
          {MENU_ITEMS.map((m) =>
          <li key={m.key}>
              <button onClick={() => {setPage(m.key);onClose();}}>
                <span>{page === m.key ? `[${m.label}]` : m.label}</span>
                <span className="idx">{m.idx}</span>
              </button>
            </li>
          )}
        </ul>
      </div>
      <div className="menu-info">
        <h2>// the label</h2>
        <p>
          <b>shi o kiku</b> [ 死を聞く / "to hear death" ] is an internet label
          and community based in <b>krasnodar, ru</b>. we release
          trashwave, breakcore, sextrance and hypertrance — no genres are sacred,
          only the bpm is.
        </p>
        <p style={{ marginTop: 18 }}>
          <b>demos:</b> demo@shiokiku.ru<br />
          <b>booking:</b> book@shiokiku.ru<br />
          <b>tg:</b> @shiokiku
        </p>
        <p style={{ marginTop: 30, fontSize: 10, letterSpacing: '0.3em', textTransform: 'uppercase' }}>
          mmxxiv — mmxxvi · all rights wrong
        </p>
      </div>
    </div>);

}

// ── Release modal ─────────────────────────────────────────────────────
function ReleaseModal({ release, onClose }) {
  useEffect(() => {
    const onKey = (e) => {if (e.key === 'Escape') onClose();};
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  if (!release) return null;
  return (
    <div className="modal" onClick={onClose}>
      <div className="modal-card" onClick={(e) => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}>close [esc]</button>
        <div className="cov" style={{ background: release.swatch }}>
          <div className="glyph">{release.glyph}</div>
        </div>
        <div className="body">
          <div style={{ fontSize: 10, letterSpacing: '0.3em', color: 'var(--accent)' }}>
            [ {release.cat} ] · {release.genre}
          </div>
          <h3>{release.title}</h3>
          <div className="by">by <b>{release.artists.join(' & ')}</b></div>
          <div className="meta-row">
            <span>release <b>{release.date}</b></span>
            <span>format <b>digital · vinyl</b></span>
            <span>tracks <b>{release.tracks.length}</b></span>
          </div>
          <div className="tracks">
            {release.tracks.map((tr, i) =>
            <div className="track" key={i}>
                <span className="n">{String(i + 1).padStart(2, '0')}</span>
                <span className="ttl">{tr.t}</span>
                <span className="dur">{tr.d}</span>
              </div>
            )}
          </div>
          <div className="ctas">
            <button className="btn primary">▶ stream</button>
            <button className="btn">bandcamp</button>
            <button className="btn">spotify</button>
          </div>
        </div>
      </div>
    </div>);

}

// ── Tweaks panel (custom for this site) ───────────────────────────────
function SOKTweaks({ tweaks, setTweak }) {
  return (
    <TweaksPanel title="tweaks">
      <TweakSection label="theme">
        <TweakRadio
          label="palette"
          value={tweaks.theme}
          options={['dark', 'light', 'acid']}
          onChange={(v) => setTweak('theme', v)} />
        
      </TweakSection>
      <TweakSection label="cursor">
        <TweakToggle
          label="glitch cursor"
          value={tweaks.cursor}
          onChange={(v) => setTweak('cursor', v)} />
        
      </TweakSection>
      <TweakSection label="texture">
        <TweakSlider
          label="grain" value={tweaks.grain} min={0} max={60} unit="%"
          onChange={(v) => setTweak('grain', v)} />
        
        <TweakSlider
          label="halftone" value={tweaks.halftone} min={0} max={40} unit="%"
          onChange={(v) => setTweak('halftone', v)} />
        
      </TweakSection>
    </TweaksPanel>);

}

Object.assign(window, {
  Cursor, EdgeChrome, Marquee, MenuOverlay, ReleaseModal, SOKTweaks
});