// Playlists — personal collection page. Mirror of the same surface
// the ingame app shows in the phone music player: every playlist
// shown here is also visible on the phone (and vice versa) because
// both surfaces read/write the same two MySQL tables.
//
// URL routing same shape as Artists:
//   • #/playlists                  → list of my playlists
//   • #/playlists/p<12-hex>        → detail view of a specific one
//
// Creation flow: header button on the list view → prompt for a
// name → POST to /api/playlists → cache refresh. Detail view holds
// the rename / delete / "add tracks" actions.

function PlaylistsScreen({ me, identifier, setRoute }) {
  // Re-use the `identifier` route-arg slot (we share it with the
  // Artists page — fine because it's just the part after the slash
  // in the URL hash). Here it's a playlist id, not a player id.
  if (identifier) {
    return <PlaylistDetail
      me={me} playlistId={identifier}
      onBack={() => setRoute('playlists')}/>;
  }
  return <PlaylistsList onOpen={(id) => setRoute('playlists', id)}/>;
}

// ─── LIST VIEW ──────────────────────────────────────────────────────

function PlaylistsList({ onOpen }) {
  const playlists = useMyPlaylists();

  const handleCreate = async () => {
    const name = prompt('Wie soll die Playlist heißen?');
    if (!name || !name.trim()) return;
    try {
      const fresh = await MyPlaylists.create(name.trim());
      toast.success('Playlist angelegt.');
      // Open the new one right away — the user almost certainly
      // wants to add tracks next.
      const created = (fresh || []).find(p => p.name === name.trim());
      if (created) onOpen(created.id);
    } catch (e) {
      toast.error('Anlegen fehlgeschlagen: ' + e.message);
    }
  };

  return (
    <div style={{ padding: '32px 36px 140px', maxWidth: 1240, margin: '0 auto' }}>

      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 22, flexWrap: 'wrap', gap: 18 }}>
        <div>
          <Eyebrow style={{ marginBottom: 6 }}>
            {playlists.length} {playlists.length === 1 ? 'Playlist' : 'Playlists'}
          </Eyebrow>
          <h1 style={{ fontWeight: 800, fontSize: 40, lineHeight: 1.05, letterSpacing: '-0.02em', margin: 0 }}>
            Playlists
          </h1>
          <p style={{ fontSize: 14.5, color: 'var(--fg-2)', marginTop: 8, maxWidth: 640, opacity: 0.82 }}>
            Deine eigenen Sammlungen. Alles was du hier anlegst taucht auch im
            Musik-Player auf deinem Handy ingame auf — und umgekehrt.
          </p>
        </div>
        <Button variant="primary" size="md" icon="plus" onClick={handleCreate}>
          Neue Playlist
        </Button>
      </div>

      {playlists.length === 0 ? (
        <EmptyState
          icon="list" iconColor="var(--lila-300)" orb="var(--lila-500)"
          title="Noch keine Playlists"
          description="Leg deine erste an — kannst du beliebig viele machen."
          cta={
            <Button variant="primary" size="md" icon="plus" onClick={handleCreate}>
              Erste Playlist anlegen
            </Button>
          }
        />
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 16 }}>
          {playlists.map(p => (
            <PlaylistTile key={p.id} playlist={p} onClick={() => onOpen(p.id)}/>
          ))}
        </div>
      )}
    </div>
  );
}

// Tile in the list grid. Shows the playlist name + how many tracks
// it has. A more elaborate version would show a 2×2 mosaic of the
// first four track covers, but that requires loading each playlist
// individually — saving that for a follow-up if the plain version
// feels too dry.
function PlaylistTile({ playlist, onClick }) {
  // Deterministic gradient per playlist so tiles aren't a sea of
  // identical purple. Hash the id into the palette set we already
  // use for fallback avatars.
  const colors = fallbackAvatar(playlist.id);
  return (
    <div onClick={onClick} style={{ cursor: 'pointer' }}>
      <Glass radius={18} padding={14} hover>
        <div style={{
          width: '100%', aspectRatio: '1', borderRadius: 14,
          background: `linear-gradient(135deg, ${colors[0]}, ${colors[1]})`,
          position: 'relative', overflow: 'hidden',
          boxShadow: `0 6px 20px ${colors[0]}55`,
          display: 'flex', alignItems: 'flex-end', justifyContent: 'flex-start',
          padding: 14,
        }}>
          {/* Pull-corner gloss — same idiom as Cover */}
          <div style={{
            position: 'absolute', top: '-20%', right: '-20%',
            width: '60%', height: '60%', borderRadius: '50%',
            background: 'rgba(255,247,236,0.25)', filter: 'blur(12px)',
          }}/>
          <ApIcon name="list" size={32} color="var(--foam)"
            style={{ position: 'relative', opacity: 0.85 }}/>
        </div>
        <div style={{ fontSize: 14, fontWeight: 700, marginTop: 12, color: 'var(--foam)',
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {playlist.name}
        </div>
        <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginTop: 2 }}>
          {playlist.trackCount} {playlist.trackCount === 1 ? 'Track' : 'Tracks'}
          {playlist.updatedAt ? ` · ${timeAgo(playlist.updatedAt)}` : ''}
        </div>
      </Glass>
    </div>
  );
}

// ─── DETAIL VIEW ────────────────────────────────────────────────────

function PlaylistDetail({ me, playlistId, onBack }) {
  const audio = useAudioStatus();
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  const load = React.useCallback(async () => {
    setLoading(true);
    try {
      const out = await Api.playlists.get(playlistId);
      setData(out);
    } catch (e) {
      toast.error('Playlist laden fehlgeschlagen: ' + e.message);
      setData(null);
    } finally {
      setLoading(false);
    }
  }, [playlistId]);

  React.useEffect(() => { load(); }, [load]);

  const onRename = async () => {
    if (!data) return;
    const name = prompt('Neuer Name:', data.name);
    if (!name || !name.trim() || name.trim() === data.name) return;
    try {
      await MyPlaylists.rename(playlistId, name.trim());
      toast.success('Umbenannt.');
      await load();
    } catch (e) {
      toast.error('Umbenennen fehlgeschlagen: ' + e.message);
    }
  };

  const onDelete = async () => {
    if (!data) return;
    if (!confirm(`Playlist „${data.name}" löschen?\n\nDie Tracks selbst werden NICHT gelöscht — nur die Sammlung.`)) return;
    try {
      await MyPlaylists.remove(playlistId);
      toast.info('Playlist gelöscht.');
      onBack();
    } catch (e) {
      toast.error('Löschen fehlgeschlagen: ' + e.message);
    }
  };

  const onRemoveTrack = async (trackId) => {
    try {
      await MyPlaylists.removeTrack(playlistId, trackId);
      // Optimistic: cut the row out of state immediately so the UI
      // updates without waiting for the full refetch.
      setData(d => d ? { ...d, tracks: d.tracks.filter(t => t.id !== trackId) } : d);
    } catch (e) {
      toast.error('Track entfernen fehlgeschlagen: ' + e.message);
    }
  };

  const playAll = () => {
    if (!data?.tracks?.length) return;
    audio.play(data.tracks[0]);
    // No real "play queue" support yet — the next-track button on
    // the now-playing bar is muted. Starts the first track for now.
  };

  if (loading && !data) {
    return (
      <div style={{ padding: '60px 32px', textAlign: 'center', color: 'var(--fg-3)' }}>
        Lade Playlist…
      </div>
    );
  }
  if (!data) {
    return (
      <div style={{ padding: '60px 32px 140px', maxWidth: 620, margin: '0 auto' }}>
        <Glass radius={20} padding={36} style={{ textAlign: 'center' }}>
          <ApIcon name="circle-question" size={32} color="var(--fg-3)"/>
          <h2 style={{ fontSize: 20, fontWeight: 800, margin: '12px 0 6px' }}>
            Playlist nicht gefunden
          </h2>
          <Button variant="secondary" size="sm" icon="chevron-left" onClick={onBack}>
            Zurück
          </Button>
        </Glass>
      </div>
    );
  }

  const colors = fallbackAvatar(data.id);

  return (
    <div style={{ padding: '32px 36px 140px', maxWidth: 1100, margin: '0 auto' }}>

      <button onClick={onBack} style={{
        display: 'inline-flex', alignItems: 'center', gap: 8,
        background: 'transparent', border: 'none', padding: '6px 0',
        cursor: 'pointer', color: 'var(--fg-2)', fontSize: 13.5, fontWeight: 600,
        fontFamily: 'inherit', marginBottom: 14,
      }}>
        <ApIcon name="chevron-left" size={12}/> Zurück zu allen Playlists
      </button>

      {/* Header — big cover, name, count, action buttons */}
      <Glass radius={24} padding={28} style={{ marginBottom: 18 }} orb="var(--lila-500)">
        <div style={{ display: 'flex', alignItems: 'center', gap: 22, flexWrap: 'wrap' }}>
          <div style={{
            width: 140, height: 140, borderRadius: 20, flexShrink: 0,
            background: `linear-gradient(135deg, ${colors[0]}, ${colors[1]})`,
            position: 'relative', overflow: 'hidden',
            boxShadow: '0 12px 36px rgba(20,8,40,0.55)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <div style={{
              position: 'absolute', top: '-20%', right: '-20%',
              width: '60%', height: '60%', borderRadius: '50%',
              background: 'rgba(255,247,236,0.25)', filter: 'blur(12px)',
            }}/>
            <ApIcon name="list" size={56} color="var(--foam)" style={{ position: 'relative', opacity: 0.9 }}/>
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <Eyebrow style={{ marginBottom: 6 }}>Playlist</Eyebrow>
            <h1 style={{ fontWeight: 800, fontSize: 36, lineHeight: 1.05, letterSpacing: '-0.02em', margin: 0 }}>
              {data.name}
            </h1>
            <div style={{ marginTop: 6, fontSize: 13, color: 'var(--fg-2)' }}>
              {data.trackCount} {data.trackCount === 1 ? 'Track' : 'Tracks'}
              {data.updatedAt
                ? <> · zuletzt bearbeitet {timeAgo(data.updatedAt)}</>
                : null}
            </div>
            <div style={{ display: 'flex', gap: 8, marginTop: 16, flexWrap: 'wrap' }}>
              <Button variant="reward" size="md" icon="play"
                disabled={!data.tracks?.length}
                onClick={playAll}>
                Abspielen
              </Button>
              <Button variant="secondary" size="md" icon="pencil" onClick={onRename}>
                Umbenennen
              </Button>
              <Button variant="danger" size="md" icon="trash" onClick={onDelete}>
                Löschen
              </Button>
            </div>
          </div>
        </div>
      </Glass>

      {/* Tracks list */}
      <Glass radius={20} padding={0}>
        {!data.tracks || data.tracks.length === 0 ? (
          <EmptyState
            bare padding="48px 24px" size="sm"
            icon="music" iconColor="var(--fg-4)"
            title="Noch keine Tracks in dieser Playlist"
            description={'Klick auf das „+ Playlist" Icon im Player oder unter einem Track-Eintrag.'}
          />
        ) : data.tracks.map((t, i) => (
          <TrackRow key={t.id} track={t}
            index={i + 1}
            border={i < data.tracks.length - 1}
            trailing={
              <>
                <ShareButton track={t}/>
                <button onClick={() => onRemoveTrack(t.id)}
                  title="Aus Playlist entfernen" aria-label="Aus Playlist entfernen"
                  style={{
                    background: 'transparent', border: 'none', cursor: 'pointer',
                    color: 'var(--fg-3)', padding: 6, display: 'flex',
                  }}>
                  <ApIcon name="x" size={14}/>
                </button>
              </>
            }/>
        ))}
      </Glass>
    </div>
  );
}

window.PlaylistsScreen = PlaylistsScreen;
