import React, { useState, useRef, useMemo, useCallback, useEffect } from 'react'

// All 24 key+mode combinations
const ALL_KEYS_WITH_MODES = [
  'C major', 'C minor', 'C# major', 'C# minor',
  'D major', 'D minor', 'D# major', 'D# minor',
  'E major', 'E minor', 'F major', 'F minor',
  'F# major', 'F# minor', 'G major', 'G minor',
  'G# major', 'G# minor', 'A major', 'A minor',
  'A# major', 'A# minor', 'B major', 'B minor'
]

const KEY_NAMES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']

function formatTime(seconds) {
  if (!seconds || !isFinite(seconds)) return '0:00'
  const mins = Math.floor(seconds / 60)
  const secs = Math.floor(seconds % 60)
  return `${mins}:${secs.toString().padStart(2, '0')}`
}

function ContinuationPlayer({ sessionId }) {
  const audioRef = useRef(null)
  const rafRef = useRef(null)
  const [playing, setPlaying] = useState(false)
  const [cTime, setCTime] = useState(0)
  const [dur, setDur] = useState(0)

  // Stable URL — only changes when sessionId changes, not on every render
  const src = useMemo(
    () => `/api/stem/${sessionId}/_continuation?processed=false&t=${Date.now()}`,
    [sessionId]
  )

  // Try to read duration from the audio element (WAV streams may delay reporting it)
  const tryReadDuration = useCallback(() => {
    const audio = audioRef.current
    if (!audio) return
    const d = audio.duration
    if (d && isFinite(d) && d > 0) {
      setDur(d)
    }
  }, [])

  // Smooth animation loop — reads currentTime every frame while playing
  useEffect(() => {
    if (!playing) {
      if (rafRef.current) cancelAnimationFrame(rafRef.current)
      return
    }

    const tick = () => {
      if (audioRef.current) {
        setCTime(audioRef.current.currentTime)
        tryReadDuration()
      }
      rafRef.current = requestAnimationFrame(tick)
    }
    rafRef.current = requestAnimationFrame(tick)

    return () => {
      if (rafRef.current) cancelAnimationFrame(rafRef.current)
    }
  }, [playing, tryReadDuration])

  const toggle = () => {
    if (!audioRef.current) return
    if (playing) {
      audioRef.current.pause()
    } else {
      audioRef.current.play()
    }
  }

  const handleSeek = (e) => {
    const d = dur || audioRef.current?.duration
    if (!audioRef.current || !d || !isFinite(d)) return
    const rect = e.currentTarget.getBoundingClientRect()
    const pct = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))
    audioRef.current.currentTime = pct * d
    setCTime(audioRef.current.currentTime)
  }

  return (
    <div className="mt-3 bg-green-500/10 border border-green-500/30 rounded-lg p-3">
      <audio
        ref={audioRef}
        src={src}
        preload="auto"
        onLoadedMetadata={tryReadDuration}
        onDurationChange={tryReadDuration}
        onCanPlayThrough={tryReadDuration}
        onPlay={() => setPlaying(true)}
        onPause={() => setPlaying(false)}
        onEnded={() => { setPlaying(false); setCTime(0) }}
      />
      <div className="flex items-center gap-3">
        <button
          onClick={toggle}
          className="w-9 h-9 rounded-full bg-green-500 hover:bg-green-400 flex items-center justify-center transition-colors flex-shrink-0"
        >
          {playing ? (
            <svg className="w-4 h-4 fill-white" viewBox="0 0 24 24">
              <rect x="6" y="4" width="4" height="16" />
              <rect x="14" y="4" width="4" height="16" />
            </svg>
          ) : (
            <svg className="w-4 h-4 fill-white ml-0.5" viewBox="0 0 24 24">
              <polygon points="5,3 19,12 5,21" />
            </svg>
          )}
        </button>

        <div className="flex-1 flex items-center gap-2">
          <span className="text-xs text-gray-400 w-10 text-right font-mono">{formatTime(cTime)}</span>
          <div
            onClick={handleSeek}
            className="flex-1 h-2 bg-gray-700/50 rounded-full cursor-pointer relative"
          >
            <div
              className="h-full bg-green-500 rounded-full"
              style={{ width: dur > 0 ? `${(cTime / dur) * 100}%` : '0%' }}
            />
          </div>
          <span className="text-xs text-gray-400 w-10 font-mono">{formatTime(dur)}</span>
        </div>
      </div>
      <p className="text-xs text-green-400/70 mt-1.5">AI Continuation (seed + generated)</p>
    </div>
  )
}

function ControlPanel({ detection, onProcess, isProcessing, hasRegion, isGenerating, onGenerate, sessionId, continuationReady }) {
  const [targetKeyWithMode, setTargetKeyWithMode] = useState('C major')
  const [targetBpm, setTargetBpm] = useState(120)
  const [generationPrompt, setGenerationPrompt] = useState('')

  // Initialize targets from detection
  useEffect(() => {
    if (detection) {
      setTargetKeyWithMode(`${detection.key} ${detection.mode}`)
      setTargetBpm(detection.bpm)
    }
  }, [detection])

  const targetKey = targetKeyWithMode.split(' ')[0]

  const semitones = useMemo(() => {
    if (!detection || !targetKey) return 0
    const fromIdx = KEY_NAMES.indexOf(detection.key)
    const toIdx = KEY_NAMES.indexOf(targetKey)
    let diff = toIdx - fromIdx
    if (diff > 6) diff -= 12
    if (diff < -6) diff += 12
    return diff
  }, [detection, targetKey])

  const bpmPercent = useMemo(() => {
    if (!detection || !targetBpm) return 0
    return Math.round(((targetBpm - detection.bpm) / detection.bpm) * 100)
  }, [detection, targetBpm])

  // Quality indicators per spec
  const getKeyQualityBadge = (semitones) => {
    const abs = Math.abs(semitones)
    if (abs <= 4) return { color: 'bg-green-500', label: 'Recommended' }
    if (abs <= 7) return { color: 'bg-yellow-500', label: 'Some quality loss' }
    return { color: 'bg-red-500', label: 'Significant quality loss' }
  }

  const getBpmQualityBadge = (percent) => {
    const abs = Math.abs(percent)
    if (abs <= 20) return { color: 'bg-green-500', label: 'Recommended' }
    if (abs <= 40) return { color: 'bg-yellow-500', label: 'Some quality loss' }
    return { color: 'bg-red-500', label: 'Significant quality loss' }
  }

  const handleKeyShift = useCallback((shift) => {
    const currentIdx = KEY_NAMES.indexOf(targetKey)
    const newIdx = (currentIdx + shift + 12) % 12
    const mode = targetKeyWithMode.split(' ')[1]
    setTargetKeyWithMode(`${KEY_NAMES[newIdx]} ${mode}`)
  }, [targetKey, targetKeyWithMode])

  const handleApply = useCallback(() => {
    if (!detection) return
    const newBpm = Math.abs(targetBpm - detection.bpm) > 0.1 ? targetBpm : null
    onProcess(semitones, newBpm)
  }, [onProcess, semitones, targetBpm, detection])

  const hasChanges = detection && (semitones !== 0 || Math.abs(targetBpm - detection.bpm) > 0.1)

  if (!detection) {
    return (
      <div className="glass rounded-xl p-6">
        <h2 className="text-lg font-semibold mb-4 text-white">Controls</h2>
        <p className="text-gray-400">Waiting for analysis...</p>
      </div>
    )
  }

  const keyQuality = getKeyQualityBadge(semitones)
  const bpmQuality = getBpmQualityBadge(bpmPercent)

  const btnBase = 'w-10 h-10 rounded-lg font-bold text-lg transition-all bg-gray-700/60 hover:bg-gray-600/60 text-white border border-gray-600 flex items-center justify-center flex-shrink-0'
  const resetBtn = 'text-xs px-3 py-1 rounded bg-white/10 hover:bg-white/20 text-gray-300 transition-colors'

  return (
    <div className="glass rounded-xl p-6 animate-fade-in">
      <h2 className="text-lg font-semibold mb-5 text-white">Pitch & Tempo Controls</h2>

      <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
        {/* ── Key Control ── */}
        <div className="flex flex-col items-center gap-2">
          {/* Label + semitone delta */}
          <div className="flex items-center gap-2">
            <span className="text-white font-medium">Key</span>
            {semitones !== 0 && (
              <span className="text-gray-400 text-xs font-mono">
                {semitones > 0 ? '+' : ''}{semitones} st
              </span>
            )}
          </div>

          {/* − / dropdown / + */}
          <div className="flex items-center gap-2 w-full">
            <button onClick={() => handleKeyShift(-1)} className={btnBase}>−</button>
            <select
              value={targetKeyWithMode}
              onChange={(e) => setTargetKeyWithMode(e.target.value)}
              className="flex-1 bg-gray-800/80 border border-gray-600 rounded-lg px-3 py-2 text-white text-base text-center focus:outline-none focus:border-purple-500"
            >
              {ALL_KEYS_WITH_MODES.map(k => (
                <option key={k} value={k}>{k}</option>
              ))}
            </select>
            <button onClick={() => handleKeyShift(1)} className={btnBase}>+</button>
          </div>

          {/* Quality badge */}
          {semitones !== 0 && (
            <span
              className={`px-2 py-0.5 rounded text-xs font-medium text-white ${keyQuality.color}`}
              title="For best quality, stay within ±4 semitones of the original key"
            >
              {keyQuality.label}
            </span>
          )}

          {/* Original + Reset */}
          <p className="text-xs text-gray-500">Original: {detection.key} {detection.mode}</p>
          <button
            onClick={() => setTargetKeyWithMode(`${detection.key} ${detection.mode}`)}
            className={resetBtn}
          >
            Reset
          </button>
        </div>

        {/* ── BPM Control ── */}
        <div className="flex flex-col items-center gap-2">
          {/* Label + percent delta */}
          <div className="flex items-center gap-2">
            <span className="text-white font-medium">BPM</span>
            {bpmPercent !== 0 && (
              <span className="text-gray-400 text-xs font-mono">
                {bpmPercent > 0 ? '+' : ''}{bpmPercent}%
              </span>
            )}
          </div>

          {/* − / number input / + */}
          <div className="flex items-center gap-2 w-full">
            <button onClick={() => setTargetBpm(v => Math.max(20, v - 5))} className={btnBase}>−</button>
            <input
              type="number"
              value={Math.round(targetBpm)}
              onChange={(e) => setTargetBpm(parseFloat(e.target.value) || detection.bpm)}
              min={Math.round(detection.bpm * 0.5)}
              max={Math.round(detection.bpm * 2)}
              className="flex-1 bg-gray-800/80 border border-gray-600 rounded-lg px-3 py-2 text-white text-base text-center focus:outline-none focus:border-purple-500 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
            />
            <button onClick={() => setTargetBpm(v => v + 5)} className={btnBase}>+</button>
          </div>

          {/* Quality badge */}
          {bpmPercent !== 0 && (
            <span
              className={`px-2 py-0.5 rounded text-xs font-medium text-white ${bpmQuality.color}`}
              title="For best quality, stay within ±20% of the original BPM"
            >
              {bpmQuality.label}
            </span>
          )}

          {/* Original + Reset */}
          <p className="text-xs text-gray-500">Original: {detection.bpm.toFixed(1)} BPM</p>
          <button
            onClick={() => setTargetBpm(detection.bpm)}
            className={resetBtn}
          >
            Reset
          </button>
        </div>
      </div>

      {/* Apply Changes button */}
      <button
        onClick={handleApply}
        disabled={!hasChanges || isProcessing}
        className={`w-full mt-6 py-4 rounded-xl font-semibold text-lg transition-all ${
          !hasChanges || isProcessing
            ? 'bg-gray-700 text-gray-500 cursor-not-allowed'
            : 'bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-400 hover:to-purple-400 text-white shadow-lg hover:shadow-purple-500/25'
        }`}
      >
        {isProcessing ? 'Processing...' : hasChanges ? (hasRegion ? 'Apply to Selection' : 'Apply Changes') : 'No Changes'}
      </button>

      {/* AI Continuation — hidden
      <div className="mt-6 pt-6 border-t border-gray-700/50">
        <h3 className="text-sm font-semibold text-white mb-3">AI Continuation</h3>
        <input
          type="text"
          value={generationPrompt}
          onChange={(e) => setGenerationPrompt(e.target.value)}
          placeholder="Describe the continuation style (optional)..."
          disabled={isGenerating || isProcessing}
          className="w-full bg-gray-800/80 border border-gray-600 rounded-lg px-4 py-2 text-white text-sm focus:outline-none focus:border-green-500 backdrop-blur placeholder-gray-500 mb-3"
        />
        <button
          onClick={() => onGenerate(generationPrompt)}
          disabled={isGenerating || isProcessing}
          className={`w-full py-3 rounded-xl font-semibold text-sm transition-all ${
            isGenerating || isProcessing
              ? 'bg-gray-700 text-gray-500 cursor-not-allowed'
              : 'bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-400 hover:to-emerald-400 text-white shadow-lg hover:shadow-green-500/25'
          }`}
        >
          {isGenerating ? 'Generating...' : 'Generate AI Continuation (15s)'}
        </button>

        {/* Dedicated continuation player * /}
        {continuationReady && sessionId && (
          <ContinuationPlayer sessionId={sessionId} />
        )}
      </div>
      */}
    </div>
  )
}

export default ControlPanel
