import { useState, useEffect, useRef, useMemo } from "react";
import { createPortal } from "react-dom";
import {
  Copy,
  Check,
  AlertTriangle,
  FileAudio,
  ShieldCheck,
  ShieldAlert,
  RefreshCw,
  Trash2,
  Download,
  Activity,
  FastForward,
  Disc,
  Upload,
  X,
  Waves,
  HardDrive,
  FileJson,
  Magnet,
  Play,
  Link,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Skeleton } from "@/components/ui/skeleton";
import { motion } from "motion/react";
import { RenameDialog } from "@/components/rename-dialog";
import {
  Album,
  AnalysisResponse,
  SpectrogramResponse,
  TorrentCreationResponse,
  CheckMQAResponse,
  CheckUpconvResponse,
  QbittorrentInjectResponse,
  QbittorrentResumeResponse,
  QbittorrentStatusResponse,
  AnalysisTrack,
} from "@/types";

interface AlbumViewProps {
  album: Album;
  addLog: (msg: string) => void;
  onReset: () => void;
  onAlbumUpdate: (newPath?: string) => void;
}

export function AlbumView({
  album,
  addLog,
  onReset,
  onAlbumUpdate,
}: AlbumViewProps) {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState<AnalysisResponse | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [copied, setCopied] = useState<string | null>(null);
  const [sanitizing, setSanitizing] = useState(false);
  const [sanitizeStatus, setSanitizeStatus] = useState<
    "idle" | "success" | "error"
  >("idle");

  const [torrenting, setTorrenting] = useState(false);
  const [torrentStatus, setTorrentStatus] = useState<
    "idle" | "success" | "error"
  >("idle");

  const [checkingMQA, setCheckingMQA] = useState(false);
  const [mqaStatus, setMqaStatus] = useState<
    "idle" | "success" | "error" | "warning"
  >("idle");

  const [checkingUpconv, setCheckingUpconv] = useState(false);
  const [upconvStatus, setUpconvStatus] = useState<
    "idle" | "success" | "error"
  >("idle");

  const [uploadingCover, setUploadingCover] = useState(false);
  const [coverUploadStatus, setCoverUploadStatus] = useState<
    "idle" | "success" | "error"
  >("idle");
  const [coverUrl, setCoverUrl] = useState<string | null>(null);

  const [spectrograms, setSpectrograms] = useState<
    Record<string, { exists: boolean; url?: string }>
  >({});
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
  const [showAllSpectrograms, setShowAllSpectrograms] = useState(false);
  const [spectrogramsViewed, setSpectrogramsViewed] = useState(false);

  const [copying, setCopying] = useState(false);
  const [copyStatus, setCopyStatus] = useState<"idle" | "success" | "error">(
    "idle",
  );
  const [deleting, setDeleting] = useState(false);
  const [generatingTemplate, setGeneratingTemplate] = useState(false);
  // Mock state for stepper visualization since we removed the real file generation
  const [generatedFiles, setGeneratedFiles] = useState<{
    json: { name: string; url: string } | null;
    torrent: { name: string; url: string } | null;
  }>({ json: null, torrent: null });
  const [skippedSteps, setSkippedSteps] = useState<Record<number, boolean>>({});

  const [injecting, setInjecting] = useState(false);
  const [injectionStatus, setInjectionStatus] = useState<
    "idle" | "injecting" | "checking" | "success" | "error" | "resumed"
  >("idle");
  const [injectionHash, setInjectionHash] = useState<string | null>(null);
  const [recheckProgress, setRecheckProgress] = useState(0);
  const [resuming, setResuming] = useState(false);
  const [showRenameDialog, setShowRenameDialog] = useState(false);

  const [releaseType, setReleaseType] = useState<number>(1);
  const [isGuessedType, setIsGuessedType] = useState(false);

  const [preflightSkipped, setPreflightSkipped] = useState(false);
  const [autoMode, setAutoMode] = useState(false);
  const [autoModeStarted, setAutoModeStarted] = useState(false);

  // Audio Preview State
  const [playingTrack, setPlayingTrack] = useState<string | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [progress, setProgress] = useState(0);
  const [isDragging, setIsDragging] = useState(false);
  const isDraggingRef = useRef(false);
  const lastSeekTimeRef = useRef(0);
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const dragStartedRef = useRef(false);
  const shouldSkipClickRef = useRef(false);

  useEffect(() => {
    audioRef.current = new Audio();
    audioRef.current.volume = 0.5;

    const handleEnded = () => {
      setIsPlaying(false);
      setProgress(0);
      setPlayingTrack(null);
    };

    const handleTimeUpdate = () => {
      if (audioRef.current && !isDraggingRef.current) {
        const duration = audioRef.current.duration;
        const currentTime = audioRef.current.currentTime;
        if (duration > 0) {
          setProgress((currentTime / duration) * 100);
        }
      }
    };

    audioRef.current.addEventListener("ended", handleEnded);
    audioRef.current.addEventListener("timeupdate", handleTimeUpdate);

    return () => {
      if (audioRef.current) {
        audioRef.current.pause();
        audioRef.current.removeEventListener("ended", handleEnded);
        audioRef.current.removeEventListener("timeupdate", handleTimeUpdate);
      }
    };
  }, []);

  const togglePlay = (filename: string) => {
    if (!audioRef.current) return;

    if (playingTrack === filename) {
      if (isPlaying) {
        audioRef.current.pause();
        setIsPlaying(false);
      } else {
        const playPromise = audioRef.current.play();
        if (playPromise !== undefined) {
          playPromise
            .then(() => setIsPlaying(true))
            .catch((e) => {
              if (e.name === "AbortError") return;
              console.error("Playback failed", e);
            });
        }
      }
    } else {
      // Stop previous if any
      audioRef.current.pause();

      // Play new
      audioRef.current.src = `/api/audio?path=${encodeURIComponent(`${album.path}/${filename}`)}`;
      const playPromise = audioRef.current.play();
      if (playPromise !== undefined) {
        playPromise
          .then(() => setIsPlaying(true))
          .catch((e) => {
            if (e.name === "AbortError") return;
            console.error("Playback failed", e);
            addLog(`Playback failed: ${e.message}`);
            setPlayingTrack(null);
            setIsPlaying(false);
          });
      }
      setPlayingTrack(filename);
      setProgress(0);
    }
  };

  const handleSeek = (e: React.MouseEvent, filename: string) => {
    if (playingTrack !== filename || !audioRef.current) return;

    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
    const x = e.clientX - rect.left;
    const width = rect.width;
    const percentage = Math.max(0, Math.min(1, x / width));

    // Update UI immediately
    setProgress(percentage * 100);

    // Throttle audio seek to every 50ms
    const now = Date.now();
    if (now - lastSeekTimeRef.current > 50) {
      if (audioRef.current.duration) {
        audioRef.current.currentTime = percentage * audioRef.current.duration;
      }
      lastSeekTimeRef.current = now;
    }
  };

  const handleTrackMouseDown = (e: React.MouseEvent, filename: string) => {
    if ((e.target as HTMLElement).closest("button")) return;
    e.preventDefault(); // Prevent text selection

    dragStartedRef.current = false;
    shouldSkipClickRef.current = false;

    if (playingTrack !== filename) {
      togglePlay(filename);
      shouldSkipClickRef.current = true; // We handled the action here, skip MouseUp toggle
    }
    setIsDragging(true);
    isDraggingRef.current = true;
  };

  const handleTrackMouseMove = (e: React.MouseEvent, filename: string) => {
    if (isDragging) {
      dragStartedRef.current = true;
      if (playingTrack === filename) {
        handleSeek(e, filename);
      }
    }
  };

  const handleTrackMouseUp = (e: React.MouseEvent, filename: string) => {
    if ((e.target as HTMLElement).closest("button")) return;

    setIsDragging(false);
    isDraggingRef.current = false;

    if (!dragStartedRef.current) {
      // It was a click
      if (playingTrack === filename && !shouldSkipClickRef.current) {
        togglePlay(filename);
      }
    } else {
      // It was a drag, ensure final position is set
      if (playingTrack === filename && audioRef.current) {
        const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
        const x = e.clientX - rect.left;
        const width = rect.width;
        const percentage = Math.max(0, Math.min(1, x / width));
        if (audioRef.current.duration) {
          audioRef.current.currentTime = percentage * audioRef.current.duration;
        }
      }
    }
  };

  const handleTrackMouseLeave = () => {
    setIsDragging(false);
    isDraggingRef.current = false;
  };

  const handleUploadCover = async (
    isAutoMode: boolean | React.MouseEvent = false,
  ) => {
    const auto = isAutoMode === true;
    if (!album.coverPath) return;

    if (coverUrl) {
      if (!auto) copyToClipboard(coverUrl, "Cover URL");
      return;
    }

    setUploadingCover(true);
    addLog("Uploading cover art...");
    try {
      // 1. Fetch the image blob from our local API
      const coverRes = await fetch(
        `/api/cover?path=${encodeURIComponent(album.coverPath)}`,
      );
      const blob = await coverRes.blob();

      // 2. Prepare form data
      const formData = new FormData();
      formData.append("file", blob, "cover.jpg");

      // 3. Upload to our proxy API
      const res = await fetch("/api/upload/image", {
        method: "POST",
        body: formData,
      });
      const result = (await res.json()) as {
        error?: string;
        url?: string;
      };

      if (result.url) {
        setCoverUrl(result.url);
        setCoverUploadStatus("success");
        if (!auto) copyToClipboard(result.url, "Cover URL");
        addLog(`Cover uploaded: ${result.url}`);
      } else {
        setCoverUploadStatus("error");
        addLog(`Upload failed: ${result.error}`);
      }
    } catch (e) {
      setCoverUploadStatus("error");
      addLog("Upload request failed.");
    } finally {
      setUploadingCover(false);
    }
  };

  // Track previous album path to handle resets correctly
  const prevAlbumPathRef = useRef<string | null>(null);
  const preservedReleaseType = useRef<number | null>(null);
  const hasInitializedReleaseType = useRef(false);
  const isSanitizingTransition = useRef(false);

  useEffect(() => {
    if (album) {
      analyzeAlbum();

      // Only reset checks if we switched to a different album
      if (prevAlbumPathRef.current !== album.path) {
        // If this is a sanitization transition, we want to keep the release type and checks
        if (isSanitizingTransition.current) {
          isSanitizingTransition.current = false;
          // We preserve preflight checks and release type
        } else {
          preservedReleaseType.current = null;
          hasInitializedReleaseType.current = false;

          // Reset checks and state for a completely new album detection
          setSpectrograms({});
          setMqaStatus("idle");
          setUpconvStatus("idle");
          setSpectrogramsViewed(false);
          setPreflightSkipped(false);
          setAutoModeStarted(false);
          setAutoMode(false);
          // Reset workflow steps
          setSkippedSteps({});
          setSanitizeStatus("idle");
          setTorrentStatus("idle");
          setCopyStatus("idle");
          setCoverUploadStatus("idle");
          setGeneratedFiles({ json: null, torrent: null });
          setInjectionStatus("idle");
          setInjectionHash(null);
          setCoverUrl(null);
        }
      }
      prevAlbumPathRef.current = album.path;
    }
  }, [album]);

  useEffect(() => {
    if (data && data.tracks) {
      fetchSpectrograms();
    }
  }, [data]);

  useEffect(() => {
    if (data && data.metadata) {
      if (data.metadata.releaseType) {
        if (preservedReleaseType.current !== null) {
          setReleaseType(preservedReleaseType.current);
          hasInitializedReleaseType.current = true;
          preservedReleaseType.current = null;
        } else if (!hasInitializedReleaseType.current) {
          setReleaseType(data.metadata.releaseType);
          hasInitializedReleaseType.current = true;
          if (data.metadata.releaseType !== 1) {
            setIsGuessedType(true);
          }
        }
      }
    }
  }, [data]);

  const fetchSpectrograms = async () => {
    if (!data || !album) return;
    try {
      const res = await fetch("/api/spectrogram", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          albumPath: album.path,
          tracks: data.tracks,
          upc: data.metadata.upc,
        }),
      });
      const result = (await res.json()) as SpectrogramResponse;
      if (result.results) {
        console.log("Spectrograms loaded:", result.results);
        setSpectrograms(result.results);
      }
    } catch (e) {
      console.error("Failed to fetch spectrograms", e);
    }
  };

  // Auto-refresh album details every 5 seconds to catch new files
  useEffect(() => {
    if (!album) return;
    const interval = setInterval(() => {
      // Silent update
      fetch("/api/analyze", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      })
        .then((res) => res.json())
        .then((result: AnalysisResponse & { error?: string }) => {
          if (!result.error) {
            // Only update if track count changed or filenames changed
            setData((prev) => {
              if (!prev) return result;
              if (prev.tracks.length !== result.tracks.length) return result;

              const prevNames = prev.tracks
                .map((t) => t.filename)
                .sort()
                .join("|");
              const newNames = result.tracks
                .map((t) => t.filename)
                .sort()
                .join("|");
              if (prevNames !== newNames) return result;

              return prev;
            });
          }
        })
        .catch(() => {});
    }, 5000);
    return () => clearInterval(interval);
  }, [album]);

  // Polling for qBittorrent status
  useEffect(() => {
    if (injectionStatus !== "checking" || !injectionHash) return;

    const interval = setInterval(async () => {
      try {
        const res = await fetch(
          `/api/qbittorrent/status?hash=${injectionHash}`,
        );
        const result = (await res.json()) as QbittorrentStatusResponse & {
          error?: string;
        };

        if (result.success && result.info) {
          const { state, progress } = result.info;

          if (progress === 1) {
            setInjectionStatus("success");
            setRecheckProgress(100);
            addLog("Torrent recheck complete: 100%");
          } else if (
            state === "checkingUP" ||
            state === "checkingDL" ||
            state === "metaDL" ||
            state === "allocating" ||
            state === "queuedUP" ||
            state === "queuedDL"
          ) {
            setRecheckProgress(Math.round(progress * 100));
          } else if (
            state === "stoppedDL" ||
            state === "pausedDL" ||
            state === "stoppedUP" ||
            state === "pausedUP"
          ) {
            // If stopped and not 100%, it means recheck finished (or didn't find anything)
            setInjectionStatus("error");
            addLog(
              `Recheck finished with incomplete data (${Math.round(progress * 100)}%). Check path mapping.`,
            );
          } else {
            // Unknown state or other error
            setInjectionStatus("error");
            addLog(`Injection failed. State: ${state}`);
          }
        }
      } catch (e) {
        console.error("Polling failed", e);
      }
    }, 1000);

    return () => clearInterval(interval);
  }, [injectionStatus, injectionHash]);

  const analyzeAlbum = async () => {
    if (!data) setLoading(true);
    setError(null);
    // setData(null); // Keep existing data to prevent flicker
    addLog(`Analyzing album: ${album.name}...`);
    try {
      const res = await fetch("/api/analyze", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      });
      const result = (await res.json()) as AnalysisResponse & {
        error?: string;
      };
      if (result.error) {
        setError(result.error);
        addLog(`Error: ${result.error}`);
      } else {
        setData(result);
        addLog(`Analysis complete. Status: ${result.quality.status}`);

        // Check for long filenames (Folder + / + File)
        // We need to type guard tracks to ensure they are not error tracks for filename access
        const hasLong = result.tracks.some((t) => {
          if ("error" in t) return false;
          return album.name.length + 1 + t.filename.length > 179;
        });
        if (hasLong) {
          setShowRenameDialog(true);
        }
      }
    } catch (e) {
      setError("Failed to connect to server");
      addLog("Failed to connect to server");
    } finally {
      setLoading(false);
    }
  };

  const copyToClipboard = (text: string, label: string) => {
    navigator.clipboard.writeText(text);
    setCopied(label);
    setTimeout(() => setCopied(null), 2000);
    addLog(`Copied ${label} to clipboard.`);
  };

  const handleSanitize = async () => {
    setSanitizing(true);
    setSanitizeStatus("idle");
    addLog("Sanitizing album...");
    try {
      const res = await fetch("/api/sanitize", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      });
      const result = await res.json();
      if (result.success) {
        setSanitizeStatus("success");
        addLog("Album sanitized successfully.");

        // Preserve release type across the reload
        preservedReleaseType.current = releaseType;

        if (result.newAlbumPath && result.newAlbumPath !== album.path) {
          isSanitizingTransition.current = true;
          onAlbumUpdate(result.newAlbumPath); // Update parent with new path
        } else {
          onAlbumUpdate(); // Refresh album data
        }
      } else {
        setSanitizeStatus("error");
        addLog(`Sanitize failed: ${result.error}`);
      }
    } catch (e) {
      setSanitizeStatus("error");
      addLog("Sanitize request failed.");
    } finally {
      setSanitizing(false);
    }
  };

  const handleTorrent = async () => {
    setTorrenting(true);
    setTorrentStatus("idle");
    addLog("Creating torrent...");
    try {
      const res = await fetch("/api/torrent", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      });
      const result = (await res.json()) as TorrentCreationResponse;
      if (result.success) {
        setTorrentStatus("success");
        addLog("Torrent created successfully.");
        if (result.output) addLog(result.output);
      } else {
        setTorrentStatus("error");
        addLog(`Torrent creation failed: ${result.error}`);
        if (result.errorOutput) addLog(result.errorOutput);
      }
    } catch (e) {
      setTorrentStatus("error");
      addLog("Torrent request failed.");
    } finally {
      setTorrenting(false);
    }
  };

  const handleCheckMQA = async () => {
    if (!data?.tracks?.length) return;
    setCheckingMQA(true);
    setMqaStatus("idle");
    addLog("Checking for MQA...");

    try {
      const res = await fetch("/api/check/mqa", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      });
      const result = (await res.json()) as CheckMQAResponse & {
        error?: string;
      };
      if (result.success) {
        if (result.isMQA) {
          setMqaStatus("warning");
          addLog("WARNING: MQA DETECTED!");
          if (
            confirm("MQA Detected! Do you want to delete this album and reset?")
          ) {
            addLog(
              "User requested delete (Not implemented in MVP, please delete manually).",
            );
          }
        } else {
          setMqaStatus("success");
          addLog("MQA Check Passed: No MQA detected.");
        }
      } else {
        setMqaStatus("error");
        addLog(`MQA Check failed: ${result.error}`);
      }
    } catch (e) {
      setMqaStatus("error");
      addLog("MQA Check request failed.");
    } finally {
      setCheckingMQA(false);
      // setTimeout(() => setMqaStatus("idle"), 5000); // Removed auto-reset
    }
  };

  const handleCheckUpconv = async () => {
    if (!data?.tracks?.length) return;
    setCheckingUpconv(true);
    setUpconvStatus("idle");
    addLog("Checking for Upconversion...");
    const has24Bit = data.tracks.some((t) => {
      if ("error" in t) return false;
      return (t.format?.bitsPerSample || 0) >= 24;
    });
    if (!has24Bit) {
      addLog("No 24-bit files to check.");
      setCheckingUpconv(false);
      return;
    }

    try {
      const res = await fetch("/api/check/upconv", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      });
      const result = (await res.json()) as CheckUpconvResponse & {
        error?: string;
      };
      if (result.success) {
        setUpconvStatus("success");
        addLog(`Upconversion Check: ${result.wastedBits}`);
        addLog(result.output);
      } else {
        setUpconvStatus("error");
        addLog(`Upconversion Check failed: ${result.error}`);
      }
    } catch (e) {
      setUpconvStatus("error");
      addLog("Upconversion Check request failed.");
    } finally {
      setCheckingUpconv(false);
      // setTimeout(() => setUpconvStatus("idle"), 5000); // Removed auto-reset
    }
  };

  const handleInject = async (eOrRetryCount?: React.MouseEvent | number) => {
    const retryCount = typeof eOrRetryCount === "number" ? eOrRetryCount : 0;

    if (retryCount === 0) {
      setInjecting(true);
      setInjectionStatus("injecting");
      addLog("Injecting torrent to qBittorrent...");
    }

    try {
      const res = await fetch("/api/qbittorrent/inject", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      });
      const result = (await res.json()) as QbittorrentInjectResponse & {
        error?: string;
      };

      if (result.success) {
        setInjectionHash(result.hash);
        addLog(
          `Torrent injected${retryCount > 0 ? ` (after ${retryCount} retries)` : ""}. Waiting for client to register...`,
        );
        // Wait 2 seconds before starting recheck loop to allow qBit to register the torrent
        setTimeout(() => {
          setInjectionStatus("checking");
          addLog("Starting recheck...");
          setInjecting(false);
        }, 4000);
      } else {
        if (retryCount < 3) {
          addLog(`Injection failed. Retrying... (${retryCount + 1}/3)`);
          setTimeout(() => handleInject(retryCount + 1), 2000);
        } else {
          setInjectionStatus("error");
          addLog(`Injection failed after 3 retries: ${result.error}`);
          setInjecting(false);
        }
      }
    } catch (e) {
      if (retryCount < 3) {
        addLog(`Injection request failed. Retrying... (${retryCount + 1}/3)`);
        setTimeout(() => handleInject(retryCount + 1), 2000);
      } else {
        setInjectionStatus("error");
        addLog("Injection request failed after 3 retries.");
        setInjecting(false);
      }
    }
  };

  const handleCopy = async () => {
    setCopying(true);
    addLog("Copying album to output directory...");
    try {
      const res = await fetch("/api/copy", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumPath: album.path }),
      });
      const result = await res.json();
      if (result.success) {
        addLog(`Album copied to: ${result.destPath}`);
        setCopyStatus("success");
      } else {
        addLog(`Copy failed: ${result.error}`);
        setCopyStatus("error");
      }
    } catch (e) {
      addLog("Copy request failed.");
      setCopyStatus("error");
    } finally {
      setCopying(false);
    }
  };

  // Auto Workflow effect
  useEffect(() => {
    if (!autoMode) return;
    if (
      loading ||
      sanitizing ||
      torrenting ||
      copying ||
      uploadingCover ||
      injecting ||
      injectionStatus === "checking" ||
      injectionStatus === "injecting"
    )
      return;
    if (isSanitizingTransition.current) return;

    const timer = setTimeout(() => {
      if (sanitizeStatus !== "success" && !skippedSteps[1]) {
        handleSanitize();
      } else if (torrentStatus !== "success" && !skippedSteps[2]) {
        handleTorrent();
      } else if (copyStatus !== "success" && !skippedSteps[3]) {
        handleCopy();
      } else if (!coverUrl && !skippedSteps[4] && album.coverPath) {
        handleUploadCover(true);
      } else if (
        injectionStatus !== "success" &&
        injectionStatus !== "resumed" &&
        !skippedSteps[5]
      ) {
        handleInject(0);
      } else {
        setAutoMode(false);
        addLog("Auto workflow completed.");
      }
    }, 500);

    return () => clearTimeout(timer);
  }, [
    autoMode,
    sanitizeStatus,
    torrentStatus,
    copyStatus,
    coverUrl,
    injectionStatus,
    skippedSteps,
    sanitizing,
    torrenting,
    copying,
    uploadingCover,
    injecting,
    loading,
    album.path,
  ]);

  const handleResume = async () => {
    if (!injectionHash) return;
    setResuming(true);
    addLog("Resuming torrent...");

    try {
      const res = await fetch("/api/qbittorrent/resume", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ hash: injectionHash }),
      });
      const result = (await res.json()) as QbittorrentResumeResponse & {
        error?: string;
      };

      if (result.success) {
        setInjectionStatus("resumed");
        addLog("Torrent resumed successfully.");
      } else {
        addLog(`Resume failed: ${result.error}`);
      }
    } catch (e) {
      addLog("Resume request failed.");
    } finally {
      setResuming(false);
    }
  };

  const handleSkipPreflight = () => {
    if (
      confirm(
        "WARNING: Skipping these checks is UNSAFE. You might upload bad files or break the workflow. Are you sure you want to skip?",
      )
    ) {
      setPreflightSkipped(true);
      addLog("WARNING: Pre-flight checks skipped by user.");
    }
  };

  const audioTriggers = useMemo(
    () => [
      {
        sound: "/sfx/error.mp3",
        conditions: [
          !!error,
          data?.quality?.status === "CORRUPT",
          showRenameDialog,
          sanitizeStatus === "error",
          torrentStatus === "error",
          copyStatus === "error",
          coverUploadStatus === "error",
          injectionStatus === "error",
          mqaStatus === "error",
          mqaStatus === "warning",
          upconvStatus === "error",
        ],
      },
      {
        sound: "/sfx/stage-complete.mp3",
        conditions: [
          sanitizeStatus === "success",
          torrentStatus === "success",
          copyStatus === "success",
          coverUploadStatus === "success",
          injectionStatus === "checking",
          mqaStatus === "success",
          upconvStatus === "success",
        ],
      },
      {
        sound: "/sfx/success.mp3",
        conditions: [injectionStatus === "success"],
      },
    ],
    [
      error,
      data?.quality?.status,
      showRenameDialog,
      sanitizeStatus,
      torrentStatus,
      copyStatus,
      coverUploadStatus,
      injectionStatus,
      mqaStatus,
      upconvStatus,
    ],
  );

  const prevTriggersRef = useRef<boolean[][]>([]);

  useEffect(() => {
    if (prevTriggersRef.current.length === 0) {
      prevTriggersRef.current = audioTriggers.map((t) =>
        t.conditions.map(() => false),
      );
    }

    audioTriggers.forEach((trigger, i) => {
      const prevConditions = prevTriggersRef.current[i] || [];

      // Trigger if condition goes explicitly from falsy to truthy
      const justFired = trigger.conditions.some(
        (cond, j) => cond && !prevConditions[j],
      );

      if (justFired) {
        new Audio(trigger.sound).play().catch(console.error);
      }

      prevTriggersRef.current[i] = [...trigger.conditions];
    });
  }, [audioTriggers]);

  const backgroundCoverMemo = useMemo(() => {
    return album.coverPath ? (
      <>
        <div className="absolute w-full h-full top-0 left-0 backdrop-blur-xs z-10 bg-background/70" />
        <div className="absolute w-full h-full top-0 left-0 z-0">
          <img
            src={`/api/cover?path=${encodeURIComponent(album.coverPath)}`}
            alt={album.name}
            className="w-full h-full object-cover scale-110"
          />
        </div>
      </>
    ) : null;
  }, [album.coverPath, album.name]);

  const discGroups = useMemo(() => {
    if (!data?.tracks) return [];
    const map = new Map<number, { track: AnalysisTrack; originalIndex: number }[]>();

    data.tracks.forEach((track: AnalysisTrack, i: number) => {
      let discNo = 1;
      if (!("error" in track)) {
        if (track.common?.disk?.no) {
          discNo = track.common.disk.no;
        } else {
          const match = track.filename.match(/^(\d+)-(\d+)\b/);
          if (match) discNo = parseInt(match[1], 10);
        }
      }
      if (!map.has(discNo)) {
        map.set(discNo, []);
      }
      map.get(discNo)!.push({ track, originalIndex: i });
    });

    const sortedDiscs = Array.from(map.keys()).sort((a, b) => a - b);
    return sortedDiscs.map((discNo) => ({
      discNo,
      items: map.get(discNo)!,
    }));
  }, [data?.tracks]);

  const isMultiDisc = useMemo(() => {
    return (
      discGroups.length > 1 ||
      (discGroups.length === 1 && discGroups[0].discNo > 1)
    );
  }, [discGroups]);

  const spectrogramsMemo = useMemo(() => {
    if (!data?.tracks) return null;
    return data.tracks.map((track: AnalysisTrack) => {
      const spec = spectrograms[track.filename];
      if (!spec?.exists || !spec.url) return null;

      let discNo = 1;
      let trackNo = 0;
      if (!("error" in track)) {
        discNo = track.common?.disk?.no || 1;
        trackNo = track.common?.track?.no || 0;
        if (!track.common?.disk?.no) {
          const match = track.filename.match(/^(\d+)-(\d+)\b/);
          if (match) {
            discNo = parseInt(match[1], 10);
            if (!track.common?.track?.no) trackNo = parseInt(match[2], 10);
          }
        }
      }

      const trackNumStr = isMultiDisc
        ? `${discNo}-${trackNo.toString().padStart(2, "0")}`
        : (trackNo || "").toString().padStart(2, "0");

      return (
        <div
          key={track.filename}
          className="space-y-3 p-4 rounded-xl bg-black/20 border border-white/5"
        >
          <div className="flex items-center justify-between">
            <div className="font-medium text-white/90 flex items-center gap-3">
              <span className="h-6 rounded bg-white/10 text-xs flex items-center justify-center font-mono text-white/50 px-2">
                {trackNumStr}
              </span>
              <span>
                {(!("error" in track) && track.common?.title) || track.filename}
              </span>
            </div>
            {!("error" in track) && (
              <div className="text-xs font-mono text-white/30">
                {track.format?.bitsPerSample}bit /{" "}
                {track.format?.sampleRate
                  ? track.format.sampleRate / 1000
                  : "?"}
                kHz
              </div>
            )}
          </div>
          <div className="bg-black/50 rounded-lg overflow-hidden border border-white/10 relative group">
            <div className="absolute inset-0 bg-white/0 group-hover:bg-white/5 transition-colors pointer-events-none" />
            <img
              key={spec.url}
              src={spec.url}
              alt={`Spectrogram for ${track.filename}`}
              className="w-full h-auto object-contain max-h-[500px]"
            />
          </div>
        </div>
      );
    });
  }, [data?.tracks, spectrograms, isMultiDisc]);

  if (loading) {
    return (
      <div className="flex flex-col gap-4 p-6 h-full justify-center">
        <div className="space-y-4 w-full max-w-2xl mx-auto">
          <Skeleton className="h-12 w-3/4" />
          <Skeleton className="h-4 w-1/2" />
          <div className="space-y-2 mt-8">
            <Skeleton className="h-4 w-full" />
            <Skeleton className="h-4 w-full" />
            <Skeleton className="h-4 w-full" />
          </div>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex flex-col items-center justify-center h-full text-destructive p-6">
        <AlertTriangle className="w-12 h-12 mb-4" />
        <p className="text-lg font-medium">{error}</p>
        <Button onClick={analyzeAlbum} variant="outline" className="mt-4">
          Try Again
        </Button>
      </div>
    );
  }

  if (!data) return null;

  const { metadata, tracks, quality } = data;
  let currentDiscText: number | null = null;
  const tracklistTextLines: string[] = [];

  tracks.forEach((t) => {
    if ("error" in t) {
      tracklistTextLines.push(`${t.filename} (Error)`);
      return;
    }
    let discNo = t.common?.disk?.no || 1;
    let trackNo = (t.common?.track?.no || 0).toString().padStart(2, "0");
    if (!t.common?.disk?.no) {
      const match = t.filename.match(/^(\d+)-(\d+)\b/);
      if (match) {
        discNo = parseInt(match[1], 10);
        if (!t.common?.track?.no) trackNo = match[2].padStart(2, "0");
      }
    }

    if (isMultiDisc && discNo !== currentDiscText) {
      if (currentDiscText !== null) tracklistTextLines.push("");
      tracklistTextLines.push(`Disc ${discNo}`);
      currentDiscText = discNo;
    }

    const trackNumStr = isMultiDisc ? `${discNo}-${trackNo}` : trackNo;
    tracklistTextLines.push(`${trackNumStr} - ${t.common?.title || t.filename}`);
  });

  const tracklistText = tracklistTextLines.join("\n");

  // Dynamic offset deduction for Tracklist Max Height
  const isLogEnabled = process.env.NEXT_PUBLIC_SHOW_SYSTEM_LOG === "true";
  const tracklistOffsetRem = isLogEnabled ? 42 : 28;

  // Check relative length: Folder Name + / + File Name
  const hasLongFilenames = tracks.some((t) => {
    if ("error" in t) return false;
    return album.name.length + 1 + t.filename.length > 179;
  });
  const has24Bit = tracks.some((t) => {
    if ("error" in t) return false;
    return (t.format?.bitsPerSample || 0) >= 24;
  });

  // Pre-flight checks validation
  const mqaPassed = mqaStatus === "success";
  const upconvPassed = !has24Bit || upconvStatus === "success";
  const specsExist = Object.keys(spectrograms).length > 0;
  const specsPassed = !specsExist || spectrogramsViewed;
  const allChecksPassed =
    preflightSkipped || (mqaPassed && upconvPassed && specsPassed);

  const releaseTypes = [
    { id: 1, name: "Album" },
    { id: 3, name: "Soundtrack" },
    { id: 5, name: "EP" },
    { id: 6, name: "Anthology" },
    { id: 7, name: "Compilation" },
    { id: 9, name: "Single" },
    { id: 11, name: "Live album" },
    { id: 13, name: "Remix" },
    { id: 14, name: "Bootleg" },
    { id: 15, name: "Interview" },
    { id: 16, name: "Mixtape" },
    { id: 17, name: "DJ Mix" },
    { id: 18, name: "Concert recording" },
    { id: 21, name: "Unknown" },
  ];

  return (
    <div className="flex flex-col gap-4">
      {/* Header Section */}
      <div className="relative overflow-hidden rounded-xl bg-linear-to-b from-white/5 to-transparent border border-white/10 p-3 shadow-2xl">
        {backgroundCoverMemo}
        <div className="flex flex-col md:flex-row gap-8 items-start relative z-10">
          {/* Cover Art */}
          <div className="shrink-0 group relative">
            <div className="w-40 h-40 md:w-50 md:h-50 rounded-lg bg-black/50 shadow-2xl overflow-hidden border border-white/10 relative z-10 transition-transform duration-500 group-hover:scale-[1.02]">
              {album.coverPath ? (
                <img
                  src={`/api/cover?path=${encodeURIComponent(album.coverPath)}`}
                  alt={album.name}
                  className="w-full h-full object-cover"
                />
              ) : (
                <div className="w-full h-full flex items-center justify-center bg-muted">
                  <Disc className="w-20 h-20 text-muted-foreground/50" />
                </div>
              )}
            </div>
            {/* Glow effect behind cover */}
            <div className="absolute inset-0 bg-primary/20 blur-3xl -z-10 rounded-full opacity-0 group-hover:opacity-50 transition-opacity duration-700" />
          </div>

          {/* Info */}
          <div className="flex-1 min-w-0 flex flex-col gap-4 pt-2">
            <div>
              <motion.h2
                initial={{ opacity: 0, y: 10 }}
                animate={{ opacity: 1, y: 0 }}
                className="text-3xl md:text-4xl font-bold tracking-tight text-white leading-tight flex items-center gap-3"
              >
                <span className="truncate">{metadata.album}</span>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-6 w-6 opacity-0 group-hover:opacity-50 hover:!opacity-100 transition-opacity"
                  onClick={() => copyToClipboard(metadata.album, "Album Title")}
                >
                  {copied === "Album Title" ? (
                    <Check className="w-4 h-4 text-green-500" />
                  ) : (
                    <Copy className="w-4 h-4" />
                  )}
                </Button>
              </motion.h2>
              <motion.div
                initial={{ opacity: 0, y: 10 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ delay: 0.1 }}
                className="text-xl md:text-2xl text-white/70 font-medium flex items-center gap-2 mt-1"
              >
                <span>{metadata.artist}</span>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-5 w-5 opacity-0 group-hover:opacity-50 hover:!opacity-100 transition-opacity"
                  onClick={() =>
                    copyToClipboard(metadata.artist, "Artist Name")
                  }
                >
                  {copied === "Artist Name" ? (
                    <Check className="w-3 h-3 text-green-500" />
                  ) : (
                    <Copy className="w-3 h-3" />
                  )}
                </Button>
              </motion.div>
            </div>

            {/* Metadata Grid */}
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              transition={{ delay: 0.2 }}
              className="flex flex-wrap gap-2 items-center mt-auto"
            >
              <Badge
                variant="outline"
                className={`text-xs px-2.5 py-1 border ${
                  quality.status === "LOSSLESS" || quality.status === "HI-RES"
                    ? "bg-green-500/10 text-green-400 border-green-500/30"
                    : "bg-red-500/10 text-red-400 border-red-500/30"
                }`}
              >
                {quality.status}
              </Badge>

              {quality.mixed && (
                <Badge
                  variant="outline"
                  className="bg-yellow-500/10 text-yellow-400 border-yellow-500/30 text-xs px-2.5 py-1"
                >
                  MIXED FORMATS
                </Badge>
              )}

              {metadata.year && <div className="h-6 w-px bg-white/10 mx-1" />}

              {metadata.year && (
                <span
                  className="text-sm text-white/60 hover:text-white cursor-pointer transition-colors font-mono"
                  onClick={() => copyToClipboard(String(metadata.year), "Year")}
                  title="Copy Year"
                >
                  {metadata.year}
                </span>
              )}

              {metadata.totalSize && (
                <>
                  <div className="h-6 w-px bg-white/10 mx-1" />
                  <span
                    className="text-sm text-white/60 hover:text-white cursor-pointer transition-colors font-mono"
                    onClick={() =>
                      copyToClipboard(
                        formatBytes(metadata.totalSize),
                        "Total Size",
                      )
                    }
                    title="Copy Total Size"
                  >
                    {formatBytes(metadata.totalSize)}
                  </span>
                </>
              )}

              {metadata.label && (
                <>
                  <div className="h-6 w-px bg-white/10 mx-1" />
                  <span
                    className="text-sm text-white/60 hover:text-white cursor-pointer transition-colors max-w-[200px] truncate"
                    onClick={() => copyToClipboard(metadata.label, "Label")}
                    title="Copy Label"
                  >
                    {metadata.label}
                  </span>
                </>
              )}

              {metadata.upc && (
                <>
                  <div className="h-6 w-px bg-white/10 mx-1" />
                  <span
                    className="text-sm text-white/60 hover:text-white cursor-pointer transition-colors font-mono"
                    onClick={() => copyToClipboard(metadata.upc || "", "UPC")}
                    title="Copy UPC"
                  >
                    UPC: {metadata.upc}
                  </span>
                </>
              )}
            </motion.div>

            {/* Additional Artists */}
            {metadata.additionalArtists && (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ delay: 0.3 }}
                className="flex flex-wrap gap-1.5 items-center"
              >
                <span className="text-xs text-white/40 uppercase tracking-wider font-semibold mr-1">
                  Feat
                </span>
                {metadata.additionalArtists.map((artist: string, i: number) => (
                  <Badge
                    key={i}
                    variant="secondary"
                    className="text-[10px] px-2 py-0.5 bg-white/5 hover:bg-white/10 text-white/80 cursor-pointer border-transparent"
                    onClick={() => copyToClipboard(artist, "Artist Name")}
                  >
                    {artist}
                  </Badge>
                ))}
              </motion.div>
            )}

            {/* Release Type & Links */}
            <div className="flex items-center gap-3 mt-2">
              <div className="relative">
                <select
                  className="h-8 w-[160px] rounded-md border border-white/10 bg-black/20 px-3 py-1 text-sm text-white/80 shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary hover:bg-white/5 appearance-none cursor-pointer"
                  value={releaseType}
                  onChange={(e) => {
                    setReleaseType(parseInt(e.target.value));
                    setIsGuessedType(false);
                  }}
                >
                  {releaseTypes.map((type) => (
                    <option
                      key={type.id}
                      value={type.id}
                      className="bg-zinc-900 text-white"
                    >
                      {type.name}
                    </option>
                  ))}
                </select>
                <div className="absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none text-white/40">
                  <svg
                    width="10"
                    height="6"
                    viewBox="0 0 10 6"
                    fill="none"
                    xmlns="http://www.w3.org/2000/svg"
                  >
                    <path
                      d="M1 1L5 5L9 1"
                      stroke="currentColor"
                      strokeWidth="1.5"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                    />
                  </svg>
                </div>
              </div>

              {isGuessedType && (
                <Badge
                  variant="secondary"
                  className="text-[10px] bg-blue-500/40 text-blue-400 border border-blue-500/20"
                >
                  Auto-detected
                </Badge>
              )}

              {metadata.tidalUrl && (
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-8 text-xs text-cyan-400 hover:text-cyan-300 font-semibold cursor-pointer"
                  onClick={() => window.open(metadata.tidalUrl, "_blank")}
                >
                  <Link />
                  TIDAL
                </Button>
              )}
            </div>
          </div>
        </div>
      </div>

      <Separator />

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
        {/* Tracklist Column */}
        <div className="lg:col-span-2 flex flex-col min-h-0 gap-4">
          {quality.mixed && (
            <Alert
              variant="destructive"
              className="py-2 bg-red-500/10 border-red-500/20 text-red-200"
            >
              <AlertTriangle className="h-4 w-4" />
              <AlertTitle className="text-sm font-semibold">
                Quality Mismatch
              </AlertTitle>
              <AlertDescription className="text-xs flex items-center gap-2 mt-1">
                <span>Different bit depths/sample rates detected.</span>
                <Button
                  variant="outline"
                  size="sm"
                  className="h-6 text-xs bg-red-500/10 border-red-500/30 hover:bg-red-500/20 text-red-200"
                  onClick={() =>
                    copyToClipboard(quality.details, "Quality Report")
                  }
                >
                  Copy Report
                </Button>
              </AlertDescription>
            </Alert>
          )}

          {hasLongFilenames && (
            <Alert
              variant="destructive"
              className="py-2 bg-red-500/10 border-red-500/20 text-red-200"
            >
              <ShieldAlert className="h-4 w-4" />
              <AlertTitle className="text-sm font-semibold">
                Filename Too Long
              </AlertTitle>
              <AlertDescription className="text-xs mt-1">
                Some filenames exceed 179 characters. Torrent creation is
                disabled.
              </AlertDescription>
            </Alert>
          )}

          <div className="flex flex-col rounded-xl bg-black/20 border border-white/10 overflow-hidden shadow-inner">
            <div className="py-3 px-4 border-b border-white/5 flex flex-row items-center justify-between shrink-0 bg-white/5">
              <h3 className="text-sm font-medium flex items-center gap-2 text-white/80">
                <FileAudio className="w-4 h-4 text-primary" /> Tracklist
              </h3>
              <div className="flex items-center gap-2">
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-6 text-xs text-white/50 hover:text-white hover:bg-white/10"
                  onClick={() => setShowRenameDialog(true)}
                >
                  Rename Files
                </Button>
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-6 text-xs text-white/50 hover:text-white hover:bg-white/10"
                  onClick={() => copyToClipboard(tracklistText, "Tracklist")}
                >
                  {copied === "Tracklist" ? (
                    <Check className="w-3 h-3 mr-1 text-green-500" />
                  ) : (
                    <Copy className="w-3 h-3 mr-1" />
                  )}
                  Copy All
                </Button>
              </div>
            </div>
            <div
              className="relative overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-white/10 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-white/20"
              style={{ maxHeight: `calc(100vh - ${tracklistOffsetRem}rem)` }}
            >
              <div className="h-full">
                <div className="p-2 space-y-3">
                  {discGroups.map((group) => (
                    <div key={group.discNo} className="space-y-0.5">
                      {isMultiDisc && (
                        <div className="flex items-center gap-2 pt-2 pb-1.5 px-2 text-xs font-semibold uppercase tracking-wider text-primary/80 border-b border-white/5 mb-1 select-none">
                          <Disc className="w-3.5 h-3.5 shrink-0 text-primary" />
                          <span>Disc {group.discNo}</span>
                          <span className="text-[10px] font-normal text-white/40 lowercase">
                            ({group.items.length} {group.items.length === 1 ? "track" : "tracks"})
                          </span>
                        </div>
                      )}
                      {group.items.map(({ track, originalIndex: i }) => {
                        const isError = "error" in track;
                        let discNo = group.discNo;
                        let trackNo = 0;

                        if (!isError) {
                          discNo = track.common?.disk?.no || group.discNo;
                          trackNo = track.common?.track?.no || 0;
                          if (!track.common?.disk?.no) {
                            const match = track.filename.match(/^(\d+)-(\d+)\b/);
                            if (match) discNo = parseInt(match[1], 10);
                          }
                        }

                        const trackNumDisplay = isError
                          ? "!!"
                          : isMultiDisc
                          ? `${discNo}-${(trackNo > 0 ? trackNo : i + 1)
                              .toString()
                              .padStart(2, "0")}`
                          : (trackNo > 0 ? trackNo : i + 1)
                              .toString()
                              .padStart(2, "0");

                        return (
                          <motion.div
                            key={i}
                            initial={{ opacity: 0, x: -10 }}
                            animate={{ opacity: 1, x: 0 }}
                            transition={{ delay: i * 0.02 }}
                            className={`group relative flex items-center justify-between p-2 rounded-lg transition-colors text-sm overflow-hidden select-none cursor-pointer ${playingTrack === track.filename ? "bg-white/10" : "hover:bg-white/5"}`}
                            onMouseDown={(e) =>
                              handleTrackMouseDown(e, track.filename)
                            }
                            onMouseMove={(e) =>
                              handleTrackMouseMove(e, track.filename)
                            }
                            onMouseUp={(e) => handleTrackMouseUp(e, track.filename)}
                            onMouseLeave={handleTrackMouseLeave}
                          >
                            {/* Progress Bar */}
                            {playingTrack === track.filename && (
                              <div
                                className="absolute inset-y-0 left-0 bg-white/10 z-0 pointer-events-none transition-[width] duration-100 ease-linear"
                                style={{ width: `${progress}%` }}
                              />
                            )}

                            <div className="relative z-10 flex items-center gap-3 min-w-0 pointer-events-none">
                              <span className={`text-white/30 font-mono text-right shrink-0 ${isMultiDisc ? "w-10" : "w-6"}`}>
                                {trackNumDisplay}
                              </span>
                              <div className="flex flex-col min-w-0 pr-2 pointer-events-auto">
                                <ScrollableTrackName
                                  text={
                                    isError
                                      ? track.filename
                                      : track.common?.title || track.filename
                                  }
                                  isError={isError}
                                />
                                <span className="text-[10px] text-white/30 truncate font-mono">
                                  {track.filename}
                                </span>
                              </div>
                            </div>
                            <div className="relative z-10 flex items-center gap-4 shrink-0">
                              {!isError && (
                                <div className="flex items-center gap-2 text-xs text-white/40 font-mono">
                                  <span>
                                    {track.format?.bitsPerSample}bit/
                                    {track.format?.sampleRate
                                      ? track.format.sampleRate / 1000
                                      : "?"}
                                    kHz
                                  </span>
                                  {process.env.NEXT_PUBLIC_SHOW_TRACK_BITRATE ===
                                    "true" && (
                                    <span>
                                      {Math.round(
                                        (track.format?.bitrate || 0) / 1000,
                                      )}
                                      kbps
                                    </span>
                                  )}
                                </div>
                              )}
                              {/* Spectrogram Button */}
                              <Button
                                variant="ghost"
                                size="icon"
                                className={`h-6 w-6 cursor-pointer relative z-20 ${spectrograms[track.filename]?.exists ? "text-primary hover:text-primary hover:bg-primary/10" : "text-white/20 hover:text-white hover:bg-white/10"}`}
                                onClick={(e) => {
                                  e.stopPropagation();
                                  const spec = spectrograms[track.filename];
                                  if (spec?.exists && spec.url) {
                                    setPreviewUrl(spec.url);
                                  }
                                }}
                                disabled={!spectrograms[track.filename]?.exists}
                                title="View Spectrogram"
                              >
                                <Activity className="w-3 h-3" />
                              </Button>
                            </div>
                          </motion.div>
                        );
                      })}
                    </div>
                  ))}
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Actions Column */}
        <div className="flex flex-col gap-6">
          {/* Quality Checks - Now Pre-flight */}
          <div
            className={`rounded-xl border transition-all duration-500 overflow-hidden shadow-sm ${
              !allChecksPassed
                ? "bg-amber-500/5 border-amber-500/30 shadow-[0_0_15px_rgba(245,158,11,0.1)] relative"
                : "bg-black/20 border-white/10"
            }`}
          >
            {!allChecksPassed && (
              <div className="absolute inset-0 bg-amber-500/5 animate-pulse pointer-events-none" />
            )}
            <div
              className={`py-3 px-4 border-b flex items-center justify-between relative z-10 ${!allChecksPassed ? "border-amber-500/20 bg-amber-500/10" : "border-white/5 bg-white/5"}`}
            >
              <h3
                className={`text-sm font-medium ${!allChecksPassed ? "text-amber-200" : "text-white/80"}`}
              >
                Pre-flight Checks
              </h3>
              <div className="flex gap-2 items-center">
                {!allChecksPassed && (
                  <Button
                    variant="ghost"
                    size="icon"
                    onClick={(e) => {
                      e.stopPropagation();
                      handleSkipPreflight();
                    }}
                    className="h-5 w-5 text-amber-500/50 hover:text-amber-500 hover:bg-amber-500/10 transition-colors"
                    title="Skip Checks (Unsafe)"
                  >
                    <FastForward className="w-3.5 h-3.5" />
                  </Button>
                )}
                <div className="flex gap-1">
                  {mqaStatus === "success" && (
                    <div className="w-2 h-2 rounded-full bg-green-500" />
                  )}
                  {upconvStatus === "success" && (
                    <div className="w-2 h-2 rounded-full bg-green-500" />
                  )}
                  {specsPassed && specsExist && (
                    <div className="w-2 h-2 rounded-full bg-green-500" />
                  )}
                </div>
              </div>
            </div>
            <div className="p-4 flex flex-col gap-2.5">
              <Button
                onClick={handleCheckMQA}
                disabled={checkingMQA}
                className={`w-full justify-start h-9 text-xs transition-all border border-white/5 ${mqaStatus === "success" ? "bg-green-500/20 text-green-400 hover:bg-green-500/30" : mqaStatus === "warning" ? "bg-yellow-500/20 text-yellow-400 hover:bg-yellow-500/30" : mqaStatus === "error" ? "bg-red-500/20 text-red-400 hover:bg-red-500/30" : "bg-white/5 hover:bg-white/10"}`}
                variant="ghost"
              >
                {checkingMQA ? (
                  <RefreshCw className="w-3.5 h-3.5 mr-2 animate-spin" />
                ) : mqaStatus === "success" ? (
                  <Check className="w-3.5 h-3.5 mr-2" />
                ) : mqaStatus === "warning" ? (
                  <AlertTriangle className="w-3.5 h-3.5 mr-2" />
                ) : (
                  <Activity className="w-3.5 h-3.5 mr-2 text-white/70" />
                )}
                {checkingMQA
                  ? "Checking..."
                  : mqaStatus === "success"
                    ? "MQA Not Detected"
                    : mqaStatus === "warning"
                      ? "MQA Detected"
                      : "Check for MQA"}
              </Button>

              {has24Bit && (
                <Button
                  onClick={handleCheckUpconv}
                  disabled={checkingUpconv}
                  className={`w-full justify-start h-9 text-xs transition-all border border-white/5 ${upconvStatus === "success" ? "bg-green-500/20 text-green-400 hover:bg-green-500/30" : upconvStatus === "error" ? "bg-red-500/20 text-red-400 hover:bg-red-500/30" : "bg-white/5 hover:bg-white/10"}`}
                  variant="ghost"
                >
                  {checkingUpconv ? (
                    <RefreshCw className="w-3.5 h-3.5 mr-2 animate-spin" />
                  ) : upconvStatus === "success" ? (
                    <Check className="w-3.5 h-3.5 mr-2" />
                  ) : (
                    <Activity className="w-3.5 h-3.5 mr-2 text-white/70" />
                  )}
                  {checkingUpconv
                    ? "Checking..."
                    : upconvStatus === "success"
                      ? "Zero Upconverts Detected"
                      : "Check for Upconverts"}
                </Button>
              )}

              <Button
                onClick={() => {
                  setShowAllSpectrograms(true);
                  setSpectrogramsViewed(true);
                }}
                disabled={Object.keys(spectrograms).length === 0}
                className={`w-full justify-start h-9 text-xs transition-all border border-white/5 ${spectrogramsViewed ? "bg-green-500/20 text-green-400 hover:bg-green-500/30" : "bg-white/5 hover:bg-white/10"}`}
                variant="ghost"
              >
                {spectrogramsViewed ? (
                  <Check className="w-3.5 h-3.5 mr-2" />
                ) : (
                  <Waves className="w-3.5 h-3.5 mr-2 text-blue-400" />
                )}
                {spectrogramsViewed
                  ? "Spectrograms Viewed"
                  : "View Spectrograms"}
              </Button>
            </div>
          </div>

          {/* Release Workflow Stepper */}
          <div className="rounded-xl bg-black/20 border border-white/10 overflow-hidden shadow-sm flex flex-col">
            <div className="py-3 px-4 border-b border-white/5 bg-white/5 flex items-center justify-between">
              <h3 className="text-sm font-medium text-white/80">
                Release Workflow
              </h3>
              {(!(
                sanitizeStatus !== "idle" ||
                torrentStatus !== "idle" ||
                copyStatus !== "idle" ||
                uploadingCover ||
                !!coverUrl ||
                injectionStatus !== "idle" ||
                Object.keys(skippedSteps).length > 0
              ) ||
                autoModeStarted) && (
                <Button
                  size="sm"
                  variant="secondary"
                  className="h-6 text-xs bg-white/10 hover:bg-white/20 text-white"
                  onClick={() => {
                    setAutoModeStarted(true);
                    setAutoMode(true);
                  }}
                  disabled={!allChecksPassed || autoModeStarted}
                >
                  {autoMode ? (
                    <RefreshCw className="w-3 h-3 mr-1 animate-spin" />
                  ) : (
                    <Play className="w-3 h-3 mr-1" />
                  )}
                  {autoMode ? "Running..." : "Auto 1-5"}
                </Button>
              )}
            </div>
            <div
              className={`p-6 flex flex-col relative transition-opacity duration-300 ${!allChecksPassed ? "opacity-30 pointer-events-none" : ""}`}
            >
              {/* Vertical Line */}
              <div className="absolute left-[39px] top-6 bottom-6 w-px bg-white/10" />

              {/* Step 1: Sanitize */}
              <WorkflowStep
                number={1}
                title="Sanitize Album"
                description={
                  !allChecksPassed
                    ? "Complete pre-flight checks first"
                    : "Normalise file names and remove special characters"
                }
                status={
                  skippedSteps[1]
                    ? "skipped"
                    : sanitizeStatus === "success"
                      ? "completed"
                      : sanitizeStatus === "error"
                        ? "error"
                        : sanitizing
                          ? "loading"
                          : "pending"
                }
                isActive={sanitizeStatus !== "success" && !skippedSteps[1]}
                onClick={handleSanitize}
                onSkip={() => setSkippedSteps((prev) => ({ ...prev, 1: true }))}
                icon={<ShieldCheck className="w-4 h-4" />}
                actionLabel="Sanitize"
                disabled={!allChecksPassed}
                allChecksPassed={allChecksPassed}
              />

              {/* Step 2: Create Torrent */}
              <WorkflowStep
                number={2}
                title="Create Torrent"
                description="Generate .torrent file"
                status={
                  skippedSteps[2]
                    ? "skipped"
                    : torrentStatus === "success"
                      ? "completed"
                      : torrentStatus === "error"
                        ? "error"
                        : torrenting
                          ? "loading"
                          : "pending"
                }
                isActive={
                  (sanitizeStatus === "success" || skippedSteps[1]) &&
                  torrentStatus !== "success" &&
                  !skippedSteps[2]
                }
                onClick={handleTorrent}
                onSkip={() => setSkippedSteps((prev) => ({ ...prev, 2: true }))}
                icon={<Download className="w-4 h-4" />}
                actionLabel="Create Torrent"
                disabled={hasLongFilenames}
                allChecksPassed={allChecksPassed}
              />

              {/* Step 3: Copy/Finalize */}
              <WorkflowStep
                number={3}
                title="Copy to Output"
                description="Copy album to the output directory"
                status={
                  skippedSteps[3]
                    ? "skipped"
                    : copyStatus === "success"
                      ? "completed"
                      : copyStatus === "error"
                        ? "error"
                        : copying
                          ? "loading"
                          : "pending"
                }
                isActive={
                  (sanitizeStatus === "success" || skippedSteps[1]) &&
                  (torrentStatus === "success" || skippedSteps[2]) &&
                  copyStatus !== "success" &&
                  !skippedSteps[3]
                }
                onClick={handleCopy}
                onSkip={() => setSkippedSteps((prev) => ({ ...prev, 3: true }))}
                icon={<HardDrive className="w-4 h-4" />}
                actionLabel="Copy to Output"
                allChecksPassed={allChecksPassed}
              />

              {/* Step 4: Cover Art */}
              <WorkflowStep
                number={4}
                title="Cover Art"
                description="Upload cover artwork"
                status={
                  skippedSteps[4]
                    ? "skipped"
                    : coverUrl
                      ? "completed"
                      : uploadingCover
                        ? "loading"
                        : "pending"
                }
                isActive={
                  (sanitizeStatus === "success" || skippedSteps[1]) &&
                  (torrentStatus === "success" || skippedSteps[2]) &&
                  (copyStatus === "success" || skippedSteps[3]) &&
                  !coverUrl &&
                  !skippedSteps[4]
                }
                onClick={handleUploadCover}
                onSkip={() => setSkippedSteps((prev) => ({ ...prev, 4: true }))}
                icon={<Upload className="w-4 h-4" />}
                actionLabel="Upload Cover"
                disabled={!album.coverPath}
                allChecksPassed={allChecksPassed}
              />

              {/* Step 5: Inject */}
              <WorkflowStep
                number={5}
                title="Inject to Client"
                description="Add to qBittorrent"
                status={
                  skippedSteps[5]
                    ? "skipped"
                    : injectionStatus === "success" ||
                        injectionStatus === "resumed"
                      ? "completed"
                      : injectionStatus === "error"
                        ? "error"
                        : injecting ||
                            injectionStatus === "injecting" ||
                            injectionStatus === "checking"
                          ? "loading"
                          : "pending"
                }
                isActive={
                  (sanitizeStatus === "success" || skippedSteps[1]) &&
                  (torrentStatus === "success" || skippedSteps[2]) &&
                  (copyStatus === "success" || skippedSteps[3]) &&
                  (!!coverUrl || skippedSteps[4]) &&
                  injectionStatus !== "success" &&
                  injectionStatus !== "resumed" &&
                  !skippedSteps[5]
                }
                onClick={handleInject}
                onSkip={() => setSkippedSteps((prev) => ({ ...prev, 5: true }))}
                icon={<Magnet className="w-4 h-4" />}
                actionLabel={
                  injectionStatus === "checking"
                    ? `Checking ${recheckProgress}%`
                    : "Inject"
                }
                disabled={injectionStatus === "checking"}
                allChecksPassed={allChecksPassed}
              />

              {/* Step 6: RED Template */}
              <WorkflowStep
                number={6}
                title="RED Template"
                description="Generate upload metadata"
                status={
                  skippedSteps[6]
                    ? "skipped"
                    : generatingTemplate
                      ? generatedFiles.json
                        ? "reloading"
                        : "loading"
                      : generatedFiles.json
                        ? "completed"
                        : "pending"
                }
                isActive={
                  (sanitizeStatus === "success" || skippedSteps[1]) &&
                  (torrentStatus === "success" || skippedSteps[2]) &&
                  (copyStatus === "success" || skippedSteps[3]) &&
                  (!!coverUrl || skippedSteps[4]) &&
                  (injectionStatus === "success" ||
                    injectionStatus === "resumed" ||
                    skippedSteps[5]) &&
                  !generatedFiles.json &&
                  !skippedSteps[6]
                }
                onClick={async () => {
                  setGeneratingTemplate(true);
                  addLog("Generating RED upload template...");
                  try {
                    const res = await fetch("/api/red-template", {
                      method: "POST",
                      headers: { "Content-Type": "application/json" },
                      body: JSON.stringify({
                        albumPath: album.path,
                        releaseType: releaseType,
                      }),
                    });
                    const result = await res.json();
                    if (result.response) {
                      if (coverUrl) {
                        if (!result.response.group) result.response.group = {};
                        result.response.group.wikiImage = coverUrl;
                      }
                      const jsonString = JSON.stringify(result, null, 4);
                      await navigator.clipboard.writeText(jsonString);
                      // Mocking the generated file state for the stepper visual
                      setGeneratedFiles((prev) => ({
                        ...prev,
                        json: { name: "Template", url: "" },
                      }));
                      addLog("Template copied to clipboard!");
                    } else {
                      addLog(`Template generation failed: ${result.error}`);
                    }
                  } catch (e) {
                    addLog("Template request failed.");
                  } finally {
                    setGeneratingTemplate(false);
                  }
                }}
                onSkip={() => setSkippedSteps((prev) => ({ ...prev, 6: true }))}
                icon={<FileJson className="w-4 h-4" />}
                actionLabel="Copy Template"
                allChecksPassed={allChecksPassed}
                allowCompletedClick={true}
              />

              {/* Info Message */}
              {(generatedFiles.json || skippedSteps[6]) &&
                injectionStatus !== "resumed" && (
                  <div className="ml-0 p-3 rounded-md bg-blue-400/20 text-white text-xs mb-4 -mt-4 backdrop-blur-sm">
                    <p className="font-semibold mb-1">Ready to Upload!</p>
                    <p>You can now finalise the upload on RED.</p>
                    <p>Return here and resume when ready.</p>
                  </div>
                )}

              {/* Step 7: Resume */}
              <WorkflowStep
                number={7}
                title="Resume Torrent"
                description="Start seeding"
                status={
                  skippedSteps[7]
                    ? "skipped"
                    : injectionStatus === "resumed"
                      ? "completed"
                      : resuming
                        ? "loading"
                        : "pending"
                }
                isActive={
                  (sanitizeStatus === "success" || skippedSteps[1]) &&
                  (torrentStatus === "success" || skippedSteps[2]) &&
                  (copyStatus === "success" || skippedSteps[3]) &&
                  (!!coverUrl || skippedSteps[4]) &&
                  (injectionStatus === "success" ||
                    injectionStatus === "resumed" ||
                    skippedSteps[5]) &&
                  (!!generatedFiles.json || skippedSteps[6]) &&
                  injectionStatus !== "resumed" &&
                  !skippedSteps[7]
                }
                onClick={handleResume}
                onSkip={() => setSkippedSteps((prev) => ({ ...prev, 7: true }))}
                icon={<Play className="w-4 h-4" />}
                actionLabel="Resume Torrent"
                disabled={
                  resuming ||
                  (injectionStatus !== "success" && !skippedSteps[5])
                }
                allChecksPassed={allChecksPassed}
              />
            </div>
          </div>

          <HoldButton
            onComplete={async () => {
              setDeleting(true);
              addLog("Deleting album...");
              if (audioRef.current) {
                audioRef.current.pause();
                audioRef.current.removeAttribute("src");
                audioRef.current.load();
              }
              setPlayingTrack(null);
              setIsPlaying(false);
              await new Promise((resolve) => setTimeout(resolve, 100));
              try {
                const res = await fetch("/api/delete", {
                  method: "POST",
                  headers: { "Content-Type": "application/json" },
                  body: JSON.stringify({
                    albumPath: album.path,
                    upc: data.metadata.upc,
                  }),
                });
                const result = await res.json();
                if (result.success) {
                  addLog("Album deleted successfully.");
                  // Trigger a rescan to update the list
                  await fetch("/api/scan", { method: "POST" });
                  // Redirect to home
                  window.location.href = "/";
                } else {
                  addLog(`Delete failed: ${result.error}`);
                  setDeleting(false);
                }
              } catch (e) {
                addLog("Delete request failed.");
                setDeleting(false);
              }
            }}
            disabled={deleting}
            className="w-full justify-start h-10 text-sm transition-all bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 relative overflow-hidden"
          >
            {deleting ? (
              <RefreshCw className="w-4 h-4 mr-3 animate-spin relative z-10" />
            ) : (
              <Trash2 className="w-4 h-4 mr-3 relative z-10" />
            )}
            <span className="relative z-10">
              {deleting ? "Deleting..." : "Hold to Delete"}
            </span>
          </HoldButton>
        </div>
      </div>

      {previewUrl &&
        createPortal(
          <div
            className="fixed inset-0 z-[100] bg-black/80 flex items-center justify-center p-8 backdrop-blur-sm"
            onClick={() => setPreviewUrl(null)}
          >
            <div
              className="relative max-w-full max-h-full bg-background/10 rounded-lg overflow-hidden shadow-2xl border border-white/10"
              onClick={(e) => e.stopPropagation()}
            >
              <img
                src={previewUrl!}
                alt="Spectrogram"
                className="max-w-full max-h-[90vh] object-contain"
              />
              <Button
                variant="ghost"
                size="icon"
                className="absolute top-2 right-2 text-white/70 hover:text-white bg-black/40 hover:bg-black/60 rounded-full"
                onClick={() => setPreviewUrl(null)}
              >
                <X className="w-5 h-5" />
              </Button>
            </div>
          </div>,
          document.body,
        )}

      {showAllSpectrograms &&
        createPortal(
          <div
            className="fixed inset-0 z-[100] bg-black/95 flex flex-col p-4 md:p-8 backdrop-blur-md overflow-hidden animate-in fade-in duration-200"
            onClick={() => setShowAllSpectrograms(false)}
          >
            <div
              className="max-w-5xl w-full mx-auto flex flex-col h-full bg-zinc-900/50 rounded-2xl border border-white/10 shadow-2xl overflow-hidden ring-1 ring-white/5"
              onClick={(e) => e.stopPropagation()}
            >
              {/* Header */}
              <div className="flex justify-between items-center p-6 border-b border-white/5 bg-black/40 shrink-0">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 rounded-full bg-blue-500/10 flex items-center justify-center border border-blue-500/20">
                    <Waves className="w-5 h-5 text-blue-400" />
                  </div>
                  <div>
                    <h2 className="text-xl font-bold text-white">
                      Album Spectrograms
                    </h2>
                    <p className="text-sm text-white/50">
                      {tracks.length} tracks generated
                    </p>
                  </div>
                </div>
                <Button
                  variant="ghost"
                  size="icon"
                  className="text-white/50 hover:text-white hover:bg-white/10 rounded-full transition-colors"
                  onClick={() => setShowAllSpectrograms(false)}
                >
                  <X className="w-6 h-6" />
                </Button>
              </div>

              {/* Content */}
              <div className="flex-1 overflow-y-auto p-6 space-y-8 [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-white/10 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-white/20">
                {spectrogramsMemo}
                {Object.keys(spectrograms).length === 0 && (
                  <div className="flex flex-col items-center justify-center py-20 text-white/30 gap-4">
                    <Waves className="w-12 h-12 opacity-50" />
                    <p>No spectrograms generated yet.</p>
                  </div>
                )}
              </div>
            </div>
          </div>,
          document.body,
        )}

      <RenameDialog
        open={showRenameDialog}
        onOpenChange={setShowRenameDialog}
        albumPath={album.path}
        onRenameComplete={() => {
          addLog("Renamed files successfully.");
          analyzeAlbum(); // Re-analyze to update UI
        }}
      />
    </div>
  );
}

interface WorkflowStepProps {
  number: number;
  title: string;
  description: string;
  status:
    | "skipped"
    | "completed"
    | "error"
    | "loading"
    | "pending"
    | "reloading";
  isActive: boolean;
  onClick: () => void;
  onSkip?: () => void;
  icon: React.ReactNode;
  actionLabel: string;
  disabled?: boolean;
  allChecksPassed?: boolean;
  allowCompletedClick?: boolean;
}

function WorkflowStep({
  number,
  title,
  description,
  status,
  isActive,
  onClick,
  onSkip,
  icon,
  actionLabel,
  disabled,
  allChecksPassed,
  allowCompletedClick,
}: WorkflowStepProps) {
  return (
    <div
      className={`relative flex gap-4 pb-8 last:pb-0 ${isActive ? "opacity-100" : "opacity-50 transition-opacity"}`}
    >
      {/* Circle */}
      <div
        className={`relative z-10 flex items-center justify-center w-8 h-8 rounded-full border-2 transition-colors shrink-0 ${
          status === "completed" || status === "reloading"
            ? "bg-green-500 border-green-500 text-black"
            : status === "skipped"
              ? "bg-yellow-500 border-yellow-500 text-black"
              : status === "error"
                ? "bg-red-500 border-red-500 text-white"
                : isActive
                  ? "bg-primary border-primary text-primary-foreground"
                  : "bg-background border-white/20 text-muted-foreground"
        }`}
      >
        {status === "completed" || status === "reloading" ? (
          <Check className="w-4 h-4" />
        ) : status === "skipped" ? (
          <FastForward className="w-4 h-4" />
        ) : status === "error" ? (
          <AlertTriangle className="w-4 h-4" />
        ) : status === "loading" ? (
          <RefreshCw className="w-4 h-4 animate-spin" />
        ) : (
          <span className="text-xs font-bold">{number}</span>
        )}
      </div>

      {/* Content */}
      <div className="flex-1 pt-1">
        <div className="flex justify-between items-start mb-1">
          <div>
            <h4
              className={`text-sm font-medium leading-none ${status === "completed" || status === "reloading" ? "text-green-400" : status === "skipped" ? "text-yellow-400" : "text-white"}`}
            >
              {title}
            </h4>
            <p className="text-xs text-muted-foreground mt-1">{description}</p>
          </div>
          {isActive && onSkip && allChecksPassed && (
            <Button
              variant="ghost"
              size="icon"
              onClick={onSkip}
              className="h-6 w-6 -mt-1 text-muted-foreground hover:text-yellow-400 hover:bg-yellow-500/10"
              title="Skip this step"
            >
              <FastForward className="w-3.5 h-3.5" />
            </Button>
          )}
        </div>

        {(isActive ||
          status === "loading" ||
          status === "reloading" ||
          status === "error" ||
          (status === "completed" && allowCompletedClick)) && (
          <motion.div
            initial={{ opacity: 0, height: 0 }}
            animate={{ opacity: 1, height: "auto" }}
            className="mt-3"
          >
            <Button
              size="sm"
              onClick={onClick}
              disabled={
                disabled ||
                status === "loading" ||
                status === "reloading" ||
                (!allowCompletedClick && status === "completed") ||
                status === "skipped"
              }
              className={`w-full justify-start h-8 text-xs disabled:opacity-100 ${status === "completed" || status === "reloading" ? "!bg-green-500/20 !text-green-400 !border-green-500/30 hover:!bg-green-500/30" : status === "skipped" ? "!bg-yellow-500/20 !text-yellow-400 !border-yellow-500/30 hover:!bg-yellow-500/30" : ""}`}
              variant={
                status === "completed" ||
                status === "reloading" ||
                status === "skipped"
                  ? "outline"
                  : "default"
              }
            >
              {status === "loading" || status === "reloading" ? (
                <RefreshCw className="w-3.5 h-3.5 mr-2 animate-spin" />
              ) : (
                icon
              )}
              <span className="ml-2">{actionLabel}</span>
            </Button>
          </motion.div>
        )}
      </div>
    </div>
  );
}

function ScrollableTrackName({
  text,
  isError,
}: {
  text: string;
  isError: boolean;
}) {
  const [isHovered, setIsHovered] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
  const textRef = useRef<HTMLSpanElement>(null);
  const [scrollDistance, setScrollDistance] = useState(0);
  const [duration, setDuration] = useState(0);

  useEffect(() => {
    if (containerRef.current && textRef.current) {
      const containerWidth = containerRef.current.offsetWidth;
      const textWidth = textRef.current.offsetWidth;

      if (textWidth > containerWidth) {
        const distance = textWidth - containerWidth + 20; // Add some padding
        setScrollDistance(distance);
        setDuration(distance * 0.05); // Adjust speed (seconds per pixel)
      } else {
        setScrollDistance(0);
      }
    }
  }, [text]);

  return (
    <div
      ref={containerRef}
      className="overflow-hidden relative h-5 flex items-center"
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
    >
      <motion.span
        ref={textRef}
        className={`whitespace-nowrap ${isError ? "text-red-400" : "group-hover:text-primary transition-colors"}`}
        animate={
          isHovered && scrollDistance > 0 ? { x: -scrollDistance } : { x: 0 }
        }
        transition={{
          type: "spring",
          stiffness: 100,
          damping: 100,

          repeatType: "mirror",
          repeatDelay: 1,
        }}
        style={{ x: 0 }}
      >
        {text}
      </motion.span>
    </div>
  );
}

function HoldButton({ onComplete, disabled, className, children }: any) {
  const [holding, setHolding] = useState(false);
  const [progress, setProgress] = useState(0);
  const intervalRef = useRef<NodeJS.Timeout | null>(null);

  const startHold = () => {
    if (disabled) return;
    setHolding(true);
    setProgress(0);
    const startTime = Date.now();
    const envDuration = process.env.NEXT_PUBLIC_DELETE_HOLD_TIME_MS
      ? parseInt(process.env.NEXT_PUBLIC_DELETE_HOLD_TIME_MS)
      : 1500;
    const duration = isNaN(envDuration) ? 1500 : envDuration;

    intervalRef.current = setInterval(() => {
      const elapsed = Date.now() - startTime;
      const newProgress = Math.min((elapsed / duration) * 100, 100);
      setProgress(newProgress);

      if (newProgress >= 100) {
        if (intervalRef.current) clearInterval(intervalRef.current);
        setHolding(false);
        setProgress(0);
        onComplete();
      }
    }, 16);
  };

  const stopHold = () => {
    if (intervalRef.current) clearInterval(intervalRef.current);
    setHolding(false);
    setProgress(0);
  };

  return (
    <Button
      onMouseDown={startHold}
      onMouseUp={stopHold}
      onMouseLeave={stopHold}
      onTouchStart={startHold}
      onTouchEnd={stopHold}
      disabled={disabled}
      className={className}
      variant="ghost"
    >
      <div
        className="absolute inset-0 bg-red-500/30 transition-all duration-75 ease-linear"
        style={{ width: `${progress}%` }}
      />
      {children}
    </Button>
  );
}

function formatBytes(bytes: number, decimals = 2) {
  if (!+bytes) return "0 Bytes";

  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];

  // Start from MB (index 1) as audio albums are rarely just bytes or KB in these contexts,
  // but generic logic is fine. FLAC albums are usually MB or GB.
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}
