'use client';

import { useState, useEffect } from 'react';
import { toast } from 'react-hot-toast';
import { Volume2, Download, Sparkles, Play, Pause } from 'lucide-react';
import JobProgress from '@/components/JobProgress';
import { modulesApi, assetsApi } from '@/lib/api';
import { useStore } from '@/lib/store';

interface Voice {
  voice_id: string;
  name: string;
  preview_url?: string;
  category?: string;
  labels?: Record<string, string>;
}

export default function TextToSpeechPage() {
  const { addJob, updateJob } = useStore();
  const [text, setText] = useState('');
  const [voices, setVoices] = useState<Voice[]>([]);
  const [selectedVoice, setSelectedVoice] = useState<string>('');
  const [model, setModel] = useState('eleven_multilingual_v2');
  const [stability, setStability] = useState(0.5);
  const [similarityBoost, setSimilarityBoost] = useState(0.75);
  const [style, setStyle] = useState(0);
  const [speed, setSpeed] = useState(1.0);
  const [useSpeakerBoost, setUseSpeakerBoost] = useState(true);
  const [outputFormat, setOutputFormat] = useState('mp3_44100_128');
  const [jobId, setJobId] = useState<string | null>(null);
  const [generatedAudio, setGeneratedAudio] = useState<any>(null);
  const [loading, setLoading] = useState(false);
  const [loadingVoices, setLoadingVoices] = useState(true);
  const [previewPlaying, setPreviewPlaying] = useState<string | null>(null);
  const [previewAudio, setPreviewAudio] = useState<HTMLAudioElement | null>(null);
  const [showAllVoices, setShowAllVoices] = useState(false);

  useEffect(() => {
    const fetchVoices = async () => {
      try {
        const response = await modulesApi.getVoices();
        let allVoices = response.data;

        // Filter to show only saved voices if not showing all
        if (!showAllVoices) {
          const savedVoiceIds = JSON.parse(localStorage.getItem('savedVoices') || '[]');
          if (savedVoiceIds.length > 0) {
            allVoices = allVoices.filter((v: Voice) => savedVoiceIds.includes(v.voice_id));
          }
        }

        setVoices(allVoices);
        if (allVoices.length > 0 && !selectedVoice) {
          setSelectedVoice(allVoices[0].voice_id);
        }
      } catch (err) {
        toast.error('Failed to load voices');
      } finally {
        setLoadingVoices(false);
      }
    };

    fetchVoices();
  }, [showAllVoices]);

  const handleGenerate = async () => {
    if (!text.trim()) {
      toast.error('Please enter some text');
      return;
    }
    if (!selectedVoice) {
      toast.error('Please select a voice');
      return;
    }

    setLoading(true);
    setGeneratedAudio(null);

    try {
      const response = await modulesApi.textToSpeech({
        text,
        voice_id: selectedVoice,
        model_id: model,
        stability,
        similarity_boost: similarityBoost,
        style,
        speed,
        use_speaker_boost: useSpeakerBoost,
        output_format: outputFormat,
      });

      const job = response.data;
      setJobId(job.id);
      addJob({
        id: job.id,
        module: 'text_to_speech',
        status: job.status,
        progress: job.progress,
        created_at: job.created_at,
      });

      toast.success('Speech synthesis started!');
    } catch (err: any) {
      toast.error(err.response?.data?.detail || 'Failed to start synthesis');
      setLoading(false);
    }
  };

  const handleJobComplete = async (job: any) => {
    setLoading(false);
    updateJob(job.id, { status: 'completed', progress: 100 });

    if (job.output_asset_ids?.[0]) {
      const asset = await assetsApi.get(job.output_asset_ids[0]);
      setGeneratedAudio(asset.data);
      toast.success('Audio generated successfully!');
    }
  };

  const handleJobError = (error: string) => {
    setLoading(false);
    toast.error(error);
  };

  const handleDownload = async () => {
    if (!generatedAudio) return;
    try {
      const response = await assetsApi.download(generatedAudio.id);
      const url = window.URL.createObjectURL(response.data);
      const a = document.createElement('a');
      a.href = url;
      a.download = generatedAudio.original_filename;
      a.click();
      window.URL.revokeObjectURL(url);
    } catch (err) {
      toast.error('Failed to download audio');
    }
  };

  const playPreview = (previewUrl: string, voiceId: string) => {
    // Stop any currently playing audio
    if (previewAudio) {
      previewAudio.pause();
      previewAudio.currentTime = 0;
    }

    if (previewPlaying === voiceId) {
      setPreviewPlaying(null);
      setPreviewAudio(null);
      return;
    }

    const audio = new Audio(previewUrl);
    audio.onended = () => {
      setPreviewPlaying(null);
      setPreviewAudio(null);
    };
    setPreviewAudio(audio);
    setPreviewPlaying(voiceId);
    audio.play();
  };

  const selectedVoiceData = voices.find((v) => v.voice_id === selectedVoice);

  return (
    <div className="max-w-6xl mx-auto space-y-8">
      <div className="flex items-center gap-4">
        <div className="w-12 h-12 bg-forge-yellow/10 rounded-lg flex items-center justify-center">
          <Volume2 className="w-6 h-6 text-forge-yellow" />
        </div>
        <div>
          <h1 className="text-2xl font-bold text-white">Text to Speech</h1>
          <p className="text-gray-500">Convert text to natural speech with ElevenLabs</p>
        </div>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
        {/* Controls */}
        <div className="space-y-6">
          {/* Text Input */}
          <div>
            <label className="block text-sm font-medium text-gray-300 mb-2">
              Text to Speak
            </label>
            <textarea
              value={text}
              onChange={(e) => setText(e.target.value)}
              placeholder="Enter the text you want to convert to speech..."
              className="input-field min-h-[200px] resize-none"
              maxLength={5000}
            />
            <p className="mt-1 text-xs text-gray-500">{text.length}/5000 characters</p>
          </div>

          {/* Voice Selection */}
          <div>
            <div className="flex items-center justify-between mb-2">
              <label className="block text-sm font-medium text-gray-300">
                Voice
              </label>
              <button
                onClick={() => setShowAllVoices(!showAllVoices)}
                className="text-xs text-forge-yellow hover:text-yellow-400"
              >
                {showAllVoices ? 'Show Library Only' : 'Show All Voices'}
              </button>
            </div>
            {loadingVoices ? (
              <div className="text-gray-500">Loading voices...</div>
            ) : voices.length === 0 ? (
              <div className="bg-forge-dark border border-gray-700 rounded-lg p-4 text-center">
                <p className="text-gray-500 text-sm mb-2">
                  No voices in your library
                </p>
                <button
                  onClick={() => setShowAllVoices(true)}
                  className="text-xs text-forge-yellow hover:text-yellow-400"
                >
                  Show all voices
                </button>
              </div>
            ) : (
              <div className="space-y-2">
                <select
                  value={selectedVoice}
                  onChange={(e) => setSelectedVoice(e.target.value)}
                  className="select-field"
                >
                  {voices.map((voice) => (
                    <option key={voice.voice_id} value={voice.voice_id}>
                      {voice.name} {voice.category && `(${voice.category})`}
                    </option>
                  ))}
                </select>
                {selectedVoiceData?.preview_url && (
                  <button
                    onClick={() => playPreview(selectedVoiceData.preview_url!, selectedVoiceData.voice_id)}
                    className="flex items-center gap-2 text-sm text-forge-yellow hover:text-yellow-400"
                  >
                    {previewPlaying === selectedVoiceData.voice_id ? (
                      <Pause className="w-4 h-4" />
                    ) : (
                      <Play className="w-4 h-4" />
                    )}
                    Preview voice
                  </button>
                )}
              </div>
            )}
          </div>

          {/* Model */}
          <div>
            <label className="block text-sm font-medium text-gray-300 mb-2">
              Model
            </label>
            <select
              value={model}
              onChange={(e) => setModel(e.target.value)}
              className="select-field"
            >
              <option value="eleven_multilingual_v2">Multilingual V2 (Best quality)</option>
              <option value="eleven_flash_v2_5">Flash V2.5 (Ultra low latency)</option>
              <option value="eleven_turbo_v2_5">Turbo V2.5 (Fast, low latency)</option>
              <option value="eleven_v3">V3 (Latest, most natural)</option>
              <option value="eleven_turbo_v2">Turbo V2</option>
              <option value="eleven_multilingual_sts_v2">Multilingual STS V2</option>
              <option value="eleven_monolingual_v1">English V1 (Legacy)</option>
            </select>
          </div>

          {/* Output Format */}
          <div>
            <label className="block text-sm font-medium text-gray-300 mb-2">
              Output Format
            </label>
            <select
              value={outputFormat}
              onChange={(e) => setOutputFormat(e.target.value)}
              className="select-field"
            >
              <option value="mp3_44100_128">MP3 44.1kHz 128kbps (Recommended)</option>
              <option value="mp3_44100_192">MP3 44.1kHz 192kbps (High Quality)</option>
              <option value="mp3_44100_64">MP3 44.1kHz 64kbps (Small Size)</option>
              <option value="pcm_16000">PCM 16kHz (Uncompressed)</option>
              <option value="pcm_22050">PCM 22.05kHz (Uncompressed)</option>
              <option value="pcm_24000">PCM 24kHz (Uncompressed)</option>
              <option value="pcm_44100">PCM 44.1kHz (Uncompressed)</option>
              <option value="ulaw_8000">uLaw 8kHz (Telephony)</option>
            </select>
          </div>

          {/* Voice Settings */}
          <div className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">
                Stability: {stability.toFixed(2)}
              </label>
              <input
                type="range"
                min={0}
                max={1}
                step={0.05}
                value={stability}
                onChange={(e) => setStability(parseFloat(e.target.value))}
                className="w-full accent-forge-yellow"
              />
              <p className="text-xs text-gray-500 mt-1">Higher = more consistent, Lower = more expressive</p>
            </div>
            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">
                Clarity/Similarity: {similarityBoost.toFixed(2)}
              </label>
              <input
                type="range"
                min={0}
                max={1}
                step={0.05}
                value={similarityBoost}
                onChange={(e) => setSimilarityBoost(parseFloat(e.target.value))}
                className="w-full accent-forge-yellow"
              />
              <p className="text-xs text-gray-500 mt-1">Higher = closer to original voice</p>
            </div>
            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">
                Style/Exaggeration: {style.toFixed(2)}
              </label>
              <input
                type="range"
                min={0}
                max={1}
                step={0.05}
                value={style}
                onChange={(e) => setStyle(parseFloat(e.target.value))}
                className="w-full accent-forge-yellow"
              />
              <p className="text-xs text-gray-500 mt-1">Higher = more dramatic delivery</p>
            </div>
            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">
                Speed: {speed.toFixed(2)}x
              </label>
              <input
                type="range"
                min={0.25}
                max={4.0}
                step={0.05}
                value={speed}
                onChange={(e) => setSpeed(parseFloat(e.target.value))}
                className="w-full accent-forge-yellow"
              />
              <p className="text-xs text-gray-500 mt-1">Playback speed multiplier</p>
            </div>
            <div className="flex items-center gap-3">
              <input
                type="checkbox"
                id="speakerBoost"
                checked={useSpeakerBoost}
                onChange={(e) => setUseSpeakerBoost(e.target.checked)}
                className="w-4 h-4 rounded border-gray-600 bg-forge-dark text-forge-yellow focus:ring-forge-yellow"
              />
              <label htmlFor="speakerBoost" className="text-gray-300 text-sm">
                Speaker Boost (Enhances audio quality)
              </label>
            </div>
          </div>

          {/* Generate Button */}
          <button
            onClick={handleGenerate}
            disabled={loading || !text.trim() || !selectedVoice}
            className="btn-primary w-full flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            <Sparkles className="w-5 h-5" />
            {loading ? 'Generating...' : 'Generate Speech'}
          </button>

          {/* Job Progress */}
          {jobId && loading && (
            <JobProgress
              jobId={jobId}
              onComplete={handleJobComplete}
              onError={handleJobError}
            />
          )}
        </div>

        {/* Results */}
        <div>
          <h2 className="text-lg font-semibold text-white mb-4">Generated Audio</h2>
          {generatedAudio ? (
            <div className="bg-forge-dark rounded-xl overflow-hidden border border-gray-800">
              <div className="p-6">
                <audio
                  src={`/api/v1/assets/${generatedAudio.id}/download`}
                  controls
                  className="w-full"
                />
              </div>
              <div className="p-4 border-t border-gray-800">
                <div className="flex items-center justify-between">
                  <div>
                    <p className="text-white font-medium">{generatedAudio.original_filename}</p>
                    <p className="text-sm text-gray-500">
                      {(generatedAudio.file_size_bytes / 1024).toFixed(1)} KB
                    </p>
                  </div>
                  <button
                    onClick={handleDownload}
                    className="btn-primary flex items-center gap-2"
                  >
                    <Download className="w-4 h-4" />
                    Download
                  </button>
                </div>
              </div>
            </div>
          ) : (
            <div className="bg-forge-dark rounded-xl border border-gray-800 p-8 text-center">
              <Volume2 className="w-12 h-12 text-gray-600 mx-auto mb-3" />
              <p className="text-gray-500">Generated audio will appear here</p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
