// ============ QUEUE / AUTOMIX ============
function Queue({ queue, onLoadTo, onRemove, onReorder, automix, onAutomixToggle, onFadeTimeChange, deckA, deckB }) {
  const [dragIdx, setDragIdx] = useState(null);
  const [dragOverIdx, setDragOverIdx] = useState(null);
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);

  const nextTrack = useMemo(() => {
    return queue.find(t => t.id !== deckA.track?.id && t.id !== deckB.track?.id && !t.loading && !(automix.playedIds || []).includes(t.id));
  }, [queue, deckA.track, deckB.track, automix.playedIds]);

  // For the "now/next" preview: if automix is fading, the deck ahead in
  // crossfade direction is "now playing" and the other is "coming up".
  const nowTrack = useMemo(() => {
    if (deckA.playing && deckB.playing) {
      // both — pick the louder one (simplification: deck closer to crossfader)
      return deckA.progress > deckB.progress ? deckA.track : deckB.track;
    }
    return deckA.playing ? deckA.track : deckB.playing ? deckB.track : null;
  }, [deckA, deckB]);

  // Outgoing-track progress drives the progress bar shown on the automix card
  const outgoingProgress = useMemo(() => {
    if (!automix.on) return 0;
    return Math.max(deckA.progress || 0, deckB.progress || 0);
  }, [automix.on, deckA.progress, deckB.progress]);

  // ----- Set-length estimation (so the user knows roughly how long their
  // automix will last). Sum the duration of every queued track that hasn't
  // already aired or finished. Subtract some seconds for crossfade overlaps.
  const setEstimate = useMemo(() => {
    const played = automix.playedIds || [];
    const onDeck = [deckA.track?.id, deckB.track?.id].filter(Boolean);
    const remainingTracks = queue.filter(t =>
      !played.includes(t.id) &&
      !onDeck.includes(t.id) &&
      !t.loading &&
      t.source !== 'soundcloud'
    );
    let secs = remainingTracks.reduce((s, t) => s + (t.duration || 180), 0);
    // Add what's left of the currently playing tracks
    if (deckA.track && deckA.playing) secs += (deckA.track.duration || 180) * (1 - (deckA.progress || 0));
    if (deckB.track && deckB.playing) secs += (deckB.track.duration || 180) * (1 - (deckB.progress || 0));
    // Subtract crossfade overlaps (~fadeTime per transition)
    const transitions = remainingTracks.length;
    secs -= transitions * (automix.fadeTime || 8) * 0.5;
    return {
      seconds: Math.max(0, Math.round(secs)),
      remainingCount: remainingTracks.length,
      playedCount: played.length,
    };
  }, [queue, deckA, deckB, automix.playedIds, automix.fadeTime]);

  const fmtMins = (s) => {
    if (s < 60) return `${s}s`;
    if (s < 3600) return `${Math.round(s / 60)} min`;
    const h = Math.floor(s / 3600);
    const m = Math.round((s - h * 3600) / 60);
    return `${h}h ${m}m`;
  };

  const phaseLabel = automix.phase === 'fading' ? 'MIXING'
    : automix.phase === 'playing' ? 'ON AIR'
    : automix.phase === 'starting' ? 'STARTING…'
    : automix.phase === 'done' ? 'FINISHED'
    : automix.on ? 'ON AIR' : 'READY';

  const fmtTitle = (t, n = 22) => !t ? '—' : (t.title.length > n ? t.title.slice(0, n) + '…' : t.title);

  // "Short set" = under 15 min remaining — we'll warn the user.
  const SHORT_SET_THRESHOLD = 15 * 60;
  const isShortSet = setEstimate.seconds < SHORT_SET_THRESHOLD;

  const handleStartClick = () => {
    if (automix.on) {
      onAutomixToggle();
      return;
    }
    if (queue.length === 0) return;
    setConfirmOpen(true);
  };
  const confirmStart = () => {
    setConfirmOpen(false);
    onAutomixToggle();
  };

  return (
    <div className="panel queue" data-screen-label="Queue">
      <div className="queue-head">
        <div className="queue-title">Up Next</div>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.1em' }}>
          {queue.length} TRACK{queue.length === 1 ? '' : 'S'}
        </div>
      </div>

      <div className={`automix-card ${automix.on ? 'is-on' : ''} ${automix.phase === 'fading' ? 'is-fading' : ''}`}>
        <div className="automix-head">
          <div className="automix-label">
            <Icon name="sparkles" size={12} /> AUTOMIX
          </div>
          <div className={`automix-phase ${automix.on ? 'on' : ''}`}>
            {automix.on && <span className="am-led" />}
            {phaseLabel}
          </div>
        </div>

        {/* Now / Next preview — only shown when automix is on or queue is non-empty */}
        {(automix.on || queue.length > 0) && (
          <div className="automix-preview">
            <div className="amp-row now">
              <span className="amp-tag">NOW</span>
              <span className="amp-title">{fmtTitle(nowTrack) || (automix.on ? 'starting…' : 'idle')}</span>
            </div>
            <div className="amp-row next">
              <span className="amp-tag">NEXT</span>
              <span className="amp-title">{fmtTitle(nextTrack) || 'queue empty'}</span>
            </div>
            {automix.on && (
              <div className="amp-progress" title="Outgoing track progress — crossfade begins at 85%">
                <div className="amp-progress-fill" style={{ width: `${Math.round(outgoingProgress * 100)}%` }} />
                <div className="amp-progress-marker" style={{ left: '85%' }} title="Fade trigger" />
              </div>
            )}
          </div>
        )}

        <button
          className={`automix-btn ${automix.on ? 'on' : ''}`}
          onClick={handleStartClick}
          disabled={!automix.on && queue.length === 0}
        >
          <Icon name={automix.on ? 'pause' : 'play'} size={14} />
          {automix.on ? 'STOP AUTOMIX' : (queue.length === 0 ? 'ADD TRACKS TO START' : 'START AUTOMIX')}
        </button>

        {/* Friendly time-remaining caption — plain English, no DJ jargon */}
        <div className="automix-caption">
          {automix.on ? (
            <>
              <span className="amc-main">
                {setEstimate.seconds > 0
                  ? `≈ ${fmtMins(setEstimate.seconds)} of music left`
                  : 'Last track playing…'}
              </span>
              {setEstimate.playedCount > 0 && (
                <span className="amc-sub">{setEstimate.playedCount} song{setEstimate.playedCount === 1 ? '' : 's'} played</span>
              )}
              <button className="amc-gear" onClick={() => setSettingsOpen(o => !o)} title="Mix settings">⚙</button>
            </>
          ) : queue.length > 0 ? (
            <>
              <span className="amc-main">
                {setEstimate.seconds > 0
                  ? `≈ ${fmtMins(setEstimate.seconds)} of music ready`
                  : 'Add some tracks below'}
              </span>
              <button className="amc-gear" onClick={() => setSettingsOpen(o => !o)} title="Mix settings">⚙</button>
            </>
          ) : (
            <span className="amc-main amc-empty">Drop tracks below or paste a YouTube URL</span>
          )}
        </div>

        {/* Settings drawer — hidden until ⚙ is clicked. Holds the technical bits. */}
        {settingsOpen && (
          <div className="automix-settings">
            <label className="ams-row">
              <span className="ams-name">Crossfade length</span>
              <input
                type="range"
                min="2"
                max="20"
                step="1"
                value={automix.fadeTime}
                onChange={(e) => onFadeTimeChange?.(parseInt(e.target.value))}
                className="ams-slider"
              />
              <span className="ams-val">{automix.fadeTime}s</span>
            </label>
            <div className="ams-help">How long each song blends into the next. Shorter = punchier, longer = smoother.</div>
          </div>
        )}
      </div>

      {/* Confirmation popup before starting the auto-mix */}
      {confirmOpen && (
        <div className="am-modal-backdrop" onClick={() => setConfirmOpen(false)}>
          <div className="am-modal" onClick={(e) => e.stopPropagation()}>
            <div className="am-modal-icon">
              <Icon name="sparkles" size={20} />
            </div>
            <div className="am-modal-title">Start automix?</div>
            <div className="am-modal-stat">
              <span className="am-modal-stat-num">{fmtMins(setEstimate.seconds)}</span>
              <span className="am-modal-stat-lbl">of non-stop music</span>
            </div>
            <div className="am-modal-meta">
              {setEstimate.remainingCount} track{setEstimate.remainingCount === 1 ? '' : 's'} ready
              {(automix.playedIds || []).length > 0 && <> · {automix.playedIds.length} already played</>}
            </div>
            {isShortSet && (
              <div className="am-modal-warn">
                <Icon name="sparkles" size={12} />
                <span>Want a longer party? Drop more songs first — your set will end after about {fmtMins(setEstimate.seconds)}.</span>
              </div>
            )}
            {!isShortSet && (
              <div className="am-modal-tip">
                Tip: you can keep adding songs while the music plays.
              </div>
            )}
            <div className="am-modal-actions">
              <button className="am-modal-btn cancel" onClick={() => setConfirmOpen(false)}>
                {isShortSet ? 'Add more first' : 'Cancel'}
              </button>
              <button className="am-modal-btn go" onClick={confirmStart}>
                <Icon name="play" size={12} /> Start playing
              </button>
            </div>
          </div>
        </div>
      )}

      <div className="queue-list">
        {queue.length === 0 && (
          <div className="queue-empty">
            <span className="queue-empty-icon">♫</span>
            Paste a YouTube URL up top, or drop MP3/WAV files
          </div>
        )}
        {queue.map((t, i) => {
          const loadedA = deckA.track?.id === t.id;
          const loadedB = deckB.track?.id === t.id;
          const isLoading = !!t.loading;
          return (
            <div
              key={t.id}
              className={`queue-item ${loadedA ? 'loaded-a' : ''} ${loadedB ? 'loaded-b' : ''} ${dragIdx === i ? 'dragging' : ''} ${isLoading ? 'loading' : ''}`}
              data-source={t.source || 'local'}
              draggable={!isLoading}
              onDragStart={(e) => {
                if (isLoading) return;
                setDragIdx(i);
                // Advertise the track id so deck drop zones can pick it up.
                // Keep the legacy mime while the renamed app is still in use
                // from older tabs and cached bundles.
                try {
                  e.dataTransfer.setData('application/x-djanything-track-id', t.id);
                  e.dataTransfer.setData('text/x-djanything-track-id', t.id);
                  e.dataTransfer.setData('text/x-mixfm-track-id', t.id);
                } catch {}
                e.dataTransfer.effectAllowed = 'copyMove';
              }}
              onDragOver={(e) => { e.preventDefault(); setDragOverIdx(i); }}
              onDrop={() => { if (dragIdx != null) onReorder(dragIdx, i); setDragIdx(null); setDragOverIdx(null); }}
              onDragEnd={() => { setDragIdx(null); setDragOverIdx(null); }}
            >
              <div className="queue-thumb">
                {t.thumb ? <img src={t.thumb} alt="" /> : <div className="queue-thumb-placeholder" />}
                {isLoading && <div className="queue-thumb-spinner" />}
              </div>
              <div className="queue-info">
                <div className="queue-item-title">
                  {t.source === 'soundcloud' && <span className="src-badge sc" title="SoundCloud — limited mode">SC</span>}
                  {t.source === 'youtube' && <span className="src-badge yt" title="YouTube">YT</span>}
                  {t.source === 'spotify' && <span className="src-badge sp" title="Spotify → YouTube">SP</span>}
                  {t.title}
                </div>
                {isLoading ? (
                  <div className="queue-item-progress">
                    <div className="qi-bar"><div className="qi-bar-fill" style={{ width: `${Math.round((t.progress || 0) * 100)}%` }} /></div>
                    <span className="qi-status">{t.statusText || 'Fetching audio…'} {Math.round((t.progress || 0) * 100)}%</span>
                  </div>
                ) : t.analyzing ? (
                  <div className="queue-item-progress">
                    <div className="qi-bar analyzing"><div className="qi-bar-fill" style={{ width: `${Math.round((t.analyzeProgress || 0) * 100)}%` }} /></div>
                    <span className="qi-status">Analyzing beats… {Math.round((t.analyzeProgress || 0) * 100)}%</span>
                  </div>
                ) : (
                  <div className="queue-item-meta">
                    <span style={{ color: 'var(--accent-cyan)' }}>{t.bpm?.toFixed(1)}</span>
                    <span className="sep">•</span>
                    <span style={{ color: 'var(--accent-violet)' }}>{t.key}</span>
                    <span className="sep">•</span>
                    <span>{t.duration ? `${Math.floor(t.duration / 60)}:${String(Math.floor(t.duration % 60)).padStart(2, '0')}` : '—'}</span>
                    {t.analyzeConfidence != null && t.analyzeConfidence < 0.3 && (
                      <span className="analyze-low" title="Low confidence — beat detection may need manual nudging">⚠ low conf</span>
                    )}
                    {t.source === 'soundcloud' && <span className="sc-hint" title="Volume + crossfade work. EQ/FX disabled on SoundCloud tracks.">· vol-only</span>}
                  </div>
                )}
              </div>
              <div className="queue-actions">
                <button className="qa-btn a" onClick={() => onLoadTo('a', t)} title="Load this track to Deck A (left)" disabled={isLoading}>A</button>
                <button className="qa-btn b" onClick={() => onLoadTo('b', t)} title="Load this track to Deck B (right)" disabled={isLoading}>B</button>
                <button className="qa-btn" onClick={() => onRemove(t.id)} title="Remove this track from the queue"><Icon name="x" size={10} /></button>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ============ TOP BAR ============
function TopBar({ onRecToggle, recording, onUpload, onLoadDemos, loadingDemos }) {
  return (
    <div className="topbar">
      <div className="logo" title="djanything.com — mix anything on the internet">
        <div className="logo-mark" />
        <span>djanything<b>.com</b></span>
      </div>
      <div className="top-actions">
        <button className="top-action-btn upload" onClick={onUpload} title="Upload your own MP3 or WAV files from this computer">
          <Icon name="upload" size={14} /> Upload
        </button>
        <button className="top-action-btn demos" onClick={onLoadDemos} disabled={loadingDemos} title="Load a few demo tracks so you can try the app right now">
          {loadingDemos ? '…' : 'DEMOS'}
        </button>
      </div>
      <div className="top-right">
        <button className={`rec-btn ${recording ? 'recording' : ''}`} onClick={onRecToggle} title={recording ? 'Stop recording and download the mix as a WAV file' : 'Record everything you mix — you can save the result when you stop'}>
          <span className="dot" />
          {recording ? 'REC' : 'RECORD'}
        </button>
        <button className="icon-btn" title="Headphone cue — preview the next track in your headphones without sending it to the speakers (coming soon)"><Icon name="headphone" size={16} /></button>
        <button className="icon-btn" title="Microphone input — talk over the music (coming soon)"><Icon name="mic" size={16} /></button>
        <button className="icon-btn" title="App settings"><Icon name="settings" size={16} /></button>
      </div>
    </div>
  );
}

Object.assign(window, { Queue, TopBar });
