/* live-entry.jsx — DJ console + TV display + router + mount */
/* eslint-disable */

// ════════════════════════════════════════════════════════════
// DJ VIEW
// ════════════════════════════════════════════════════════════
function DjView() {
  const [room, roomApi] = useRoom(CFG.room);
  const spotify = useSpotify();
  const toast = useToast();
  const [tab, setTab] = React.useState('pending');
  const [playback, setPlayback] = React.useState(null);

  // Poll Spotify playback every 3s when authed
  React.useEffect(() => {
    if (spotify.isMock || !spotify.authed) return;
    let active = true;
    const tick = async () => {
      try {
        const p = await spotify.client.currentPlayback();
        if (active) setPlayback(p);
      } catch (e) { /* token may have expired */ }
    };
    tick();
    const t = setInterval(tick, 3000);
    return () => { active = false; clearInterval(t); };
  }, [spotify.authed, spotify.isMock]);

  // Tell the room when the DJ connects/disconnects
  React.useEffect(() => {
    if (!roomApi) return;
    roomApi.setDjConnected(spotify.isMock || spotify.authed, undefined);
  }, [spotify.authed, spotify.isMock]);

  // Share Spotify token with guests — runs after room loads from Supabase to avoid race condition
  React.useEffect(() => {
    if (!room || !roomApi) return;
    if (spotify.authed) {
      try {
        const tok = JSON.parse(localStorage.getItem('sonarium.spotify.token') || 'null');
        if (tok && tok.access_token) roomApi.update({ djToken: tok });
      } catch {}
    }
  }, [!!room, spotify.authed]);

  if (!room) return null;

  const pending = room.requests.filter(r => r.status === 'pending');
  const queued  = room.requests.filter(r => r.status === 'next' || r.status === 'queued');
  const playing = room.requests.find(r => r.status === 'playing');

  const approve = async (r) => {
    roomApi.setStatus(r.id, queued.length === 0 ? 'next' : 'queued');
    if (!spotify.isMock && spotify.authed && r.track.uri) {
      try { await spotify.client.queue(r.track.uri); toast('Añadida a la cola de Spotify'); }
      catch (e) { toast('Error encolando en Spotify', 'error'); }
    } else { toast('Aprobada'); }
  };
  const reject = (r) => { roomApi.setStatus(r.id, 'rejected'); toast('Rechazada'); };
  const skip   = async () => {
    if (!spotify.isMock && spotify.authed) {
      try { await spotify.client.next(); toast('Saltada'); } catch (e) { toast('No se pudo saltar', 'error'); }
    }
    const next = queued[0];
    if (next) roomApi.setNowPlaying(next.id);
  };
  const togglePlay = async () => {
    if (spotify.isMock || !spotify.authed) return;
    try {
      if (playback?.isPlaying) await spotify.client.pause();
      else await spotify.client.play();
    } catch (e) { toast('Control no disponible · ¿hay un dispositivo activo en Spotify?', 'error'); }
  };

  return (
    <div style={{ minHeight: '100vh', position: 'relative', overflow: 'hidden' }}>
      <div className="aurora"><div className="orb-mid"/></div>
      <div className="grain" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}/>

      <div className="dj-grid" style={{
        position: 'relative', zIndex: 1, minHeight: '100vh',
        gap: 18, padding: 18,
      }}>
        {/* Sidebar */}
        <aside className="glass" style={{ padding: 18, display: 'flex', flexDirection: 'column' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 26 }}>
            <FSJAMark size={36}/>
            <div>
              <div className="serif" style={{ fontSize: 18, lineHeight: 1 }}>Sonarium</div>
              <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.45)', marginTop: 2 }}>
                Consola del DJ
              </div>
            </div>
          </div>

          <SpotifyStatus spotify={spotify}/>

          <div style={{ marginTop: 14, marginBottom: 18 }}>
            <div className="glass-soft" style={{ padding: '12px 14px' }}>
              <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 2 }}>Sala <span className="mono" style={{ color: 'var(--gold-500)' }}>{room.code}</span></div>
              <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,0.55)', display: 'flex', alignItems: 'center', gap: 6 }}>
                <span className="live-dot"/> {room.stats?.listeners ?? 1} conectados
              </div>
            </div>
          </div>

          <nav style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
            <DjNavItem icon={Icon.clock(15)} label="Pendientes"   badge={pending.length} highlight active={tab === 'pending'} onClick={() => setTab('pending')}/>
            <DjNavItem icon={Icon.music(15)} label="En cola"      badge={queued.length}  active={tab === 'queue'}   onClick={() => setTab('queue')}/>
            <DjNavItem icon={Icon.check(15)} label="Historial"    active={tab === 'history'} onClick={() => setTab('history')}/>
            <DjNavItem icon={Icon.ban(15)}   label="Bloqueados"/>
          </nav>

          <div style={{ marginTop: 'auto' }}>
            <div className="glass-soft" style={{ padding: 14 }}>
              <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.55)', marginBottom: 8, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
                QR de la sala
              </div>
              <div style={{ background: '#fff', padding: 8, borderRadius: 8, marginBottom: 10 }}>
                <RealQR url={`${location.origin + location.pathname}?role=guest&room=${room.code}`} size={120} dark="#0a1a2e"/>
              </div>
              <div className="mono" style={{ fontSize: 10.5, color: 'var(--gold-500)', textAlign: 'center', letterSpacing: '0.06em', wordBreak: 'break-all' }}>
                {location.origin + location.pathname}?role=guest&room={room.code}
              </div>
            </div>

            <button
              onClick={() => window.open(`${location.origin + location.pathname}?role=tv&room=${room.code}`, '_blank')}
              className="btn-ghost"
              style={{ width: '100%', height: 40, borderRadius: 12, fontSize: 13, marginTop: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}
            >
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
                <rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/>
              </svg>
              Abrir pantalla TV
            </button>
            <button
              onClick={() => window.open(`${location.origin + location.pathname}?role=qr&room=${room.code}`, '_blank')}
              className="btn-ghost"
              style={{ width: '100%', height: 40, borderRadius: 12, fontSize: 13, marginTop: 6, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}
            >
              {Icon.qr(15)}
              Pantalla QR + enlace
            </button>

            {/* Zona de peligro */}
            <div style={{ marginTop: 16, borderTop: '1px solid rgba(255,255,255,.07)', paddingTop: 14, display: 'flex', flexDirection: 'column', gap: 6 }}>
              <button
                onClick={() => {
                  if (window.confirm('¿Borrar todas las peticiones y reiniciar la sala?')) {
                    roomApi.reset();
                    toast('Sala reiniciada');
                  }
                }}
                style={{
                  width: '100%', height: 36, borderRadius: 10, fontSize: 12, border: 'none',
                  background: 'rgba(255,255,255,.05)', color: 'rgba(255,255,255,.5)',
                  cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7,
                  transition: 'background .15s, color .15s',
                }}
                onMouseEnter={e => { e.currentTarget.style.background = 'rgba(220,60,60,.18)'; e.currentTarget.style.color = '#f87171'; }}
                onMouseLeave={e => { e.currentTarget.style.background = 'rgba(255,255,255,.05)'; e.currentTarget.style.color = 'rgba(255,255,255,.5)'; }}
              >
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6"/>
                </svg>
                Resetear sala
              </button>
              <button
                onClick={() => {
                  if (window.confirm('¿Cerrar sesión? La sala quedará vacía y volverás al inicio.')) {
                    roomApi.reset();
                    localStorage.removeItem('sonarium.config.room');
                    localStorage.removeItem('sonarium.config.djName');
                    window.location.href = location.pathname;
                  }
                }}
                style={{
                  width: '100%', height: 36, borderRadius: 10, fontSize: 12, border: 'none',
                  background: 'rgba(255,255,255,.05)', color: 'rgba(255,255,255,.5)',
                  cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7,
                  transition: 'background .15s, color .15s',
                }}
                onMouseEnter={e => { e.currentTarget.style.background = 'rgba(220,60,60,.18)'; e.currentTarget.style.color = '#f87171'; }}
                onMouseLeave={e => { e.currentTarget.style.background = 'rgba(255,255,255,.05)'; e.currentTarget.style.color = 'rgba(255,255,255,.5)'; }}
              >
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/>
                </svg>
                Cerrar sesión
              </button>
            </div>
          </div>
        </aside>

        {/* Main */}
        <main style={{ display: 'flex', flexDirection: 'column', gap: 18, minWidth: 0 }}>
          <DjNowPlaying playing={playing} playback={playback} spotify={spotify} onTogglePlay={togglePlay} onSkip={skip}/>

          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
            <div className="serif" style={{ fontSize: 26 }}>
              {tab === 'pending' && 'Pendientes de aprobar'}
              {tab === 'queue'   && 'En cola'}
              {tab === 'history' && 'Historial'}
            </div>
          </div>

          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 8 }}>
            {tab === 'pending' && (pending.length
              ? pending.map(r => <DjPendingRow key={r.id} r={r} onApprove={() => approve(r)} onReject={() => reject(r)}/>)
              : <EmptyState text="Sin peticiones pendientes. Las nuevas aparecerán aquí."/>
            )}
            {tab === 'queue' && (queued.length
              ? queued.map((r, i) => <DjQueueRow key={r.id} r={r} index={i} onSkip={() => roomApi.setNowPlaying(r.id)} onRemove={() => roomApi.removeRequest(r.id)}/>)
              : <EmptyState text="Cola vacía."/>
            )}
            {tab === 'history' && <EmptyState text={`${room.requests.filter(r => r.status === 'played').length} canciones sonadas esta noche.`}/>}
          </div>
        </main>

        {/* Right rail */}
        <aside style={{ display: 'flex', flexDirection: 'column', gap: 18, minHeight: 0 }}>
          {queued[0] && <DjUpcoming r={queued[0]}/>}

          <div className="glass" style={{ padding: 18, flex: 1, display: 'flex', flexDirection: 'column' }}>
            <div style={{ fontSize: 11, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.5)', marginBottom: 14 }}>
              Esta noche
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
              <DjStat label="Sonadas"   value={String(room.requests.filter(r => r.status === 'played').length)}/>
              <DjStat label="En cola"   value={String(queued.length)}/>
              <DjStat label="Esperando" value={String(pending.length)} tone="gold"/>
              <DjStat label="Conectados" value={String(room.stats?.listeners ?? 1)}/>
            </div>
            {pending[0]?.note && (
              <div style={{ marginTop: 'auto', paddingTop: 14, borderTop: '0.5px solid rgba(255,255,255,0.08)', fontSize: 11.5, color: 'rgba(255,255,255,0.55)', lineHeight: 1.5 }}>
                <strong style={{ color: 'rgba(255,255,255,0.85)' }}>{pending[0].from}</strong> espera aprobación: <em>«{pending[0].note}»</em>
              </div>
            )}
          </div>
        </aside>
      </div>
    </div>
  );
}

function SpotifyStatus({ spotify }) {
  if (spotify.isMock) {
    const [open,     setOpen]     = React.useState(false);
    const [clientId, setClientId] = React.useState('');
    const save = () => {
      const id = clientId.trim();
      if (!id) return;
      localStorage.setItem('sonarium.config.clientId', id);
      window.location.reload();
    };
    return (
      <div className="glass-soft" style={{ padding: 12, fontSize: 12 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: open ? 10 : 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, color: 'rgba(255,255,255,.5)', fontWeight: 600 }}>
            <SpotifyGlyph size={14} color="rgba(255,255,255,.35)"/> Sin Spotify
          </div>
          <button
            onClick={() => setOpen(o => !o)}
            style={{ background: 'none', border: 'none', color: 'var(--gold-500)', fontSize: 11, cursor: 'pointer', fontFamily: 'inherit' }}
          >
            {open ? 'Cancelar' : 'Configurar →'}
          </button>
        </div>
        {open && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <div style={{ fontSize: 11, color: 'rgba(255,255,255,.45)', lineHeight: 1.5 }}>
              Pega tu <strong style={{ color: 'rgba(255,255,255,.7)' }}>Client ID</strong> de{' '}
              <a href="https://developer.spotify.com/dashboard" target="_blank" rel="noreferrer"
                style={{ color: 'var(--gold-500)', textDecoration: 'none' }}>
                Spotify Developer
              </a>
            </div>
            <input
              className="glass-input"
              placeholder="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
              value={clientId}
              onChange={e => setClientId(e.target.value)}
              onKeyDown={e => e.key === 'Enter' && save()}
              style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '.02em' }}
              autoFocus
            />
            <button
              onClick={save}
              disabled={!clientId.trim()}
              className="btn-gold"
              style={{ height: 36, borderRadius: 10, fontSize: 12, opacity: clientId.trim() ? 1 : 0.4 }}
            >
              Guardar y conectar
            </button>
          </div>
        )}
      </div>
    );
  }
  if (!spotify.authed) {
    return (
      <button onClick={spotify.login} className="btn-gold" style={{
        width: '100%', height: 42, borderRadius: 12, fontSize: 13.5,
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      }}>
        <SpotifyGlyph size={16}/> Conectar Spotify
      </button>
    );
  }
  return (
    <div className="glass-soft" style={{ padding: 12, display: 'flex', alignItems: 'center', gap: 10 }}>
      <SpotifyGlyph size={20} color="#1DB954"/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 12, color: '#1DB954', fontWeight: 600 }}>Spotify conectado</div>
        <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.55)' }}>Listo para pinchar</div>
      </div>
      <button onClick={spotify.logout} style={{
        background: 'none', border: 'none', color: 'rgba(255,255,255,0.5)',
        fontSize: 11, cursor: 'pointer', fontFamily: 'inherit', textDecoration: 'underline',
      }}>Salir</button>
    </div>
  );
}

function SpotifyGlyph({ size = 16, color = '#fff' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={color}>
      <path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.36-.66.48-1.02.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.84-.179-.94-.601-.12-.421.18-.84.6-.961 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.281 1.143zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.42 1.56-.299.421-1.02.599-1.559.3z"/>
    </svg>
  );
}

function DjNavItem({ icon, label, badge, active, highlight, onClick }) {
  return (
    <div onClick={onClick} style={{
      display: 'flex', alignItems: 'center', gap: 12, padding: '10px 12px',
      borderRadius: 12, cursor: 'pointer',
      background: active ? 'rgba(255,255,255,0.1)' : 'transparent',
      color: active ? '#fff' : 'rgba(255,255,255,0.7)',
      fontSize: 13.5, fontWeight: active ? 600 : 500,
    }}>
      <span style={{ opacity: active ? 1 : 0.7 }}>{icon}</span>
      <span style={{ flex: 1 }}>{label}</span>
      {badge !== undefined && (
        <span style={{
          minWidth: 22, height: 18, borderRadius: 9, padding: '0 6px',
          background: highlight && badge > 0 ? 'var(--gold-500)' : 'rgba(255,255,255,0.12)',
          color: highlight && badge > 0 ? '#1a1208' : '#fff',
          fontSize: 11, fontWeight: 700, fontFamily: 'var(--font-mono)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>{badge}</span>
      )}
    </div>
  );
}

function DjNowPlaying({ playing, playback, spotify, onTogglePlay, onSkip }) {
  // Prefer the live Spotify playback if available
  const live = playback?.track;
  const isPlaying = spotify.authed && playback ? playback.isPlaying : true;
  const track = live || playing?.track;
  if (!track) {
    return (
      <div className="glass" style={{ padding: 24, color: 'rgba(255,255,255,0.55)', textAlign: 'center', fontSize: 14 }}>
        Sin canción sonando. <span style={{ color: 'var(--gold-500)' }}>Aprueba una para empezar.</span>
      </div>
    );
  }
  return (
    <div className="glass" style={{ padding: 18, display: 'flex', alignItems: 'center', gap: 18 }}>
      <TrackArt track={track} size={72} radius={12}/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontSize: 10.5, color: 'var(--gold-500)', letterSpacing: '0.14em',
          textTransform: 'uppercase', marginBottom: 4, display: 'flex', alignItems: 'center', gap: 8,
        }}>
          {isPlaying && (<><span className="eq-bar"/><span className="eq-bar"/><span className="eq-bar"/><span className="eq-bar"/><span className="eq-bar"/></>)}
          <span style={{ marginLeft: isPlaying ? 6 : 0 }}>{isPlaying ? 'Sonando ahora' : 'En pausa'}</span>
        </div>
        <div className="serif" style={{ fontSize: 24, lineHeight: 1.1, marginBottom: 2 }}>{track.name}</div>
        <div style={{ fontSize: 13, color: 'rgba(255,255,255,0.6)' }}>
          {track.artists}
          {playing && <> · de <span style={{ color: '#fff' }}>{playing.from}</span> para <span style={{ color: 'var(--gold-300)' }}>{playing.to}</span></>}
        </div>
        {playback && (
          <div style={{ marginTop: 12, height: 4, borderRadius: 4, background: 'rgba(255,255,255,0.1)', position: 'relative', overflow: 'hidden' }}>
            <div style={{
              position: 'absolute', left: 0, top: 0, bottom: 0,
              width: `${Math.min(100, (playback.progressMs / track.durationMs) * 100)}%`,
              background: 'linear-gradient(90deg, var(--gold-500), var(--burg-500))', borderRadius: 4,
            }}/>
          </div>
        )}
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <button onClick={onTogglePlay} className="glass-pill" style={{
          width: 44, height: 44, border: 'none', color: '#fff', cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>{isPlaying ? Icon.pause(18) : Icon.play(16)}</button>
        <button onClick={onSkip} className="glass-pill" style={{
          width: 44, height: 44, border: 'none', color: '#fff', cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>{Icon.skip(16)}</button>
      </div>
    </div>
  );
}

function DjPendingRow({ r, onApprove, onReject }) {
  return (
    <div className="glass-soft" style={{
      padding: 14, display: 'flex', alignItems: 'flex-start', gap: 14,
      border: '0.5px solid rgba(229,169,58,0.18)',
    }}>
      <TrackArt track={r.track} size={56} radius={10}/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 4 }}>
          <div style={{ fontSize: 15, fontWeight: 600, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {r.track.name} <span style={{ color: 'rgba(255,255,255,0.5)', fontWeight: 400 }}>· {r.track.artists}</span>
          </div>
          <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.4)', fontFamily: 'var(--font-mono)', flexShrink: 0 }}>
            {fmt.ago(r.createdAt)}
          </div>
        </div>
        <div style={{ fontSize: 12.5, color: 'rgba(255,255,255,0.6)', marginBottom: 8 }}>
          de <strong style={{ color: '#fff', fontWeight: 600 }}>{r.from}</strong>
          {r.to && <> para <strong style={{ color: 'var(--gold-300)', fontWeight: 600 }}>{r.to}</strong></>}
        </div>
        {r.note && (
          <div style={{
            fontSize: 12.5, color: 'rgba(255,255,255,0.75)', fontStyle: 'italic',
            padding: 10, borderRadius: 10, background: 'rgba(255,255,255,0.04)',
            borderLeft: '2px solid var(--gold-500)',
          }}>«{r.note}»</div>
        )}
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, flexShrink: 0 }}>
        <button onClick={onApprove} className="btn-gold" style={{
          height: 32, padding: '0 14px', borderRadius: 9, fontSize: 12.5,
          display: 'flex', alignItems: 'center', gap: 6, border: 'none',
        }}>{Icon.check(13)} Aprobar</button>
        <button onClick={onReject} style={{
          height: 32, padding: '0 14px', borderRadius: 9, cursor: 'pointer',
          background: 'rgba(255,255,255,0.06)', color: 'rgba(255,255,255,0.7)',
          border: '0.5px solid rgba(255,255,255,0.12)', fontSize: 12.5, fontFamily: 'inherit',
          display: 'flex', alignItems: 'center', gap: 6,
        }}>{Icon.x(13)} Rechazar</button>
      </div>
    </div>
  );
}

function DjQueueRow({ r, index, onSkip, onRemove }) {
  return (
    <div className="glass-soft" style={{ padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 14 }}>
      <div style={{ color: 'rgba(255,255,255,0.35)', cursor: 'grab' }}>{Icon.drag(14)}</div>
      <div className="mono tnum" style={{ width: 24, fontSize: 13, color: 'rgba(255,255,255,0.45)', textAlign: 'center' }}>{index + 1}</div>
      <TrackArt track={r.track} size={48} radius={10}/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 14.5, fontWeight: 500, marginBottom: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {r.track.name} <span style={{ color: 'rgba(255,255,255,0.5)', fontWeight: 400 }}>· {r.track.artists}</span>
        </div>
        <div style={{ fontSize: 12, color: 'rgba(255,255,255,0.55)', display: 'flex', alignItems: 'center', gap: 6, whiteSpace: 'nowrap', overflow: 'hidden' }}>
          <span style={{ color: 'rgba(255,255,255,0.85)' }}>{r.from}</span>
          {r.to && (<>
            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
            <span style={{ color: 'var(--gold-300)' }}>{r.to}</span>
          </>)}
        </div>
      </div>
      <button onClick={onSkip} style={{
        height: 28, padding: '0 10px', borderRadius: 8, border: 'none', cursor: 'pointer',
        background: 'rgba(255,255,255,0.08)', color: '#fff', fontSize: 11.5, fontFamily: 'inherit',
        display: 'flex', alignItems: 'center', gap: 5,
      }}>Reproducir ya</button>
      <button onClick={onRemove} style={{
        width: 28, height: 28, borderRadius: 8, border: 'none', cursor: 'pointer',
        background: 'rgba(255,255,255,0.04)', color: 'rgba(255,255,255,0.5)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>{Icon.x(13)}</button>
    </div>
  );
}

function DjUpcoming({ r }) {
  return (
    <div className="glass" style={{ padding: 20 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
        <div style={{ fontSize: 11, color: 'var(--gold-500)', letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 600 }}>
          Próxima
        </div>
        <div className="mono tnum" style={{ fontSize: 12, color: 'rgba(255,255,255,0.5)' }}>{fmt.mmss(r.track.durationMs || 200_000)}</div>
      </div>
      <TrackArt track={r.track} size={120} radius={14}/>
      <div className="serif" style={{ fontSize: 22, lineHeight: 1.1, marginTop: 14 }}>{r.track.name}</div>
      <div style={{ fontSize: 13, color: 'rgba(255,255,255,0.6)', marginTop: 4 }}>{r.track.artists}</div>
      {(r.from || r.to || r.note) && (
        <div style={{
          marginTop: 16, padding: 14, borderRadius: 12,
          background: 'rgba(139,35,50,0.22)', border: '0.5px solid rgba(255,255,255,0.08)',
        }}>
          <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,0.55)', marginBottom: 6 }}>
            de <strong style={{ color: '#fff', fontWeight: 600 }}>{r.from}</strong>
            {r.to && <> para <strong style={{ color: 'var(--gold-300)', fontWeight: 600 }}>{r.to}</strong></>}
          </div>
          {r.note && (
            <div className="serif" style={{ fontSize: 15, lineHeight: 1.35, fontStyle: 'italic' }}>«{r.note}»</div>
          )}
        </div>
      )}
    </div>
  );
}

function DjStat({ label, value, tone }) {
  return (
    <div style={{
      padding: '12px 14px', borderRadius: 12,
      background: tone === 'gold' ? 'rgba(229,169,58,0.12)' : 'rgba(255,255,255,0.04)',
      border: '0.5px solid rgba(255,255,255,0.06)',
    }}>
      <div className="tnum mono" style={{ fontSize: 26, fontWeight: 600, color: tone === 'gold' ? 'var(--gold-500)' : '#fff', lineHeight: 1 }}>{value}</div>
      <div style={{ marginTop: 6, fontSize: 11, color: 'rgba(255,255,255,0.5)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>{label}</div>
    </div>
  );
}

function EmptyState({ text }) {
  return (
    <div style={{ padding: 40, textAlign: 'center', color: 'rgba(255,255,255,0.45)', fontSize: 13.5 }}>
      {text}
    </div>
  );
}

// ════════════════════════════════════════════════════════════
// TV VIEW
// ════════════════════════════════════════════════════════════
function TvView() {
  const [room, roomApi] = useRoom(CFG.room);
  const spotify = useSpotify();

  const [now, setNow] = React.useState(new Date());
  const [, setTick] = React.useState(0);

  React.useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 30_000);
    return () => clearInterval(t);
  }, []);
  React.useEffect(() => {
    const t = setInterval(() => setTick(x => x + 1), 1000);
    return () => clearInterval(t);
  }, []);

  if (!room) return null;
  const playing = room.requests.find(r => r.status === 'playing');
  const upNext  = room.requests.filter(r => r.status === 'next' || r.status === 'queued').slice(0, 6);
  const ticker  = room.requests.filter(r => r.from && r.to).slice(-16);

  const progress = playing && room.nowPlaying
    ? Math.min(1, (Date.now() - room.nowPlaying.startedAt) / room.nowPlaying.durationMs)
    : 0;

  const guestShort = `${location.origin + location.pathname}?role=guest&room=${room.code}`.replace(/^https?:\/\//, '');
  const guestFull  = `${location.origin + location.pathname}?role=guest&room=${room.code}`;

  const ArtBox = ({ track, size = 128 }) => {
    const s = { width: size, height: size, borderRadius: 14, flexShrink: 0, objectFit: 'cover', boxShadow: '0 8px 28px rgba(0,0,0,0.5)' };
    if (track?.image) return <img src={track.image} alt="" style={s}/>;
    return <div style={{ ...s, overflow: 'hidden' }}><Cover seed={track?._cover ?? 0} size={size} radius={14}/></div>;
  };

  return (
    <div style={{ minHeight: '100vh', position: 'relative', overflow: 'hidden', background: '#060d1a' }}>
      {/* Aurora background */}
      <div style={{ position: 'absolute', inset: 0 }}>
        <div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(ellipse at 15% 20%, rgba(27,58,102,0.95) 0%, transparent 52%), radial-gradient(ellipse at 85% 80%, rgba(139,35,50,0.75) 0%, transparent 52%)' }}/>
        <div style={{ position: 'absolute', top: '0%', right: '5%', width: 480, height: 480, borderRadius: '50%', background: 'radial-gradient(circle, var(--gold-500), transparent 65%)', filter: 'blur(90px)', opacity: 0.22 }}/>
      </div>
      <div className="grain" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}/>

      <div style={{ position: 'relative', zIndex: 1, minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>

        {/* ── Header ── */}
        <header style={{ padding: '14px 20px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexShrink: 0, borderBottom: '0.5px solid rgba(255,255,255,0.07)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <FSJAMark size={28}/>
            <div>
              <div style={{ fontSize: 9, letterSpacing: '0.2em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.38)', fontWeight: 500 }}>Fundación San Juan de Ávila</div>
              <div className="serif" style={{ fontSize: 16, lineHeight: 1.15 }}>
                Sonarium · <span style={{ color: 'var(--gold-500)' }}>{room.code}</span>
              </div>
            </div>
          </div>
          <div className="glass-pill" style={{ height: 30, padding: '0 12px', display: 'flex', alignItems: 'center', gap: 7, fontSize: 11, letterSpacing: '0.1em', textTransform: 'uppercase', fontWeight: 500, flexShrink: 0 }}>
            <span className="live-dot"/>
            {now.toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' })}
          </div>
        </header>

        {/* ── Body: 2-col on ≥768px, 1-col on mobile ── */}
        <div className="tv-body" style={{ flex: 1, minHeight: 0 }}>

          {/* Left: Now Playing */}
          <section className="glass" style={{ padding: 20, display: 'flex', flexDirection: 'column' }}>
            {/* Section label */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 18, fontSize: 10, color: 'var(--gold-500)', letterSpacing: '0.2em', textTransform: 'uppercase', fontWeight: 700 }}>
              <span className="eq-bar"/><span className="eq-bar"/><span className="eq-bar"/>
              Sonando ahora
            </div>

            {playing ? (
              <>
                {/* Art + meta */}
                <div className="tv-now-art">
                  <ArtBox track={playing.track}/>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div className="serif" style={{ fontSize: 26, lineHeight: 1.05, marginBottom: 5, letterSpacing: '-0.01em' }}>
                      {playing.track.name}
                    </div>
                    <div style={{ fontSize: 15, color: 'rgba(255,255,255,0.58)', marginBottom: (playing.from || playing.to || playing.note) ? 14 : 0 }}>
                      {playing.track.artists}
                    </div>

                    {(playing.from || playing.to || playing.note) && (
                      <div style={{ padding: '12px 14px', borderRadius: 12, background: 'linear-gradient(135deg, rgba(139,35,50,0.35), rgba(139,35,50,0.12))', border: '0.5px solid rgba(229,169,58,0.22)', position: 'relative' }}>
                        <div style={{ position: 'absolute', top: -9, left: 12, background: 'var(--gold-500)', color: '#1a1208', fontSize: 9, fontWeight: 800, letterSpacing: '0.15em', textTransform: 'uppercase', padding: '2px 7px', borderRadius: 4 }}>
                          Dedicatoria
                        </div>
                        <div style={{ fontSize: 13, color: 'rgba(255,255,255,0.7)', marginBottom: playing.note ? 6 : 0, marginTop: 2 }}>
                          de <strong style={{ color: '#fff', fontWeight: 600 }}>{playing.from}</strong>
                          {playing.to && <> para <strong style={{ color: 'var(--gold-300)', fontWeight: 600 }}>{playing.to}</strong></>}
                        </div>
                        {playing.note && (
                          <div className="serif" style={{ fontSize: 14, lineHeight: 1.4, fontStyle: 'italic', color: 'rgba(255,255,255,0.92)' }}>
                            «{playing.note}»
                          </div>
                        )}
                      </div>
                    )}
                  </div>
                </div>

                {/* Progress bar */}
                <div style={{ marginTop: 'auto', paddingTop: 20 }}>
                  <div style={{ height: 3, borderRadius: 3, background: 'rgba(255,255,255,0.08)', overflow: 'hidden' }}>
                    <div style={{ height: '100%', width: `${progress * 100}%`, background: 'linear-gradient(90deg, var(--gold-500), var(--burg-500))', transition: 'width 1s linear' }}/>
                  </div>
                  <div className="tnum mono" style={{ display: 'flex', justifyContent: 'space-between', marginTop: 5, fontSize: 11, color: 'rgba(255,255,255,0.4)' }}>
                    <span>{fmt.mmss(progress * (playing.track.durationMs || 200_000))}</span>
                    <span>{fmt.mmss(playing.track.durationMs || 200_000)}</span>
                  </div>
                </div>
              </>
            ) : (
              <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: '40px 0', color: 'rgba(255,255,255,0.45)', textAlign: 'center' }}>
                <div style={{ fontSize: 40, marginBottom: 12, opacity: 0.4 }}>♪</div>
                <div className="serif" style={{ fontSize: 22, marginBottom: 8 }}>Sin música</div>
                <div style={{ fontSize: 13 }}>Escanea el QR y pide la primera canción.</div>
              </div>
            )}
          </section>

          {/* Right: Queue + QR */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>

            {/* Queue */}
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 8 }}>
              <div style={{ fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase', fontWeight: 700, color: 'rgba(255,255,255,0.4)', padding: '0 2px' }}>
                A continuación
              </div>
              {upNext.length === 0 ? (
                <div className="glass-soft" style={{ padding: '18px 16px', borderRadius: 14, textAlign: 'center', color: 'rgba(255,255,255,0.38)', fontSize: 13 }}>
                  La cola está vacía.
                </div>
              ) : upNext.map((r, i) => (
                <div key={r.id} className="glass-soft" style={{ padding: '9px 12px', borderRadius: 12, display: 'flex', alignItems: 'center', gap: 10 }}>
                  <div className="tnum mono" style={{ width: 18, fontSize: 12, color: i === 0 ? 'var(--gold-500)' : 'rgba(255,255,255,0.3)', fontWeight: 700, textAlign: 'center', flexShrink: 0 }}>
                    {String(i + 1).padStart(2, '0')}
                  </div>
                  <TrackArt track={r.track} size={38} radius={7}/>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div className="serif" style={{ fontSize: 14, lineHeight: 1.2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                      {r.track.name}
                    </div>
                    <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,0.45)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                      {r.track.artists}
                      {(r.from && r.to) && <span style={{ color: 'rgba(255,255,255,0.3)' }}> · {r.from} → {r.to}</span>}
                    </div>
                  </div>
                </div>
              ))}
            </div>

            {/* QR card */}
            <div className="glass" style={{ padding: 16, display: 'flex', alignItems: 'center', gap: 14 }}>
              <div style={{ background: '#fff', padding: 7, borderRadius: 9, flexShrink: 0 }}>
                <RealQR url={guestFull} size={72} dark="#0a1a2e"/>
              </div>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--gold-500)', fontWeight: 700, marginBottom: 4 }}>
                  Pide tu canción
                </div>
                <div className="serif" style={{ fontSize: 18, lineHeight: 1.1, marginBottom: 6 }}>Únete a la sala</div>
                <div className="mono" style={{ fontSize: 10, color: 'rgba(255,255,255,0.45)', wordBreak: 'break-all', lineHeight: 1.5 }}>
                  {guestShort}
                </div>
              </div>
            </div>

          </div>
        </div>

        {/* ── Ticker ── */}
        {ticker.length > 0 && (
          <div style={{ margin: '0 20px 20px', height: 42, borderRadius: 12, background: 'rgba(255,255,255,0.04)', backdropFilter: 'blur(12px)', border: '0.5px solid rgba(255,255,255,0.08)', display: 'flex', alignItems: 'center', overflow: 'hidden', flexShrink: 0 }}>
            <div className="marquee-track">
              {[...ticker, ...ticker].map((r, i) => (
                <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, flexShrink: 0 }}>
                  <span style={{ color: 'var(--gold-500)', fontSize: 12 }}>♪</span>
                  <span style={{ fontSize: 13, color: 'rgba(255,255,255,0.82)' }}>
                    <strong>{r.from}</strong> dedica «{r.track.name}» a <strong style={{ color: 'var(--gold-300)' }}>{r.to}</strong>
                  </span>
                  <span style={{ color: 'rgba(255,255,255,0.18)', padding: '0 16px' }}>·</span>
                </div>
              ))}
            </div>
          </div>
        )}

      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════
// QR SCREEN — pantalla proyectable con QR + sala + link
// ════════════════════════════════════════════════════════════
function QrScreen() {
  const [room] = useRoom(CFG.room);
  if (!room) return null;

  const djName   = localStorage.getItem('sonarium.config.djName') || room.djName || '';
  const guestUrl = `${location.origin + location.pathname}?role=guest&room=${room.code}`;
  const shortUrl = guestUrl.replace(/^https?:\/\//, '');

  return (
    <AuroraScreen>
      <div style={{
        minHeight: '100vh', display: 'flex', alignItems: 'center',
        justifyContent: 'center', padding: '40px 24px',
      }}>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 28, textAlign: 'center', maxWidth: 480, width: '100%' }}>

          {/* Logo + DJ */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <FSJAMark size={48}/>
            <div style={{ textAlign: 'left' }}>
              <div className="serif" style={{ fontSize: 34, lineHeight: 1 }}>Sonarium</div>
              {djName && (
                <div style={{ fontSize: 13, color: 'rgba(255,255,255,.5)', marginTop: 4 }}>
                  con <strong style={{ color: '#fff' }}>{djName}</strong>
                </div>
              )}
            </div>
          </div>

          {/* Tarjeta principal */}
          <div className="glass" style={{ padding: 28, width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 22 }}>

            {/* QR */}
            <div style={{
              background: '#fff', borderRadius: 16, padding: 14,
              boxShadow: '0 0 60px rgba(229,169,58,.2), 0 8px 32px rgba(0,0,0,.4)',
            }}>
              <RealQR url={guestUrl} size={220}/>
            </div>

            {/* Sala */}
            <div>
              <div style={{ fontSize: 11, letterSpacing: '.16em', textTransform: 'uppercase', color: 'var(--gold-500)', fontWeight: 600, marginBottom: 6 }}>
                Sala
              </div>
              <div className="mono" style={{ fontSize: 38, fontWeight: 700, letterSpacing: '.06em', lineHeight: 1 }}>
                {room.code}
              </div>
            </div>

            {/* Divider */}
            <div style={{ width: '100%', borderTop: '1px solid rgba(255,255,255,.08)' }}/>

            {/* URL */}
            <div style={{ width: '100%' }}>
              <div style={{ fontSize: 12, color: 'rgba(255,255,255,.45)', marginBottom: 10 }}>
                O entra desde el navegador en:
              </div>
              <div className="glass-soft mono" style={{
                fontSize: 15, padding: '12px 16px', borderRadius: 12,
                wordBreak: 'break-all', lineHeight: 1.6, color: 'rgba(255,255,255,.85)',
              }}>
                {shortUrl}
              </div>
            </div>

          </div>

          {/* Pie */}
          <div style={{ fontSize: 12, color: 'rgba(255,255,255,.25)' }}>
            Pide tu canción · {room.stats?.listeners ?? 1} conectados
          </div>

        </div>
      </div>
    </AuroraScreen>
  );
}

// ════════════════════════════════════════════════════════════
// ROUTER + MOUNT
// ════════════════════════════════════════════════════════════
function App() {
  // Auto-handle Spotify OAuth return: if there's a ?code= param, the
  // useSpotify hook in the eventual view will exchange it. We still want
  // to land on a role afterwards, so default to 'dj' when returning from auth.
  const initialRole = (() => {
    const u = new URL(location.href);
    if (u.searchParams.has('code')) return 'dj';
    return CFG.role || '';
  })();
  const [role, setRole] = React.useState(initialRole);

  const view = role === 'guest' ? <GuestView/>
             : role === 'dj'    ? <DjView/>
             : role === 'tv'    ? <TvView/>
             : role === 'qr'    ? <QrScreen/>
             : <DjWelcome/>;

  return (
    <ToastProvider>
      {view}
    </ToastProvider>
  );
}

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