/* WOAH! — Iteration 2 extras: CustomCursor, MusicPlayer, VideoPlayer, GalleryV2 */
const { useState: u2State, useEffect: u2Effect, useRef: u2Ref, useCallback: u2CB } = React;

/* ============================================================
   CACHE BUSTING — change this number when you update any asset
   to force browsers to re-download images/audio.
   How to use:
   - TopMarquee dynamic nav-height + hero padding 8rem? Bump v from 52 to 53.
   - Replaced okami-night.mp3? Bump again.
   - Just save & re-upload — visitors will see the new version.
   ============================================================ */
window.ASSET_VERSION = '118';
window.v = (path) => `${path}?v=${window.ASSET_VERSION}`;
const v = window.v;

/* ---------- Custom Cursor ---------- */
const CustomCursor = () => {
  const dotRef = u2Ref(null);
  const haloRef = u2Ref(null);
  const trailLayerRef = u2Ref(null);
  const stateRef = u2Ref({ x: -100, y: -100, hx: -100, hy: -100, lastTrail: 0, hovering: false, color: '#00F0FF' });
  const rafRef = u2Ref(0);

  u2Effect(() => {
    if (window.matchMedia('(hover: none)').matches) return;
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    document.body.classList.add('cursor-on');

    const onMove = (e) => {
      stateRef.current.x = e.clientX;
      stateRef.current.y = e.clientY;
    };
    const onDown = (e) => {
      const ring = document.createElement('div');
      ring.className = 'cur-pulse';
      ring.style.left = e.clientX + 'px';
      ring.style.top = e.clientY + 'px';
      document.body.appendChild(ring);
      setTimeout(() => ring.remove(), 500);
    };
    const onOver = (e) => {
      const t = e.target;
      const interactive = t.closest && t.closest('a,button,input,textarea,[role=button],[data-cursor]');
      stateRef.current.hovering = !!interactive;
      if (interactive) {
        const c = interactive.getAttribute('data-cursor-color') || '#00F0FF';
        stateRef.current.color = c;
      } else {
        stateRef.current.color = '#00F0FF';
      }
    };

    window.addEventListener('mousemove', onMove, { passive: true });
    window.addEventListener('mousedown', onDown);
    window.addEventListener('mouseover', onOver);

    const tick = (t) => {
      const s = stateRef.current;
      s.hx += (s.x - s.hx) * 0.18;
      s.hy += (s.y - s.hy) * 0.18;
      if (dotRef.current) {
        dotRef.current.style.transform = `translate3d(${s.x}px, ${s.y}px, 0) translate(-50%,-50%) scale(${s.hovering ? 1.9 : 1})`;
        dotRef.current.style.background = s.color;
        dotRef.current.style.boxShadow = `0 0 14px ${s.color}, 0 0 28px ${s.color}`;
      }
      if (haloRef.current) {
        haloRef.current.style.transform = `translate3d(${s.hx}px, ${s.hy}px, 0) translate(-50%,-50%) scale(${s.hovering ? 1.7 : 1})`;
        haloRef.current.style.borderColor = s.color + '66';
        haloRef.current.style.boxShadow = `0 0 28px ${s.color}55, inset 0 0 14px ${s.color}33`;
      }
      if (!reduced && trailLayerRef.current && t - s.lastTrail > 32) {
        s.lastTrail = t;
        const dot = document.createElement('span');
        dot.className = 'cur-trail';
        dot.style.left = s.x + 'px';
        dot.style.top = s.y + 'px';
        dot.style.background = s.color;
        trailLayerRef.current.appendChild(dot);
        setTimeout(() => dot.remove(), 600);
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => {
      cancelAnimationFrame(rafRef.current);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mousedown', onDown);
      window.removeEventListener('mouseover', onOver);
      document.body.classList.remove('cursor-on');
    };
  }, []);

  return ReactDOM.createPortal(
    <>
      <div className="cur-trails" ref={trailLayerRef} aria-hidden="true"/>
      <div className="cur-halo" ref={haloRef} aria-hidden="true"/>
      <div className="cur-dot" ref={dotRef} aria-hidden="true"/>
    </>,
    document.body
  );
};

/* ---------- Music Player (in nav) ---------- */
const MusicPlayer = () => {
  const [playing, setPlaying] = u2State(false);
  const [muted, setMuted] = u2State(false);
  const [volume, setVolume] = u2State(0.2); // 0–1 (default 20%)
  const [src] = u2State(v('assets/okami-night.mp3'));
  const [trackName] = u2State('Ōkami Night');
  const [trackJp] = u2State('狼の夜');
  const [time, setTime] = u2State(0);
  const [bars, setBars] = u2State(() => Array.from({length:22}, ()=>0.3));
  const audioRef = u2Ref(null);
  const barTimerRef = u2Ref(0);

  u2Effect(()=>{
    if (playing) {
      barTimerRef.current = setInterval(()=>{
        setBars(prev => prev.map((_,i)=> 0.25 + Math.random()*0.75 ));
      }, 110);
    } else {
      clearInterval(barTimerRef.current);
      setBars(prev => prev.map((_,i)=> 0.18 + Math.sin((Date.now()/600)+i)*0.05 ));
    }
    return ()=> clearInterval(barTimerRef.current);
  }, [playing]);

  // Apply volume to the audio element whenever it changes
  u2Effect(()=>{
    if (audioRef.current) audioRef.current.volume = volume;
  }, [volume]);

  // hardcoded track

  const toggle = () => {
    if (!audioRef.current || !src) return;
    if (playing) audioRef.current.pause(); else audioRef.current.play().catch(()=>{});
  };
  const fmt = (t)=> {
    const m = Math.floor(t/60), s = Math.floor(t%60);
    return `${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`;
  };

  // Toggle mute on click; unmuting restores prior volume on the audio element
  const toggleMute = () => {
    setMuted(m => {
      const next = !m;
      if (audioRef.current) audioRef.current.muted = next;
      return next;
    });
  };

  // Volume display: muted always shows 0
  const displayVol = muted ? 0 : volume;
  // Pick icon variant based on level
  const volIcon = muted || volume === 0
    ? 'volumeOff'
    : volume < 0.5 ? 'volumeLow' : 'volume';

  return (
    <div className={`mplayer ${playing?'is-playing':''}`} data-cursor>
      <div className="mplayer__art">
        <span className="mplayer__art-glow"/>
        <img src={v('logos/woah.png')} alt="WOAH!" className="mplayer__art-img"
          style={{position:'absolute',inset:'4px',width:'calc(100% - 8px)',height:'calc(100% - 8px)',objectFit:'contain',zIndex:1}}/>
      </div>
      <div className="mplayer__info">
        <div className="mplayer__title">{trackName}</div>
        <div className="mplayer__title-jp">{trackJp}</div>
        <div className="mplayer__sub">
          {playing && <span className="mplayer__live">● LIVE</span>}
          <span>EQ: CYBER ▸ ON</span>
        </div>
      </div>
      <div className="mplayer__wave" aria-hidden="true">
        {bars.map((h,i)=>(
          <span key={i} style={{height:`${Math.max(8, h*100)}%`, opacity: 0.35 + h*0.65}}/>
        ))}
      </div>
      <div className="mplayer__ctrls">
        <span className="mplayer__time">{fmt(time)}</span>
        <button className="mplayer__btn mplayer__btn--play" onClick={toggle} aria-label={playing?'Pause':'Play'}>
          <Icon name={playing?'pause':'play'} size={14}/>
        </button>
        <div className="mplayer__vol">
          <button className="mplayer__btn" onClick={toggleMute} aria-label={muted?'Unmute':'Mute'}>
            <Icon name={volIcon} size={14}/>
          </button>
          <div className="mplayer__vol-popup" role="group" aria-label="Volume">
            <input
              type="range" min="0" max="1" step="0.01"
              value={displayVol}
              onChange={(e)=>{
                const v = parseFloat(e.target.value);
                setVolume(v);
                // If user drags above 0 while muted, auto-unmute
                if (v > 0 && muted) {
                  setMuted(false);
                  if (audioRef.current) audioRef.current.muted = false;
                }
              }}
              className="mplayer__vol-slider"
              aria-label="Volume level"
              style={{'--vol': `${displayVol * 100}%`}}
            />
            <span className="mplayer__vol-num">{Math.round(displayVol * 100)}</span>
          </div>
        </div>
      </div>
      {src && (
        <audio ref={audioRef} src={src} loop
          onPlay={()=>{ setPlaying(true); if(audioRef.current) audioRef.current.volume = volume; }}
          onPause={()=>setPlaying(false)}
          onTimeUpdate={(e)=>setTime(e.target.currentTime)}
        />
      )}
    </div>
  );
};

/* ---------- Video Player (live broadcast) ---------- */
const VideoPlayer = () => {
  const [src, setSrc] = u2State(null);
  const [playing, setPlaying] = u2State(false);
  const [muted, setMuted] = u2State(true);
  const [t, setT] = u2State(0);
  const [dur, setDur] = u2State(0);
  const vRef = u2Ref(null);
  const containerRef = u2Ref(null);

  const onFile = (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    setSrc(URL.createObjectURL(f));
    setTimeout(()=>{ if (vRef.current) vRef.current.play().catch(()=>{}); }, 60);
  };
  const toggle = () => {
    if (!vRef.current || !src) return;
    if (playing) vRef.current.pause(); else vRef.current.play().catch(()=>{});
  };
  const fmt = (s)=>{
    if (!isFinite(s)) return '00:00';
    const m = Math.floor(s/60), x = Math.floor(s%60);
    return `${String(m).padStart(2,'0')}:${String(x).padStart(2,'0')}`;
  };
  const fs = () => {
    if (!containerRef.current) return;
    if (!document.fullscreenElement) containerRef.current.requestFullscreen?.();
    else document.exitFullscreen?.();
  };

  return (
    <div className="vbroadcast">
      <div className="vbroadcast__head">
        <span className="lbl">[ CLUB TOUR ]</span>
        <h3>STEP INSIDE OUR CLUB</h3>
        <span className="vbroadcast__hud-r">// CH.01 · 4K · HDR</span>
      </div>
      <div className="vplayer" ref={containerRef}>
        <span className="vplayer__corner vplayer__corner--tl">⌐</span>
        <span className="vplayer__corner vplayer__corner--tr">¬</span>
        <span className="vplayer__corner vplayer__corner--bl">⌐</span>
        <span className="vplayer__corner vplayer__corner--br">¬</span>
        <div className="vplayer__hud-tl"><span className="rec">REC ●</span> CH.01</div>
        <div className="vplayer__hud-tr">{fmt(t)} / {fmt(dur)}</div>
        <div className="vplayer__hud-br">
          <span className="vplayer__eq"><i/><i/><i/><i/><i/></span>
          4K HDR · WOAH!_LIVE
        </div>

        {!src && (
          <div className="vplayer__empty">
            <div className="vplayer__scan"/>
            <div className="vplayer__grid"/>
            <div className="vplayer__nosig">[ NO SIGNAL ]</div>
            <div className="vplayer__await">{'>>> AWAITING TRANSMISSION '}<span className="blink">_</span></div>
          </div>
        )}
        {src && (
          <video ref={vRef} src={src} loop muted={muted} playsInline
            onPlay={()=>setPlaying(true)} onPause={()=>setPlaying(false)}
            onTimeUpdate={(e)=>setT(e.target.currentTime)}
            onLoadedMetadata={(e)=>setDur(e.target.duration||0)}
          />
        )}

        {src && (
          <div className="vplayer__ctrls">
            <button className="vplayer__btn" onClick={toggle} aria-label="Play"><Icon name={playing?'pause':'play'} size={14}/></button>
            <button className="vplayer__btn" onClick={()=>{ setMuted(m=>!m); if(vRef.current) vRef.current.muted = !muted; }} aria-label="Mute"><Icon name={muted?'volumeOff':'volume'} size={14}/></button>
            <div className="vplayer__progress" onClick={(e)=>{
              const r = e.currentTarget.getBoundingClientRect();
              const p = (e.clientX-r.left)/r.width;
              if (vRef.current && dur) vRef.current.currentTime = p*dur;
            }}>
              <span style={{width: `${dur?(t/dur)*100:0}%`}}/>
            </div>
            <span className="vplayer__tc">{fmt(t)} / {fmt(dur)}</span>
            <button className="vplayer__btn" onClick={fs} aria-label="Fullscreen"><Icon name="fullscreen" size={14}/></button>
          </div>
        )}
      </div>
    </div>
  );
};

/* ---------- Memories Gallery v2 ---------- */
const FILTERS_V2 = ['ALL','DJ SETS','COSPLAY','COMMUNITY','GUEST DJS'];

const MemoriesGalleryV2 = () => {
  const [filter, setFilter] = u2State('ALL');
  const placeholders = Array.from({length:12}).map((_,i)=>({
    placeholder: true, h: 220 + ((i*61)%200), hue: (i*43+200)%360, idx: i
  }));
  const display = placeholders;

  return (
    <>
      <div className="galv2__bar">
        <div className="galv2__filters" role="tablist">
          {FILTERS_V2.map(f=>(
            <button key={f} role="tab" aria-selected={filter===f}
              className={`galv2__pill ${filter===f?'is-on':''}`} onClick={()=>setFilter(f)}>{f}</button>
          ))}
        </div>
      </div>

      <div className="galv2">
        {display.map((p, i) => (
          <div key={i} className="galv2__card is-placeholder" style={{height: p.h+'px'}}>
            <span className="galv2__corner galv2__corner--tl">⌐</span>
            <span className="galv2__corner galv2__corner--br">¬</span>
            <span className="galv2__num">IMG_{String(i+1).padStart(3,'0')}</span>
            <span className="galv2__inner" style={{
              background:`linear-gradient(135deg, oklch(0.18 0.10 ${p.hue}), oklch(0.10 0.06 ${(p.hue+40)%360}))`
            }}>
              <span className="galv2__scan"/>
              <span className="galv2__grid"/>
              <span className="galv2__await">[ AWAITING IMAGE ]</span>
            </span>
            <span className="galv2__edge"/>
          </div>
        ))}
      </div>
    </>
  );
};

window.CustomCursor = CustomCursor;
window.MusicPlayer = MusicPlayer;
window.VideoPlayer = VideoPlayer;
window.MemoriesGalleryV2 = MemoriesGalleryV2;
