import { useEffect, useMemo, useRef, useState, type KeyboardEvent, type MouseEvent } from 'react'
import { Pause, Play, Volume2, VolumeX } from 'lucide-react'

const NAVY = '#032340'
const GOLD = '#CD9E53'

function createWaveform(seedValue: string | number, count = 72) {
  let seed = String(seedValue).split('').reduce((sum, char) => sum + char.charCodeAt(0), 17)
  return Array.from({ length: count }, (_, index) => {
    seed = (seed * 9301 + 49297) % 233280
    const random = seed / 233280
    const envelope = 0.48 + 0.27 * Math.sin(index * 0.31) + 0.15 * Math.sin(index * 0.83)
    return Math.max(0.18, Math.min(0.96, envelope + random * 0.3))
  })
}

function formatTime(seconds: number) {
  if (!Number.isFinite(seconds) || seconds < 0) return '0:00'
  const minutes = Math.floor(seconds / 60)
  return `${minutes}:${String(Math.floor(seconds % 60)).padStart(2, '0')}`
}

type MediaWavePlayerProps = {
  src: string
  episodeKey: string | number
  tone?: 'light' | 'dark'
  compact?: boolean
}

export default function MediaWavePlayer({ src, episodeKey, tone = 'dark', compact = false }: MediaWavePlayerProps) {
  const audioRef = useRef<HTMLAudioElement>(null)
  const [playing, setPlaying] = useState(false)
  const [muted, setMuted] = useState(false)
  const [current, setCurrent] = useState(0)
  const [duration, setDuration] = useState(0)
  const [failed, setFailed] = useState(false)
  const bars = useMemo(() => createWaveform(episodeKey), [episodeKey])
  const progress = duration > 0 ? Math.min(current / duration, 1) : 0
  const dark = tone === 'dark'
  const ink = dark ? '#fff' : NAVY
  const mutedInk = dark ? 'rgba(255,255,255,0.52)' : 'rgba(3,35,64,0.56)'
  const idleBar = dark ? 'rgba(255,255,255,0.18)' : 'rgba(3,35,64,0.16)'

  useEffect(() => {
    const audio = audioRef.current
    if (!audio) return
    audio.pause()
    audio.currentTime = 0
    audio.muted = false
    setPlaying(false)
    setMuted(false)
    setCurrent(0)
    setDuration(0)
    setFailed(false)
    audio.load()
  }, [src, episodeKey])

  const togglePlayback = async () => {
    const audio = audioRef.current
    if (!audio || failed) return
    if (!audio.paused) {
      audio.pause()
      return
    }
    try {
      await audio.play()
    } catch {
      setFailed(true)
    }
  }

  const seekToRatio = (ratio: number) => {
    const audio = audioRef.current
    if (!audio || !duration) return
    audio.currentTime = Math.max(0, Math.min(1, ratio)) * duration
    setCurrent(audio.currentTime)
  }

  const seekFromPointer = (event: MouseEvent<HTMLDivElement>) => {
    const rect = event.currentTarget.getBoundingClientRect()
    seekToRatio((event.clientX - rect.left) / rect.width)
  }

  const seekFromKeyboard = (event: KeyboardEvent<HTMLDivElement>) => {
    const audio = audioRef.current
    if (!audio || !duration || !['ArrowRight', 'ArrowLeft'].includes(event.key)) return
    event.preventDefault()
    const delta = event.key === 'ArrowRight' ? 5 : -5
    audio.currentTime = Math.max(0, Math.min(duration, audio.currentTime + delta))
    setCurrent(audio.currentTime)
  }

  const toggleMute = () => {
    const audio = audioRef.current
    if (!audio) return
    audio.muted = !audio.muted
    setMuted(audio.muted)
  }

  return (
    <div style={{
      width: '100%', minWidth: 0, display: 'flex', gap: compact ? 12 : 10,
      flexDirection: compact ? 'row-reverse' : 'column',
      alignItems: compact ? 'center' : undefined,
      direction: compact ? 'ltr' : undefined,
    }}>
      <audio
        ref={audioRef}
        src={src}
        preload="metadata"
        onLoadedMetadata={(event) => setDuration(Number.isFinite(event.currentTarget.duration) ? event.currentTarget.duration : 0)}
        onDurationChange={(event) => setDuration(Number.isFinite(event.currentTarget.duration) ? event.currentTarget.duration : 0)}
        onTimeUpdate={(event) => setCurrent(event.currentTarget.currentTime)}
        onPlay={() => setPlaying(true)}
        onPause={() => setPlaying(false)}
        onEnded={() => { setPlaying(false); setCurrent(0) }}
        onError={() => setFailed(true)}
        style={{ display: 'none' }}
      />

      <div
        role="slider"
        aria-label="موقعیت پخش پادکست"
        aria-valuemin={0}
        aria-valuemax={Math.max(0, Math.round(duration))}
        aria-valuenow={Math.round(current)}
        tabIndex={0}
        onClick={seekFromPointer}
        onKeyDown={seekFromKeyboard}
        style={{
          height: compact ? 58 : 48,
          flex: compact ? 1 : undefined,
          minWidth: 0,
          display: 'flex',
          alignItems: 'center',
          gap: 2,
          direction: 'ltr',
          cursor: duration ? 'pointer' : 'default',
          overflow: 'hidden',
          outline: 'none',
        }}
      >
        {bars.map((height, index) => {
          const played = (index + 0.5) / bars.length <= progress
          return (
            <span key={index} style={{
              flex: '1 1 0',
              minWidth: 1,
              maxWidth: compact ? 'none' : 6,
              height: `${Math.round(height * (compact ? 52 : 42))}px`,
              borderRadius: 999,
              background: played ? GOLD : idleBar,
              transition: 'background-color 140ms ease',
            }} />
          )
        })}
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 10, direction: 'ltr', flexShrink: 0 }}>
        <button
          type="button"
          onClick={togglePlayback}
          disabled={failed}
          aria-label={playing ? 'توقف پادکست' : 'پخش پادکست'}
          style={{
            width: 42,
            height: 42,
            borderRadius: '50%',
            border: 0,
            flexShrink: 0,
            display: 'inline-flex',
            alignItems: 'center',
            justifyContent: 'center',
            background: failed ? idleBar : GOLD,
            color: dark ? NAVY : '#fff',
            cursor: failed ? 'not-allowed' : 'pointer',
          }}
        >
          {playing
            ? <Pause size={17} fill="currentColor" />
            : <Play size={17} fill="currentColor" style={{ marginLeft: 2 }} />}
        </button>

        {!compact && (
          <>
            <span style={{ minWidth: 36, color: ink, fontSize: 11, fontWeight: 800 }}>{formatTime(current)}</span>
            <div style={{ flex: 1, height: 3, borderRadius: 999, background: idleBar, overflow: 'hidden' }}>
              <div style={{ width: `${progress * 100}%`, height: '100%', background: GOLD, transition: 'width 120ms linear' }} />
            </div>
            <span style={{ minWidth: 36, textAlign: 'right', color: mutedInk, fontSize: 11, fontWeight: 700 }}>{formatTime(duration)}</span>
            <button
              type="button"
              onClick={toggleMute}
              aria-label={muted ? 'فعال کردن صدا' : 'قطع صدا'}
              style={{ border: 0, background: 'transparent', padding: 5, color: mutedInk, cursor: 'pointer', display: 'flex' }}
            >
              {muted ? <VolumeX size={17} /> : <Volume2 size={17} />}
            </button>
          </>
        )}
      </div>

      {failed && (
        <div style={{ color: dark ? '#fca5a5' : '#b42318', fontSize: 11, textAlign: 'right' }}>
          فایل صوتی قابل پخش نیست. آدرس فایل یا فرمت آن را بررسی کنید.
        </div>
      )}
    </div>
  )
}
