import { useState, useRef, useCallback, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { Upload as UploadIcon, Music, X, Image, Mic, Link2, Loader2, Circle, Square, MicOff, ShieldAlert } from 'lucide-react'
import { supabase } from '@/lib/supabase'
import { useAuthStore } from '@/stores/auth'
import { Button } from '@/components/ui/Button'
import { Input } from '@/components/ui/Input'

type Mode = 'choose' | 'original' | 'external'

interface OEmbedData {
  title: string
  description: string
  thumbnail: string
  duration: number
  audioUrl: string
  platform: string
  author: string
  authorAvatar: string
}

const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001'

async function fetchVideoMeta(url: string): Promise<OEmbedData | null> {
  try {
    const res = await fetch(`${API_URL}/api/metadata?url=${encodeURIComponent(url)}`)
    if (!res.ok) return null
    return await res.json()
  } catch {
    return null
  }
}

export function Upload() {
  const { user } = useAuthStore()
  const navigate = useNavigate()
  const [mode, setMode] = useState<Mode>('choose')

  // Shared fields
  const [title, setTitle] = useState('')
  const [description, setDescription] = useState('')
  const [coverPreview, setCoverPreview] = useState<string | null>(null)
  const [coverFile, setCoverFile] = useState<File | null>(null)
  const [uploading, setUploading] = useState(false)
  const [error, setError] = useState('')

  // Original mode
  const [audioFile, setAudioFile] = useState<File | null>(null)
  const [duration, setDuration] = useState(0)
  const [dragActive, setDragActive] = useState(false)
  const audioInputRef = useRef<HTMLInputElement>(null)

  // Recording mode
  const [isRecording, setIsRecording] = useState(false)
  const [recordingTime, setRecordingTime] = useState(0)
  const [micPermission, setMicPermission] = useState<'granted' | 'denied' | 'prompt' | 'checking'>('checking')
  const mediaRecorderRef = useRef<MediaRecorder | null>(null)
  const chunksRef = useRef<Blob[]>([])
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null)

  // External mode
  const [externalUrl, setExternalUrl] = useState('')
  const [fetching, setFetching] = useState(false)
  const [platform, setPlatform] = useState('')
  const [author, setAuthor] = useState('')
  const [authorAvatar, setAuthorAvatar] = useState('')

  // Check microphone permission when entering original mode
  useEffect(() => {
    if (mode !== 'original') return
    let permStatus: PermissionStatus | null = null
    async function checkMicPermission() {
      try {
        permStatus = await navigator.permissions.query({ name: 'microphone' as PermissionName })
        setMicPermission(permStatus.state as 'granted' | 'denied' | 'prompt')
        permStatus.onchange = () => setMicPermission(permStatus!.state as 'granted' | 'denied' | 'prompt')
      } catch {
        // Permissions API not supported or blocked by Permissions Policy — assume prompt
        setMicPermission('prompt')
      }
    }
    checkMicPermission()
    return () => { if (permStatus) permStatus.onchange = null }
  }, [mode])

  // Cleanup recording on unmount
  useEffect(() => {
    return () => {
      if (timerRef.current) clearInterval(timerRef.current)
      if (mediaRecorderRef.current?.state === 'recording') {
        mediaRecorderRef.current.stop()
        mediaRecorderRef.current.stream.getTracks().forEach(t => t.stop())
      }
    }
  }, [])

  async function startRecording() {
    setError('')
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
      setMicPermission('granted')
      const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' })
      mediaRecorderRef.current = mediaRecorder
      chunksRef.current = []

      mediaRecorder.ondataavailable = (e) => {
        if (e.data.size > 0) chunksRef.current.push(e.data)
      }

      mediaRecorder.onstop = () => {
        stream.getTracks().forEach(t => t.stop())
        if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null }

        const blob = new Blob(chunksRef.current, { type: 'audio/webm' })
        const file = new File([blob], `enregistrement-${Date.now()}.webm`, { type: 'audio/webm' })
        setAudioFile(file)
        setDuration(recordingTime)
        if (!title) setTitle('Mon enregistrement')
        setIsRecording(false)
      }

      mediaRecorder.start(1000)
      setIsRecording(true)
      setRecordingTime(0)
      timerRef.current = setInterval(() => setRecordingTime(t => t + 1), 1000)
    } catch (err) {
      const e = err as DOMException
      if (e.name === 'NotAllowedError') {
        setMicPermission('denied')
        setError('Acces au microphone refuse. Autorisez le microphone dans les parametres de votre navigateur puis rechargez la page.')
      } else if (e.name === 'NotFoundError') {
        setError('Aucun microphone detecte. Verifiez qu\'un micro est branche a votre appareil.')
      } else {
        setError('Impossible d\'acceder au microphone. Verifiez les permissions de votre navigateur.')
      }
    }
  }

  function stopRecording() {
    if (mediaRecorderRef.current?.state === 'recording') {
      mediaRecorderRef.current.stop()
    }
  }

  function formatRecordTime(s: number) {
    const m = Math.floor(s / 60)
    const sec = s % 60
    return `${m.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`
  }

  const handleAudioSelect = useCallback((file: File) => {
    if (!file.type.startsWith('audio/')) {
      setError('Veuillez selectionner un fichier audio.')
      return
    }
    setAudioFile(file)
    setError('')

    const audio = new Audio()
    audio.src = URL.createObjectURL(file)
    audio.addEventListener('loadedmetadata', () => {
      setDuration(Math.floor(audio.duration))
      URL.revokeObjectURL(audio.src)
    })

    if (!title) setTitle(file.name.replace(/\.[^.]+$/, '').replace(/[-_]/g, ' '))
  }, [title])

  function handleCoverSelect(file: File) {
    if (!file.type.startsWith('image/')) return
    setCoverFile(file)
    setCoverPreview(URL.createObjectURL(file))
  }

  // Auto-fetch metadata when URL changes (debounced)
  useEffect(() => {
    if (mode !== 'external') return
    const url = externalUrl.trim()
    if (!url) {
      setPlatform('')
      setCoverPreview(null)
      setTitle('')
      setDescription('')
      setDuration(0)
      setAuthor('')
      setAuthorAvatar('')
      return
    }

    // Basic URL validation before fetching
    if (!url.startsWith('http://') && !url.startsWith('https://')) return

    const timeout = setTimeout(async () => {
      setFetching(true)
      setError('')

      const meta = await fetchVideoMeta(url)
      if (!meta) {
        setError('URL non reconnue. Formats supportes : YouTube, Spotify, Dailymotion, SoundCloud.')
        setFetching(false)
        return
      }

      setTitle(meta.title || '')
      setDescription(meta.description || '')
      if (meta.thumbnail) setCoverPreview(meta.thumbnail)
      if (meta.duration) setDuration(meta.duration)
      if (meta.author) setAuthor(meta.author)
      if (meta.authorAvatar) setAuthorAvatar(meta.authorAvatar)
      setPlatform(meta.platform)
      setFetching(false)
    }, 600)

    return () => clearTimeout(timeout)
  }, [externalUrl, mode])

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!user) return
    setUploading(true)
    setError('')

    let audio_url = ''
    const timestamp = Date.now()

    if (mode === 'original') {
      if (!audioFile) return

      const audioPath = `${user.id}/${timestamp}-${audioFile.name}`
      const { error: audioErr } = await supabase.storage
        .from('podcasts')
        .upload(audioPath, audioFile)

      if (audioErr) {
        setError("Erreur lors de l'upload audio: " + audioErr.message)
        setUploading(false)
        return
      }

      const { data: audioUrlData } = supabase.storage.from('podcasts').getPublicUrl(audioPath)
      audio_url = audioUrlData.publicUrl
    } else {
      audio_url = externalUrl.trim()
    }

    let cover_url: string | null = coverPreview
    if (coverFile) {
      const coverPath = `${user.id}/${timestamp}-cover-${coverFile.name}`
      const { error: coverErr } = await supabase.storage
        .from('covers')
        .upload(coverPath, coverFile)
      if (!coverErr) {
        const { data } = supabase.storage.from('covers').getPublicUrl(coverPath)
        cover_url = data.publicUrl
      }
    }

    const { data: podcast, error: insertErr } = await supabase
      .from('podcasts')
      .insert({
        creator_id: user.id,
        title,
        description,
        audio_url,
        duration_seconds: duration,
        cover_url,
        ...(mode === 'external' && author ? { external_author: author, external_author_avatar: authorAvatar || null } : {}),
      })
      .select()
      .single()

    if (insertErr) {
      setError('Erreur: ' + insertErr.message)
      setUploading(false)
      return
    }

    navigate(`/podcast/${podcast.id}`)
  }

  if (!user) {
    return (
      <div className="text-center py-16">
        <p className="text-text-secondary mb-4">Connectez-vous pour publier un podcast.</p>
        <Button onClick={() => navigate('/auth')}>Se connecter</Button>
      </div>
    )
  }

  if (mode === 'choose') {
    return (
      <div className="max-w-2xl mx-auto">
        <h1 className="text-2xl font-heading font-bold mb-2">Publier un podcast</h1>
        <p className="text-text-secondary mb-8">Choisissez comment vous souhaitez partager votre contenu</p>

        <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
          {/* Original content card */}
          <button
            type="button"
            onClick={() => setMode('original')}
            className="group relative overflow-hidden rounded-2xl border-2 border-border hover:border-primary/40 bg-surface p-6 text-left transition-all duration-300 hover:shadow-[0_8px_30px_rgba(91,76,219,0.12)] cursor-pointer"
          >
            <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-bl from-primary/[0.08] to-transparent rounded-bl-full transition-all duration-300 group-hover:w-40 group-hover:h-40" />
            <div className="absolute bottom-0 left-0 w-20 h-20 bg-gradient-to-tr from-accent/[0.05] to-transparent rounded-tr-full" />

            <div className="relative z-10">
              <div className="w-14 h-14 rounded-2xl bg-gradient-to-br from-primary to-[#7B6AEF] flex items-center justify-center mb-4 shadow-[0_4px_20px_rgba(91,76,219,0.25)] transition-transform duration-300 group-hover:scale-110 group-hover:rotate-[-4deg]">
                <Mic size={24} className="text-white" />
              </div>
              <h3 className="font-heading font-bold text-lg mb-1.5">Contenu original</h3>
              <p className="text-sm text-text-secondary leading-relaxed">
                Uploadez votre propre fichier audio. Partagez votre voix, votre histoire, votre podcast.
              </p>
              <div className="flex gap-1.5 mt-4">
                <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-primary/10 text-primary">MP3</span>
                <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-primary/10 text-primary">WAV</span>
                <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-primary/10 text-primary">M4A</span>
              </div>
            </div>
          </button>

          {/* External content card */}
          <button
            type="button"
            onClick={() => setMode('external')}
            className="group relative overflow-hidden rounded-2xl border-2 border-border hover:border-mint/40 bg-surface p-6 text-left transition-all duration-300 hover:shadow-[0_8px_30px_rgba(76,199,178,0.12)] cursor-pointer"
          >
            <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-bl from-mint/[0.08] to-transparent rounded-bl-full transition-all duration-300 group-hover:w-40 group-hover:h-40" />
            <div className="absolute bottom-0 left-0 w-20 h-20 bg-gradient-to-tr from-sun/[0.05] to-transparent rounded-tr-full" />

            <div className="relative z-10">
              <div className="w-14 h-14 rounded-2xl bg-gradient-to-br from-mint to-[#3BB8A0] flex items-center justify-center mb-4 shadow-[0_4px_20px_rgba(76,199,178,0.25)] transition-transform duration-300 group-hover:scale-110 group-hover:rotate-[4deg]">
                <Link2 size={24} className="text-white" />
              </div>
              <h3 className="font-heading font-bold text-lg mb-1.5">Contenu existant</h3>
              <p className="text-sm text-text-secondary leading-relaxed">
                Partagez une video ou un podcast deja en ligne. On recupere tout automatiquement.
              </p>
              <div className="flex gap-1.5 mt-4">
                <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-mint/10 text-mint">YouTube</span>
                <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-mint/10 text-mint">Spotify</span>
                <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-mint/10 text-mint">Dailymotion</span>
                <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-mint/10 text-mint">SoundCloud</span>
              </div>
            </div>
          </button>
        </div>
      </div>
    )
  }

  return (
    <div className="max-w-2xl mx-auto">
      <div className="flex items-center gap-3 mb-6">
        <button
          type="button"
          onClick={() => {
            setMode('choose')
            setAudioFile(null)
            setExternalUrl('')
            setTitle('')
            setDescription('')
            setCoverPreview(null)
            setCoverFile(null)
            setDuration(0)
            setError('')
            setPlatform('')
            setAuthor('')
            setAuthorAvatar('')
          }}
          className="text-sm text-text-secondary hover:text-text transition-colors cursor-pointer"
        >
          ← Retour
        </button>
        <h1 className="text-2xl font-heading font-bold">
          {mode === 'original' ? 'Uploader un fichier audio' : 'Partager un contenu existant'}
        </h1>
      </div>

      <form onSubmit={handleSubmit} className="space-y-6">
        {mode === 'original' ? (
          /* ---- ORIGINAL: Audio file picker + Recorder ---- */
          isRecording ? (
            /* Recording in progress */
            <div className="border-2 border-accent/30 bg-accent/[0.03] rounded-2xl p-8 text-center">
              <div className="relative inline-flex items-center justify-center mb-4">
                <div className="absolute w-20 h-20 rounded-full bg-accent/20 animate-ping" />
                <div className="relative w-16 h-16 rounded-full bg-gradient-to-br from-accent to-[#D04B3A] flex items-center justify-center">
                  <Mic size={28} className="text-white" />
                </div>
              </div>
              <p className="text-2xl font-heading font-bold tabular-nums mb-1">{formatRecordTime(recordingTime)}</p>
              <p className="text-sm text-text-secondary mb-5">Enregistrement en cours...</p>
              <button
                type="button"
                onClick={stopRecording}
                className="inline-flex items-center gap-2 px-6 py-3 rounded-full bg-accent text-white font-semibold hover:bg-accent/90 transition-colors cursor-pointer shadow-[0_4px_20px_rgba(232,96,76,0.3)]"
              >
                <Square size={16} fill="white" />
                Arreter l'enregistrement
              </button>
            </div>
          ) : !audioFile ? (
            <div className="space-y-3">
              {/* Drag & drop zone */}
              <div
                className={`border-2 border-dashed rounded-2xl p-8 text-center transition-colors cursor-pointer ${dragActive ? 'border-primary bg-primary/5' : 'border-border hover:border-primary/30'}`}
                onClick={() => audioInputRef.current?.click()}
                onDragOver={(e) => { e.preventDefault(); setDragActive(true) }}
                onDragLeave={() => setDragActive(false)}
                onDrop={(e) => {
                  e.preventDefault()
                  setDragActive(false)
                  const file = e.dataTransfer.files[0]
                  if (file) handleAudioSelect(file)
                }}
              >
                <UploadIcon size={32} className="mx-auto text-text-secondary mb-2" />
                <p className="font-medium text-sm">Glissez votre fichier audio ici</p>
                <p className="text-xs text-text-secondary mt-1">ou cliquez pour selectionner (MP3, WAV, M4A)</p>
                <input
                  ref={audioInputRef}
                  type="file"
                  accept="audio/*"
                  className="hidden"
                  onChange={(e) => e.target.files?.[0] && handleAudioSelect(e.target.files[0])}
                />
              </div>

              <div className="flex items-center gap-3">
                <div className="flex-1 h-px bg-border" />
                <span className="text-xs text-text-secondary">ou</span>
                <div className="flex-1 h-px bg-border" />
              </div>

              {/* Record button */}
              {micPermission === 'denied' ? (
                <div className="w-full rounded-2xl border-2 border-accent/20 bg-accent/[0.03] p-5">
                  <div className="flex items-center gap-4">
                    <div className="w-12 h-12 rounded-2xl bg-gray-200 flex items-center justify-center shrink-0">
                      <MicOff size={20} className="text-text-secondary" />
                    </div>
                    <div>
                      <p className="font-heading font-bold text-text-secondary">Microphone bloque</p>
                      <p className="text-xs text-text-secondary mt-0.5">
                        Cliquez sur l'icone <ShieldAlert size={12} className="inline -mt-0.5" /> dans la barre d'adresse de votre navigateur pour autoriser l'acces au microphone, puis rechargez la page.
                      </p>
                    </div>
                  </div>
                </div>
              ) : (
                <button
                  type="button"
                  onClick={startRecording}
                  className="w-full group relative overflow-hidden rounded-2xl border-2 border-border hover:border-accent/30 bg-surface p-5 text-left transition-all duration-300 hover:shadow-[0_8px_30px_rgba(232,96,76,0.1)] cursor-pointer"
                >
                  <div className="absolute top-0 right-0 w-24 h-24 bg-gradient-to-bl from-accent/[0.06] to-transparent rounded-bl-full transition-all duration-300 group-hover:w-32 group-hover:h-32" />
                  <div className="relative z-10 flex items-center gap-4">
                    <div className="w-12 h-12 rounded-2xl bg-gradient-to-br from-accent to-[#D04B3A] flex items-center justify-center shadow-[0_4px_16px_rgba(232,96,76,0.25)] transition-transform duration-300 group-hover:scale-110">
                      <Circle size={20} className="text-white" fill="white" />
                    </div>
                    <div>
                      <p className="font-heading font-bold">Enregistrer directement</p>
                      <p className="text-xs text-text-secondary">
                        {micPermission === 'granted'
                          ? 'Votre micro est pret — cliquez pour commencer'
                          : 'Votre navigateur demandera l\'acces au microphone'}
                      </p>
                    </div>
                  </div>
                </button>
              )}
            </div>
          ) : (
            <div className="flex items-center gap-3 p-4 bg-primary/5 rounded-xl border border-primary/20">
              <Music size={20} className="text-primary shrink-0" />
              <div className="min-w-0 flex-1">
                <p className="text-sm font-medium truncate">{audioFile.name}</p>
                <p className="text-xs text-text-secondary">
                  {(audioFile.size / 1024 / 1024).toFixed(1)} Mo
                  {duration > 0 && ` — ${Math.floor(duration / 60)}min ${duration % 60}s`}
                </p>
              </div>
              <button type="button" onClick={() => { setAudioFile(null); setDuration(0) }} className="text-text-secondary hover:text-text cursor-pointer">
                <X size={18} />
              </button>
            </div>
          )
        ) : (
          /* ---- EXTERNAL: URL input ---- */
          <div className="space-y-3">
            <div className="relative">
              <Input
                id="url"
                label="URL de la video ou du podcast"
                value={externalUrl}
                onChange={(e) => setExternalUrl(e.target.value)}
                placeholder="https://youtube.com/watch?v=... ou https://open.spotify.com/episode/..."
              />
              {fetching && (
                <div className="absolute right-3 bottom-3">
                  <Loader2 size={18} className="animate-spin text-text-secondary" />
                </div>
              )}
            </div>

            {platform && coverPreview && (
              <div className="flex items-center gap-3 p-3 bg-mint/5 rounded-xl border border-mint/20">
                <img src={coverPreview} alt="" className="w-16 h-16 rounded-lg object-cover shrink-0" />
                <div className="min-w-0 flex-1">
                  <p className="text-sm font-medium truncate">{title || 'Sans titre'}</p>
                  <div className="flex items-center gap-2 mt-0.5 text-xs text-text-secondary">
                    {author && <span className="truncate">{author}</span>}
                    {author && duration > 0 && <span>·</span>}
                    {duration > 0 && <span className="shrink-0">{Math.floor(duration / 60)}:{(duration % 60).toString().padStart(2, '0')}</span>}
                  </div>
                  <div className="flex items-center gap-1.5 mt-1">
                    <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-mint/10 text-mint">
                      {platform}
                    </span>
                    <span className="text-[11px] font-medium px-2 py-0.5 rounded-full bg-primary/10 text-primary">
                      Auto-detecte
                    </span>
                  </div>
                </div>
              </div>
            )}
          </div>
        )}

        {/* Shared fields — hidden in external mode until metadata is fetched */}
        {(mode === 'original' || platform) && (
          <div className="grid grid-cols-1 sm:grid-cols-[1fr_auto] gap-6">
          <div className="space-y-4">
            <Input id="title" label="Titre" value={title} onChange={(e) => setTitle(e.target.value)} required placeholder="Le titre de votre podcast" />
            <div className="flex flex-col gap-1.5">
              <label htmlFor="desc" className="text-[13px] font-semibold text-text tracking-wide">Description</label>
              <textarea
                id="desc"
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder="De quoi parle votre podcast ?"
                rows={4}
                className="rounded-2xl border-2 border-border bg-surface-warm/50 px-4 py-3 text-sm text-text placeholder:text-text-secondary/40 outline-none resize-none transition-all duration-200 focus:border-primary focus:bg-surface focus:shadow-[0_0_0_4px_rgba(91,76,219,0.08)]"
              />
            </div>
          </div>

          <div className="flex flex-col items-center gap-2">
            <label className="text-[13px] font-semibold text-text tracking-wide">Couverture</label>
            <div
              className="w-32 h-32 rounded-xl border-2 border-dashed border-border hover:border-primary/30 flex items-center justify-center cursor-pointer overflow-hidden transition-colors"
              onClick={() => {
                const input = document.createElement('input')
                input.type = 'file'
                input.accept = 'image/*'
                input.onchange = () => input.files?.[0] && handleCoverSelect(input.files[0])
                input.click()
              }}
            >
              {coverPreview ? (
                <img src={coverPreview} alt="" className="w-full h-full object-cover" />
              ) : (
                <Image size={24} className="text-text-secondary" />
              )}
            </div>
            {coverPreview && mode === 'external' && !coverFile && (
              <p className="text-[11px] text-text-secondary">Auto-detectee</p>
            )}
          </div>
        </div>
        )}

        {error && <p className="text-sm text-accent">{error}</p>}

        {(mode === 'original' || platform) && (
          <Button
            type="submit"
            size="lg"
            className="w-full"
            disabled={
              (mode === 'original' ? !audioFile : !externalUrl.trim()) || !title || uploading
            }
          >
            {uploading ? 'Publication en cours...' : 'Publier le podcast'}
          </Button>
        )}
      </form>
    </div>
  )
}
