'use client'; import React, { useState, useEffect } from 'react'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; import { Progress } from "@/components/ui/progress"; import { useToast } from "@/hooks/use-toast"; import { useAutoTagging, EnhancedTrackMetadata, EnhancedAlbumMetadata } from "@/hooks/use-auto-tagging"; import { useIsMobile } from "@/hooks/use-mobile"; import { MusicIcon, AlbumIcon, UsersIcon, CheckCircle2Icon, XCircleIcon, AlertTriangleIcon, InfoIcon } from 'lucide-react'; import Image from 'next/image'; interface AutoTaggingDialogProps { isOpen: boolean; onClose: () => void; mode: 'track' | 'album' | 'artist'; itemId: string; itemName: string; artistName?: string; } export const AutoTaggingDialog: React.FC = ({ isOpen, onClose, mode, itemId, itemName, artistName }) => { const isMobile = useIsMobile(); const { toast } = useToast(); const [confidenceThreshold, setConfidenceThreshold] = useState(70); const [activeTab, setActiveTab] = useState<'tracks' | 'albums'>('tracks'); const [isApplying, setIsApplying] = useState(false); const { isProcessing, progress, enhancedTracks, enhancedAlbums, startAutoTagging, applyEnhancedMetadata } = useAutoTagging(); // Start auto-tagging when the dialog is opened useEffect(() => { if (isOpen && itemId && !isProcessing && progress === 0) { // Wrap in try/catch to handle any errors that might occur during auto-tagging try { startAutoTagging(mode, itemId, confidenceThreshold); } catch (error) { console.error('Failed to start auto-tagging:', error); toast({ title: "Auto-Tagging Error", description: error instanceof Error ? error.message : "Failed to start auto-tagging", variant: "destructive", }); onClose(); } } }, [isOpen, itemId, mode, isProcessing, progress, startAutoTagging, confidenceThreshold, toast, onClose]); // Set the active tab based on the mode useEffect(() => { if (mode === 'track') { setActiveTab('tracks'); } else if (mode === 'album' || mode === 'artist') { setActiveTab('albums'); } }, [mode]); const handleApplyMetadata = async () => { try { setIsApplying(true); await applyEnhancedMetadata( enhancedTracks.filter(track => track.status === 'matched' && track.confidence >= confidenceThreshold), enhancedAlbums.filter(album => album.status === 'matched' && album.confidence >= confidenceThreshold) ); onClose(); } catch (error) { console.error('Failed to apply metadata:', error); toast({ title: "Error", description: "Failed to apply metadata", variant: "destructive", }); } finally { setIsApplying(false); } }; // Get match statistics const matchedTracks = enhancedTracks.filter(track => track.status === 'matched' && track.confidence >= confidenceThreshold).length; const totalTracks = enhancedTracks.length; const matchedAlbums = enhancedAlbums.filter(album => album.status === 'matched' && album.confidence >= confidenceThreshold).length; const totalAlbums = enhancedAlbums.length; const getStatusIcon = (status: 'pending' | 'matched' | 'failed' | 'applied', confidence: number) => { if (status === 'pending') return ; if (status === 'failed') return ; if (status === 'matched' && confidence >= confidenceThreshold) return ; if (status === 'matched' && confidence < confidenceThreshold) return ; if (status === 'applied') return ; return null; }; const getConfidenceColor = (confidence: number) => { if (confidence >= 90) return 'bg-green-500'; if (confidence >= 70) return 'bg-green-400'; if (confidence >= 50) return 'bg-yellow-500'; return 'bg-red-500'; }; // Render the appropriate dialog/sheet based on mobile status const DialogComponent = isMobile ? Sheet : Dialog; const DialogContentComponent = isMobile ? SheetContent : DialogContent; const DialogHeaderComponent = isMobile ? SheetHeader : DialogHeader; const DialogTitleComponent = isMobile ? SheetTitle : DialogTitle; const DialogDescriptionComponent = isMobile ? SheetDescription : DialogDescription; return ( !open && onClose()}> Auto-Tagging {mode === 'track' ? 'Track' : mode === 'album' ? 'Album' : 'Artist'} {isProcessing ? ( `Analyzing ${mode === 'track' ? 'track' : mode === 'album' ? 'album' : 'artist'} "${itemName}"` ) : ( `Found metadata for ${matchedTracks} of ${totalTracks} tracks${totalAlbums > 0 ? ` and ${matchedAlbums} of ${totalAlbums} albums` : ''}` )} {/* Progress bar */} {(isProcessing || isApplying) && (

{isProcessing ? 'Analyzing metadata...' : 'Applying metadata...'}

)}
{/* Tabs for tracks and albums */} {!isProcessing && !isApplying && (
setActiveTab(value as 'tracks' | 'albums')} className="flex-1 flex flex-col">
Tracks ({matchedTracks}/{totalTracks}) Albums ({matchedAlbums}/{totalAlbums}) {/* Confidence threshold slider */}
Min. Confidence: {confidenceThreshold}% setConfidenceThreshold(parseInt(e.target.value))} className="w-24" />
{/* Tracks tab content */}
Title
Artist
Album
Confidence
{enhancedTracks.map(track => (
{getStatusIcon(track.status, track.confidence)}
{track.title}
{track.artist}
{track.album}
{track.confidence}%
))}
{/* Albums tab content */}
{enhancedAlbums.map(album => (
{/* Album cover */}
{album.coverArtUrl ? ( {album.name} ) : (
)} {/* Status badge */}
{getStatusIcon(album.status, album.confidence)}
{/* Album info */}

{album.name}

{album.artist}

{album.confidence}%
{album.year && (

Year: {album.year}

)}
))}
)}
); }; export default AutoTaggingDialog;