"use client"

import type React from "react"

import { useState, useRef, useCallback } from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Progress } from "@/components/ui/progress"
import { useToast } from "@/hooks/use-toast"
import { Upload, FileAudio, Download, Trash2, CheckCircle, XCircle, Loader2, Settings2, Music, Zap } from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Badge } from "@/components/ui/badge"
import { formatDuration } from "@/lib/audio-utils"

interface AudioFile {
  id: string
  file: File
  name: string
  originalSize: number
  convertedBlob?: Blob
  convertedSize?: number
  status: "pending" | "processing" | "complete" | "error"
  progress: number
  error?: string
  duration?: number
}

interface ConversionSettings {
  targetBitrate: number // kbps
  targetSampleRate: number // Hz
  channels: 1 | 2 // mono or stereo
}

declare global {
  interface Window {
    lamejs: any
  }
}

export default function AudioConverterPage() {
  const { toast } = useToast()
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [files, setFiles] = useState<AudioFile[]>([])
  const [isProcessing, setIsProcessing] = useState(false)
  const [lameLoaded, setLameLoaded] = useState(false)
  const [settings, setSettings] = useState<ConversionSettings>({
    targetBitrate: 64, // Lower bitrate for smaller files
    targetSampleRate: 22050, // Lower sample rate
    channels: 1, // Mono for smallest size
  })

  const loadLameJs = useCallback(async () => {
    if (window.lamejs) {
      setLameLoaded(true)
      return true
    }

    return new Promise<boolean>((resolve) => {
      const script = document.createElement("script")
      script.src = "https://cdn.jsdelivr.net/npm/lamejs@1.2.1/lame.min.js"
      script.onload = () => {
        setLameLoaded(true)
        resolve(true)
      }
      script.onerror = () => {
        console.error("Failed to load lamejs")
        resolve(false)
      }
      document.head.appendChild(script)
    })
  }, [])

  const handleFileSelect = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      // Load lamejs if not already loaded
      if (!lameLoaded) {
        await loadLameJs()
      }

      const selectedFiles = Array.from(e.target.files || [])

      const audioFiles: AudioFile[] = selectedFiles
        .filter(
          (file) =>
            file.type.startsWith("audio/") ||
            [".mp3", ".wav", ".flac", ".ogg", ".m4a", ".aac"].some((ext) => file.name.toLowerCase().endsWith(ext)),
        )
        .map((file) => ({
          id: `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
          file,
          name: file.name,
          originalSize: file.size,
          status: "pending" as const,
          progress: 0,
        }))

      if (audioFiles.length === 0) {
        toast({
          title: "Aucun fichier audio",
          description: "Veuillez sélectionner des fichiers audio valides",
          variant: "destructive",
        })
        return
      }

      setFiles((prev) => [...prev, ...audioFiles])

      // Extract duration for each file
      audioFiles.forEach((audioFile) => {
        const audio = new Audio()
        audio.src = URL.createObjectURL(audioFile.file)
        audio.addEventListener("loadedmetadata", () => {
          setFiles((prev) =>
            prev.map((f) => (f.id === audioFile.id ? { ...f, duration: Math.round(audio.duration) } : f)),
          )
          URL.revokeObjectURL(audio.src)
        })
      })

      if (fileInputRef.current) {
        fileInputRef.current.value = ""
      }
    },
    [toast, lameLoaded, loadLameJs],
  )

  const processFile = async (audioFile: AudioFile): Promise<Blob> => {
    // Ensure lamejs is loaded
    if (!window.lamejs) {
      await loadLameJs()
    }

    return new Promise((resolve, reject) => {
      const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)()
      const reader = new FileReader()

      reader.onload = async (e) => {
        try {
          const arrayBuffer = e.target?.result as ArrayBuffer
          const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)

          const targetSampleRate = settings.targetSampleRate
          const numChannels = settings.channels
          const bitrate = settings.targetBitrate

          // Create offline context for resampling
          const offlineContext = new OfflineAudioContext(
            numChannels,
            Math.ceil(audioBuffer.duration * targetSampleRate),
            targetSampleRate,
          )

          const source = offlineContext.createBufferSource()
          source.buffer = audioBuffer

          // Convert to mono if needed
          if (numChannels === 1 && audioBuffer.numberOfChannels > 1) {
            const merger = offlineContext.createChannelMerger(1)
            source.connect(merger)
            merger.connect(offlineContext.destination)
          } else {
            source.connect(offlineContext.destination)
          }

          source.start(0)
          const renderedBuffer = await offlineContext.startRendering()

          // Encode to MP3 using lamejs
          const mp3Blob = encodeMP3(renderedBuffer, bitrate)

          audioContext.close()
          resolve(mp3Blob)
        } catch (error) {
          audioContext.close()
          reject(error)
        }
      }

      reader.onerror = () => reject(new Error("Failed to read file"))
      reader.readAsArrayBuffer(audioFile.file)
    })
  }

  const encodeMP3 = (audioBuffer: AudioBuffer, bitrate: number): Blob => {
    const numChannels = audioBuffer.numberOfChannels
    const sampleRate = audioBuffer.sampleRate
    const samples = audioBuffer.length

    // Initialize MP3 encoder
    const mp3encoder = new window.lamejs.Mp3Encoder(numChannels, sampleRate, bitrate)
    const mp3Data: Int8Array[] = []

    // Get audio data
    const left = audioBuffer.getChannelData(0)
    const right = numChannels > 1 ? audioBuffer.getChannelData(1) : null

    // Convert Float32 to Int16
    const leftInt16 = new Int16Array(samples)
    const rightInt16 = right ? new Int16Array(samples) : null

    for (let i = 0; i < samples; i++) {
      leftInt16[i] = Math.max(-32768, Math.min(32767, Math.floor(left[i] * 32767)))
      if (rightInt16 && right) {
        rightInt16[i] = Math.max(-32768, Math.min(32767, Math.floor(right[i] * 32767)))
      }
    }

    // Encode in chunks
    const sampleBlockSize = 1152
    for (let i = 0; i < samples; i += sampleBlockSize) {
      const leftChunk = leftInt16.subarray(i, i + sampleBlockSize)
      const rightChunk = rightInt16 ? rightInt16.subarray(i, i + sampleBlockSize) : null

      let mp3buf: Int8Array
      if (numChannels === 1) {
        mp3buf = mp3encoder.encodeBuffer(leftChunk)
      } else {
        mp3buf = mp3encoder.encodeBuffer(leftChunk, rightChunk)
      }

      if (mp3buf.length > 0) {
        mp3Data.push(mp3buf)
      }
    }

    // Flush remaining data
    const mp3buf = mp3encoder.flush()
    if (mp3buf.length > 0) {
      mp3Data.push(mp3buf)
    }

    // Combine all chunks
    const totalLength = mp3Data.reduce((sum, chunk) => sum + chunk.length, 0)
    const mp3Array = new Uint8Array(totalLength)
    let offset = 0
    for (const chunk of mp3Data) {
      mp3Array.set(chunk, offset)
      offset += chunk.length
    }

    return new Blob([mp3Array], { type: "audio/mp3" })
  }

  const processAllFiles = async () => {
    setIsProcessing(true)

    // Ensure lamejs is loaded
    if (!window.lamejs) {
      const loaded = await loadLameJs()
      if (!loaded) {
        toast({
          title: "Erreur",
          description: "Impossible de charger l'encodeur MP3",
          variant: "destructive",
        })
        setIsProcessing(false)
        return
      }
    }

    for (const audioFile of files.filter((f) => f.status === "pending")) {
      setFiles((prev) => prev.map((f) => (f.id === audioFile.id ? { ...f, status: "processing", progress: 10 } : f)))

      try {
        // Simulate progress updates
        const progressInterval = setInterval(() => {
          setFiles((prev) =>
            prev.map((f) =>
              f.id === audioFile.id && f.status === "processing" && f.progress < 90
                ? { ...f, progress: f.progress + 10 }
                : f,
            ),
          )
        }, 200)

        const convertedBlob = await processFile(audioFile)

        clearInterval(progressInterval)

        setFiles((prev) =>
          prev.map((f) =>
            f.id === audioFile.id
              ? {
                  ...f,
                  status: "complete",
                  progress: 100,
                  convertedBlob,
                  convertedSize: convertedBlob.size,
                }
              : f,
          ),
        )
      } catch (error) {
        setFiles((prev) =>
          prev.map((f) =>
            f.id === audioFile.id
              ? {
                  ...f,
                  status: "error",
                  progress: 0,
                  error: error instanceof Error ? error.message : "Conversion failed",
                }
              : f,
          ),
        )
      }
    }

    setIsProcessing(false)
    toast({
      title: "Conversion terminée",
      description: "Tous les fichiers ont été traités",
    })
  }

  const downloadFile = (audioFile: AudioFile) => {
    if (!audioFile.convertedBlob) return

    const url = URL.createObjectURL(audioFile.convertedBlob)
    const a = document.createElement("a")
    a.href = url
    a.download = audioFile.name.replace(/\.[^/.]+$/, "") + "_compressed.mp3"
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  }

  const downloadAll = () => {
    files.filter((f) => f.status === "complete" && f.convertedBlob).forEach((f) => downloadFile(f))
  }

  const removeFile = (id: string) => {
    setFiles((prev) => prev.filter((f) => f.id !== id))
  }

  const clearAll = () => {
    setFiles([])
  }

  const formatSize = (bytes: number): string => {
    if (bytes < 1024) return bytes + " B"
    if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB"
    return (bytes / (1024 * 1024)).toFixed(2) + " MB"
  }

  const getCompressionRatio = (original: number, converted: number): string => {
    const ratio = ((original - converted) / original) * 100
    return ratio > 0 ? `-${ratio.toFixed(0)}%` : `+${Math.abs(ratio).toFixed(0)}%`
  }

  const estimateOutputSize = (durationSeconds: number): number => {
    // MP3 size ≈ (bitrate * duration) / 8
    return (settings.targetBitrate * 1000 * durationSeconds) / 8
  }

  const totalOriginalSize = files.reduce((sum, f) => sum + f.originalSize, 0)
  const totalConvertedSize = files.reduce((sum, f) => sum + (f.convertedSize || 0), 0)
  const completedCount = files.filter((f) => f.status === "complete").length

  return (
    <div className="min-h-screen bg-black p-6">
      <div className="max-w-6xl mx-auto space-y-6">
        <div>
          <h1 className="text-3xl font-bold text-white mb-2">Convertisseur Audio MP3</h1>
          <p className="text-zinc-400">Compressez vos fichiers audio en MP3 pour respecter la limite de 2MB</p>
        </div>

        <Alert className="bg-green-950/50 border-green-800">
          <Zap className="h-4 w-4 text-green-400" />
          <AlertTitle className="text-green-300">Compression MP3</AlertTitle>
          <AlertDescription className="text-green-200">
            Cet outil convertit vos fichiers en MP3 compressé. Un fichier de 20MB peut être réduit à moins de 2MB avec
            les paramètres agressifs (64 kbps, 22 kHz, Mono). Pour une meilleure qualité, utilisez 128 kbps.
          </AlertDescription>
        </Alert>

        <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
          {/* Settings Panel */}
          <Card className="bg-zinc-900 border-zinc-800">
            <CardHeader>
              <CardTitle className="text-white flex items-center gap-2">
                <Settings2 className="w-5 h-5" />
                Paramètres de compression
              </CardTitle>
            </CardHeader>
            <CardContent className="space-y-6">
              <div className="space-y-2">
                <Label className="text-zinc-300">Bitrate (qualité vs taille)</Label>
                <Select
                  value={settings.targetBitrate.toString()}
                  onValueChange={(v) => setSettings((s) => ({ ...s, targetBitrate: Number.parseInt(v) }))}
                >
                  <SelectTrigger className="bg-zinc-800 border-zinc-700 text-white">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent className="bg-zinc-800 border-zinc-700">
                    <SelectItem value="32">32 kbps (Très petit, qualité faible)</SelectItem>
                    <SelectItem value="64">64 kbps (Petit, qualité acceptable)</SelectItem>
                    <SelectItem value="96">96 kbps (Équilibré)</SelectItem>
                    <SelectItem value="128">128 kbps (Bonne qualité)</SelectItem>
                    <SelectItem value="192">192 kbps (Haute qualité)</SelectItem>
                  </SelectContent>
                </Select>
              </div>

              <div className="space-y-2">
                <Label className="text-zinc-300">Taux d'échantillonnage</Label>
                <Select
                  value={settings.targetSampleRate.toString()}
                  onValueChange={(v) => setSettings((s) => ({ ...s, targetSampleRate: Number.parseInt(v) }))}
                >
                  <SelectTrigger className="bg-zinc-800 border-zinc-700 text-white">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent className="bg-zinc-800 border-zinc-700">
                    <SelectItem value="16000">16 kHz (Voix uniquement)</SelectItem>
                    <SelectItem value="22050">22.05 kHz (Économique)</SelectItem>
                    <SelectItem value="44100">44.1 kHz (CD Quality)</SelectItem>
                  </SelectContent>
                </Select>
              </div>

              <div className="space-y-2">
                <Label className="text-zinc-300">Canaux</Label>
                <Select
                  value={settings.channels.toString()}
                  onValueChange={(v) => setSettings((s) => ({ ...s, channels: Number.parseInt(v) as 1 | 2 }))}
                >
                  <SelectTrigger className="bg-zinc-800 border-zinc-700 text-white">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent className="bg-zinc-800 border-zinc-700">
                    <SelectItem value="1">Mono (plus petit)</SelectItem>
                    <SelectItem value="2">Stéréo</SelectItem>
                  </SelectContent>
                </Select>
              </div>

              <div className="p-3 bg-zinc-800/50 rounded-lg space-y-2">
                <p className="text-xs text-zinc-400">Estimation taille finale:</p>
                <p className="text-sm text-white">~{((settings.targetBitrate * 60) / 8 / 1024).toFixed(1)} MB/minute</p>
                <p className="text-xs text-zinc-500">
                  Une chanson de 4 min ≈ {((settings.targetBitrate * 240) / 8 / 1024).toFixed(1)} MB
                </p>
              </div>

              <div className="space-y-2">
                <Label className="text-zinc-300">Presets rapides</Label>
                <div className="grid grid-cols-2 gap-2">
                  <Button
                    variant="outline"
                    size="sm"
                    className="border-zinc-700 bg-zinc-800/50 text-xs"
                    onClick={() => setSettings({ targetBitrate: 64, targetSampleRate: 22050, channels: 1 })}
                  >
                    Ultra compact
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    className="border-zinc-700 bg-zinc-800/50 text-xs"
                    onClick={() => setSettings({ targetBitrate: 128, targetSampleRate: 44100, channels: 2 })}
                  >
                    Bonne qualité
                  </Button>
                </div>
              </div>
            </CardContent>
          </Card>

          {/* Upload Area */}
          <Card className="bg-zinc-900 border-zinc-800 lg:col-span-2">
            <CardHeader>
              <CardTitle className="text-white flex items-center gap-2">
                <Upload className="w-5 h-5" />
                Fichiers à compresser
              </CardTitle>
              <CardDescription className="text-zinc-400">
                Glissez-déposez ou sélectionnez des fichiers audio
              </CardDescription>
            </CardHeader>
            <CardContent>
              <div
                className="border-2 border-dashed border-zinc-700 rounded-lg p-8 text-center hover:border-zinc-500 transition-colors cursor-pointer"
                onClick={() => fileInputRef.current?.click()}
              >
                <FileAudio className="w-12 h-12 mx-auto text-zinc-500 mb-4" />
                <p className="text-zinc-400 mb-2">Cliquez ou glissez vos fichiers ici</p>
                <p className="text-xs text-zinc-500">MP3, WAV, FLAC, OGG, M4A, AAC</p>
                <input
                  ref={fileInputRef}
                  type="file"
                  multiple
                  accept="audio/*,.mp3,.wav,.flac,.ogg,.m4a,.aac"
                  onChange={handleFileSelect}
                  className="hidden"
                />
              </div>

              {files.length > 0 && (
                <div className="mt-4 flex gap-2">
                  <Button
                    onClick={processAllFiles}
                    disabled={isProcessing || files.every((f) => f.status !== "pending")}
                    className="flex-1"
                  >
                    {isProcessing ? (
                      <>
                        <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                        Compression...
                      </>
                    ) : (
                      <>
                        <Zap className="w-4 h-4 mr-2" />
                        Compresser tout ({files.filter((f) => f.status === "pending").length})
                      </>
                    )}
                  </Button>
                  <Button
                    variant="outline"
                    onClick={downloadAll}
                    disabled={completedCount === 0}
                    className="border-zinc-700 bg-transparent"
                  >
                    <Download className="w-4 h-4 mr-2" />
                    Tout télécharger
                  </Button>
                  <Button variant="destructive" onClick={clearAll} disabled={isProcessing}>
                    <Trash2 className="w-4 h-4" />
                  </Button>
                </div>
              )}
            </CardContent>
          </Card>
        </div>

        {/* File List */}
        {files.length > 0 && (
          <Card className="bg-zinc-900 border-zinc-800">
            <CardHeader>
              <div className="flex items-center justify-between">
                <CardTitle className="text-white flex items-center gap-2">
                  <Music className="w-5 h-5" />
                  Fichiers ({files.length})
                </CardTitle>
                <div className="flex gap-4 text-sm">
                  <span className="text-zinc-400">
                    Original: <span className="text-white">{formatSize(totalOriginalSize)}</span>
                  </span>
                  {totalConvertedSize > 0 && (
                    <>
                      <span className="text-zinc-400">
                        Compressé: <span className="text-green-400">{formatSize(totalConvertedSize)}</span>
                      </span>
                      <span className="text-green-400 font-medium">
                        {getCompressionRatio(totalOriginalSize, totalConvertedSize)}
                      </span>
                    </>
                  )}
                </div>
              </div>
            </CardHeader>
            <CardContent>
              <div className="space-y-3">
                {files.map((audioFile) => (
                  <div key={audioFile.id} className="flex items-center gap-4 p-3 bg-zinc-800/50 rounded-lg">
                    <div className="flex-shrink-0">
                      {audioFile.status === "complete" && <CheckCircle className="w-5 h-5 text-green-500" />}
                      {audioFile.status === "error" && <XCircle className="w-5 h-5 text-red-500" />}
                      {audioFile.status === "processing" && <Loader2 className="w-5 h-5 text-blue-500 animate-spin" />}
                      {audioFile.status === "pending" && <FileAudio className="w-5 h-5 text-zinc-500" />}
                    </div>

                    <div className="flex-1 min-w-0">
                      <p className="text-sm text-white truncate">{audioFile.name}</p>
                      <div className="flex items-center gap-2 text-xs text-zinc-400">
                        <span>{formatSize(audioFile.originalSize)}</span>
                        {audioFile.duration && (
                          <>
                            <span>•</span>
                            <span>{formatDuration(audioFile.duration)}</span>
                          </>
                        )}
                        {audioFile.convertedSize && (
                          <>
                            <span>→</span>
                            <span className="text-green-400">{formatSize(audioFile.convertedSize)}</span>
                            <span className="text-green-500 font-medium">
                              ({getCompressionRatio(audioFile.originalSize, audioFile.convertedSize)})
                            </span>
                          </>
                        )}
                      </div>
                      {audioFile.status === "processing" && (
                        <Progress value={audioFile.progress} className="h-1 mt-2" />
                      )}
                      {audioFile.error && <p className="text-xs text-red-400 mt-1">{audioFile.error}</p>}
                    </div>

                    <div className="flex items-center gap-2">
                      <Badge
                        variant={
                          audioFile.status === "complete"
                            ? "default"
                            : audioFile.status === "error"
                              ? "destructive"
                              : audioFile.status === "processing"
                                ? "secondary"
                                : "outline"
                        }
                        className="text-xs"
                      >
                        {audioFile.status === "complete" && "Terminé"}
                        {audioFile.status === "error" && "Erreur"}
                        {audioFile.status === "processing" && "En cours"}
                        {audioFile.status === "pending" && "En attente"}
                      </Badge>

                      {audioFile.status === "complete" && (
                        <Button size="sm" variant="ghost" onClick={() => downloadFile(audioFile)}>
                          <Download className="w-4 h-4" />
                        </Button>
                      )}

                      <Button
                        size="sm"
                        variant="ghost"
                        onClick={() => removeFile(audioFile.id)}
                        disabled={isProcessing && audioFile.status === "processing"}
                      >
                        <Trash2 className="w-4 h-4" />
                      </Button>
                    </div>
                  </div>
                ))}
              </div>
            </CardContent>
          </Card>
        )}
      </div>
    </div>
  )
}
