import type { WidgetRegistryMeta } from 'officerdev';
// The player is this plugin's own now, so these are siblings rather than host API. Parked: nothing
// registers this widget — plugins cannot contribute widgets, and that mechanism is not built.
import type { PlayerTrack } from '../web/useMusicPlayer';
import { useMusicPlayer } from '../web/useMusicPlayer';
import { useState, useEffect } from 'react';
import { Music, ChevronLeft, Play, Folder } from 'lucide-react';
import { useClient } from 'hooks/useClient';
import { Widget } from 'widgets/Widget';

// Music Player widget — a BROWSER over the library. Top-level dirs of ~/Music are "libraries" (tabs);
// within a library you drill through folders (Artist → Albums → …) until a folder has tracks (songs).
// Playback is owned by the app-wide player (useMusicPlayer): selecting a track hands it a queue.

const MUSIC_ROOT = 'Music';

type DirEntry = { name: string; type: 'directory' | 'file'; size: number; modifiedAt: number };
type LsResult = { path: string; rootDir?: string; entries: DirEntry[] };
type Track = { file: string; title?: string; artist?: string };
type AlbumMeta = { path: string; cover?: string; tracks: Track[] };

const AUDIO_EXT = new Set(['mp3', 'flac', 'm4a', 'aac', 'ogg', 'opus', 'wav', 'wma', 'mp4']);
const isAudio = (n: string) => {
  const d = n.lastIndexOf('.');
  return d >= 0 && AUDIO_EXT.has(n.slice(d + 1).toLowerCase());
};

export const MusicPlayer = () => {
  const { token, get } = useClient(); // base '/api'
  const player = useMusicPlayer();

  const [libraries, setLibraries] = useState<string[]>([]);
  const [library, setLibrary] = useState<string | null>(null);
  const [cwd, setCwd] = useState<string>(MUSIC_ROOT); // home-relative path
  const [dirs, setDirs] = useState<string[]>([]);
  const [songs, setSongs] = useState<Track[]>([]);
  const [loading, setLoading] = useState(false);

  // Top-level libraries (once).
  useEffect(() => {
    get<LsResult>(`/file-browser/ls?path=${encodeURIComponent(MUSIC_ROOT)}`)
      .then((r) =>
        setLibraries(
          r.entries
            .filter((e) => e.type === 'directory')
            .map((e) => e.name)
            .sort(),
        ),
      )
      .catch(() => setLibraries([]));
  }, []);

  // Current folder contents when cwd changes.
  useEffect(() => {
    if (!library) return;
    let cancelled = false;
    setLoading(true);
    setDirs([]);
    setSongs([]);
    get<LsResult>(`/file-browser/ls?path=${encodeURIComponent(cwd)}`)
      .then(async (r) => {
        if (cancelled) return;
        setDirs(
          r.entries
            .filter((e) => e.type === 'directory')
            .map((e) => e.name)
            .sort(),
        );
        const audio = r.entries.filter((e) => e.type === 'file' && isAudio(e.name)).map((e) => e.name);
        if (audio.length) {
          const rel = cwd.slice(MUSIC_ROOT.length + 1); // <library>/<…>
          try {
            const meta = await get<AlbumMeta>(`/music/meta?path=${encodeURIComponent(rel)}`);
            if (!cancelled) setSongs(meta.tracks);
          } catch {
            if (!cancelled) setSongs(audio.sort().map((f) => ({ file: f })));
          }
        }
      })
      .catch(() => {})
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [cwd, library]);

  const relToMusic = cwd.slice(MUSIC_ROOT.length + 1); // '' at root, else <library>/<…>
  const breadcrumb = relToMusic ? relToMusic.split('/') : [];
  const coverUrl = (rel: string) =>
    `/api/music/cover?path=${encodeURIComponent(rel)}${token ? `&token=${encodeURIComponent(token)}` : ''}`;

  const selectLibrary = (lib: string) => {
    setLibrary(lib);
    setCwd(`${MUSIC_ROOT}/${lib}`);
  };
  const enter = (name: string) => setCwd(`${cwd}/${name}`);
  const goUp = () => {
    const parts = cwd.split('/');
    if (parts.length <= 2) {
      setLibrary(null);
      setCwd(MUSIC_ROOT);
      return;
    }
    setCwd(parts.slice(0, -1).join('/'));
  };

  const play = (i: number) => {
    const queue: PlayerTrack[] = songs.map((t) => ({
      albumRel: relToMusic,
      file: t.file,
      title: t.title,
      artist: t.artist,
    }));
    player.playQueue(queue, i);
  };
  const isCurrent = (file: string) => player.current?.albumRel === relToMusic && player.current?.file === file;

  return (
    <Widget title="Music Player" className="w-72">
      {/* Library tabs */}
      <div className="flex gap-1 overflow-x-auto px-3 pb-2">
        {libraries.map((lib) => (
          <button
            key={lib}
            type="button"
            onClick={() => selectLibrary(lib)}
            className={`shrink-0 rounded-full px-2.5 py-1 text-xs ${
              library === lib
                ? 'bg-primary text-primary-foreground'
                : 'bg-muted text-muted-foreground hover:text-foreground'
            }`}
          >
            {lib}
          </button>
        ))}
        {!libraries.length && <span className="px-1 text-xs text-muted-foreground">No libraries</span>}
      </div>

      {!library ? (
        <div className="px-3 pb-4 text-center text-sm text-muted-foreground">Pick a library</div>
      ) : (
        <div className="flex flex-col gap-2 px-3 pb-3">
          {/* breadcrumb / back */}
          <button
            type="button"
            onClick={goUp}
            className="flex items-center gap-1 truncate text-xs text-muted-foreground hover:text-foreground"
          >
            <ChevronLeft size={14} className="shrink-0" />
            <span className="truncate">{breadcrumb.length ? breadcrumb.join(' / ') : library}</span>
          </button>

          {/* album header (cover + play-all) when the folder has songs */}
          {songs.length > 0 && (
            <div className="flex items-center gap-3">
              <div className="flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted">
                <img
                  src={coverUrl(relToMusic)}
                  alt=""
                  className="h-full w-full object-cover"
                  onError={(e) => {
                    (e.currentTarget as HTMLImageElement).style.visibility = 'hidden';
                  }}
                />
              </div>
              <div className="min-w-0 flex-1">
                <p className="truncate text-sm font-semibold text-foreground">
                  {breadcrumb[breadcrumb.length - 1] ?? library}
                </p>
                <p className="truncate text-xs text-muted-foreground">{breadcrumb[breadcrumb.length - 2] ?? ''}</p>
              </div>
              <button
                type="button"
                onClick={() => play(0)}
                title="Play all"
                className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground hover:opacity-90 active:scale-95"
              >
                <Play size={16} className="ml-0.5" />
              </button>
            </div>
          )}

          {/* folders + songs */}
          <div className="flex max-h-72 flex-col overflow-y-auto">
            {dirs.map((d) => (
              <button
                key={d}
                type="button"
                onClick={() => enter(d)}
                className="flex items-center gap-2 rounded px-2 py-1.5 text-left text-sm text-foreground hover:bg-muted"
              >
                <Folder size={14} className="shrink-0 text-muted-foreground" />
                <span className="truncate">{d}</span>
              </button>
            ))}
            {songs.map((t, i) => (
              <button
                key={t.file}
                type="button"
                onClick={() => play(i)}
                className={`flex items-center gap-2 rounded px-2 py-1 text-left text-xs hover:bg-muted ${
                  isCurrent(t.file) ? 'text-primary' : 'text-muted-foreground'
                }`}
              >
                <span className="w-4 shrink-0 text-right tabular-nums">{i + 1}</span>
                <span className="truncate">{t.title ?? t.file}</span>
              </button>
            ))}
            {loading && <span className="px-2 py-3 text-center text-sm text-muted-foreground">Loading…</span>}
            {!loading && !dirs.length && !songs.length && (
              <span className="px-2 py-3 text-center text-sm text-muted-foreground">Empty</span>
            )}
          </div>
        </div>
      )}
    </Widget>
  );
};

export const widgetRegistryMetas: WidgetRegistryMeta[] = [
  { key: 'music-player', name: 'Music Player', icon: Music, component: MusicPlayer },
];
