<script>
  import {
    Play,
    Download,
    Loader2,
    AlertCircle,
    ChevronDown,
    Copy,
    Share,
    MoreHorizontal,
    Shuffle,
    Pause,
    X,
    Code,
    Layout,
  } from 'lucide-svelte';
  import { onMount } from 'svelte';
  import Prism from 'prismjs';
  import 'prismjs/components/prism-python';
  import 'prismjs/components/prism-bash';

  let text = `In a hole in the ground, there lived a hobbit. Not a nasty, dirty, wet hole, filled with the ends of worms and an oozy smell, nor yet a dry, bare, sandy hole with nothing in it to sit down on or to eat: it was a hobbit-hole, and that means comfort.`;
  let selectedVoice = 'Andrew';
  let selectedModel = 'Chatterbox';
  let modelDropdownOpen = false;
  let voiceDropdownOpen = false;
  let isGenerating = false;
  let audioUrl = null;
  let generationTime = 0;
  let exaggeration = 0.25;
  let temperature = 0.7;
  let isPlaying = false;
  let currentTime = 0;
  let duration = 0;
  let audioTitle = '';
  let audioElement = null;
  let sampleAudioElement = null;
  let playingSampleVoice = null;
  let showErrorModal = false;
  let errorMessage = '';
  let errorDetails = '';
  let historyCount = 0;
  let userVoices = [];
  let isLoadingVoices = false;
  let showLoginPrompt = false;
  let copyNotification = null;
  let mode = 'api';
  let settingsExpanded = false;

  // Live code variables
  let setupCode = '';
  let pythonCode = '';
  let codeUpdateCounter = 0;

  const famousBookOpeners = [
    'It was the best of times, it was the worst of times. It was the age of wisdom, it was the age of foolishness.',
    'It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.',
    'All happy families are alike; each unhappy family is unhappy in its own way.',
    'In a hole in the ground, there lived a hobbit. Not a nasty, dirty, wet hole, filled with the ends of worms and an oozy smell, nor yet a dry, bare, sandy hole with nothing in it to sit down on or to eat: it was a hobbit-hole, and that means comfort.',
  ];
  let currentBookIndex = 0;

  const models = [
    { id: 'chatterbox', name: 'Chatterbox', badge: 'recommended' },
    { id: 'kokoro', name: 'Kokoro', badge: 'coming soon', disabled: true },
  ];

  const voices = [
    {
      id: 'andrew',
      name: 'Andrew',
      description: 'Older British man who speaks clearly and warmly.',
      sample: '/voices/andrew.mp3',
      preview_url:
        'https://huggingface.co/spaces/abidlabs/hfstudio/resolve/main/frontend/static/voices/andrew.mp3',
    },
    {
      id: 'lily',
      name: 'Lily',
      description: 'Friendly, conversational tone of a woman in her 30s',
      sample: '/voices/lily.mp3',
      preview_url:
        'https://huggingface.co/spaces/abidlabs/hfstudio/resolve/main/frontend/static/voices/lily.mp3',
    },
    {
      id: 'pirate',
      name: 'Pirate',
      description: 'Young male pirate-y voice that speaks gruffly and with excitement',
      sample: '/voices/pirate.mp3',
      preview_url:
        'https://huggingface.co/spaces/abidlabs/hfstudio/resolve/main/frontend/static/voices/pirate.mp3',
    },
    {
      id: 'fairy',
      name: 'Fairy',
      description: 'High and airy female voice that bursts with excitement',
      sample: '/voices/fairy.mp3',
      preview_url:
        'https://huggingface.co/spaces/abidlabs/hfstudio/resolve/main/frontend/static/voices/fairy.mp3',
    },
  ];

  async function generateSpeech() {
    if (!text.trim()) return;

    const response = await fetch('/api/auth/user', { credentials: 'include' });
    if (!response.ok) {
      showLoginPrompt = true;
      return;
    }

    isGenerating = true;
    audioUrl = null;
    currentTime = 0;
    isPlaying = false;
    audioTitle = text.length > 30 ? text.substring(0, 30) + '...' : text;

    try {
      // Check if this is a cloned voice and get the voice URL
      let voiceUrl = null;
      if (selectedVoice === 'Yours' && userVoices.length > 0) {
        const userVoice = userVoices[0]; // Use the first (latest) user voice
        if (userVoice && userVoice.voice_url) {
          voiceUrl = window.location.origin + userVoice.voice_url;
        }
      }

      const requestBody = {
        text: text,
        voice_id: selectedVoice.toLowerCase(),
        model_id: selectedModel.toLowerCase(),
        mode: 'api',
        parameters: {
          exaggeration: exaggeration,
          temperature: temperature,
          ...(voiceUrl && { voice_url: voiceUrl }), // Include voice URL if it's a cloned voice
        },
      };

      const response = await fetch('/api/tts/generate', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        credentials: 'include',
        body: JSON.stringify(requestBody),
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`HTTP error! status: ${response.status}, body: ${errorText}`);
      }

      const result = await response.json();

      if (result.success && result.audio_url) {
        audioUrl = result.audio_url;
        generationTime = result.generation_time || 0;

        // Save to code recorder history
        await saveToHistory(requestBody, result);

        setTimeout(() => {
          if (audioElement) {
            audioElement.play().catch(() => {
              // Ignore autoplay failures
            });
          }
        }, 100);
      } else {
        const errorMessage = result.error || 'Unknown error occurred';
        showError('Generation Failed', errorMessage);
        audioUrl = null;
      }
    } catch (error) {
      showError(
        'Network Error',
        'Failed to connect to the server. Please check your connection and try again.'
      );
      audioUrl = null;
    } finally {
      isGenerating = false;
    }
  }

  function togglePlayPause() {
    if (audioElement) {
      if (isPlaying) {
        audioElement.pause();
      } else {
        audioElement.play();
      }
    }
  }

  function handleAudioLoad() {
    if (audioElement) {
      duration = audioElement.duration;
    }
  }

  function handleTimeUpdate() {
    if (audioElement) {
      currentTime = audioElement.currentTime;
    }
  }

  function handlePlay() {
    isPlaying = true;
  }

  function handlePause() {
    isPlaying = false;
  }

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

  function downloadAudio() {
    if (audioUrl) {
      const a = document.createElement('a');
      a.href = audioUrl;
      a.download = 'speech.wav';
      a.click();
    }
  }

  function shareAudio() {}

  function playSampleVoice(voice, event) {
    event.stopPropagation();

    if (playingSampleVoice === voice.name) {
      if (sampleAudioElement) {
        sampleAudioElement.pause();
        sampleAudioElement.currentTime = 0;
      }
      playingSampleVoice = null;
    } else {
      if (sampleAudioElement) {
        sampleAudioElement.pause();
      }
      playingSampleVoice = voice.name;

      const sampleUrl = voice.sample || '/samples/harvard.wav';

      if (!sampleAudioElement) {
        sampleAudioElement = new Audio(sampleUrl);
        sampleAudioElement.addEventListener('ended', () => {
          playingSampleVoice = null;
        });
      } else {
        sampleAudioElement.src = sampleUrl;
      }

      sampleAudioElement.play().catch((err) => {
        playingSampleVoice = null;
      });
    }
  }

  function handleKeyDown(event) {
    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault();
      generateSpeech();
    }
    if (event.key === 'Escape') {
      modelDropdownOpen = false;
      voiceDropdownOpen = false;
    }
  }

  function handleClickOutside(event) {
    if (!event.target.closest('.model-dropdown')) {
      modelDropdownOpen = false;
    }
    if (!event.target.closest('.voice-dropdown')) {
      voiceDropdownOpen = false;
    }
  }

  function showError(message, details = '') {
    errorMessage = message;
    errorDetails = details;
    showErrorModal = true;
  }

  function closeErrorModal() {
    showErrorModal = false;
    errorMessage = '';
    errorDetails = '';
  }

  function refreshText() {
    currentBookIndex = (currentBookIndex + 1) % famousBookOpeners.length;
    text = famousBookOpeners[currentBookIndex];
  }

  async function saveToHistory(requestBody, result) {
    try {
      // Get the actual voice URL
      let voiceUrl = null;

      // Check if this is a user voice (cloned voice)
      const userVoice = userVoices.find((v) => v.voice_name === selectedVoice);
      if (userVoice && userVoice.voice_url) {
        voiceUrl = window.location.origin + userVoice.voice_url;
      } else {
        // Check built-in voices
        const builtInVoice = voices.find((v) => v.name === selectedVoice);
        if (builtInVoice && builtInVoice.preview_url) {
          voiceUrl = builtInVoice.preview_url;
        }
      }

      const pythonCode = `audio_bytes = client.text_to_speech(
    "${requestBody.text.replace(/"/g, '\\"')}",
    extra_body={
        "exaggeration": ${requestBody.parameters.exaggeration},
        "temperature": ${requestBody.parameters.temperature}${
          voiceUrl
            ? `,
        "audio_url": "${voiceUrl}"`
            : ''
        }
    }
)`;

      await fetch('/api/history/save', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({
          code: pythonCode,
          result_type: 'audio',
          result_data: {
            url: result.audio_url,
            title: audioTitle,
            type: 'audio',
          },
          entry_type: 'generation',
        }),
      });

      // Update history count
      await loadHistoryCount();
    } catch (error) {
      console.error('Error saving to history:', error);
    }
  }

  async function loadHistoryCount() {
    try {
      const response = await fetch('/api/history/load', {
        method: 'GET',
        credentials: 'include',
      });

      if (response.ok) {
        const data = await response.json();
        const generationEntries = data.entries.filter((e) => e.entry_type === 'generation');
        historyCount = generationEntries.length;
      }
    } catch (error) {
      console.error('Error loading history count:', error);
      historyCount = 0;
    }
  }

  async function loadUserVoices() {
    try {
      isLoadingVoices = true;
      const response = await fetch('/api/voice/user-voices', {
        method: 'GET',
        credentials: 'include',
      });

      if (response.ok) {
        const data = await response.json();
        userVoices = data.voices || [];
      } else {
        userVoices = [];
      }
    } catch (error) {
      console.error('Error loading user voices:', error);
      userVoices = [];
    } finally {
      isLoadingVoices = false;
    }
  }

  function handleAuthAction() {
    // Get OAuth config and redirect to HuggingFace OAuth
    const clientId = '4831a493-1dbc-4dd4-9bb3-c3b41d2e96ba';
    const scopes = 'inference-api manage-repos';

    // Store current path to return to after auth
    const returnPath = window.location.pathname;

    // Determine the correct callback URL based on environment
    let redirectUri;
    if (window.location.hostname === 'localhost') {
      // Development: use backend port for callback
      redirectUri = 'http://localhost:7860/auth/callback';
    } else {
      // Production: use current origin
      redirectUri = `${window.location.origin}/auth/callback`;
    }

    const authUrl = `https://huggingface.co/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scopes)}&response_type=code&state=${encodeURIComponent(returnPath)}`;

    window.location.href = authUrl;
  }

  function generateSetupCode() {
    if (mode === 'local') {
      return `pip install huggingface-hub hfstudio uv
hfstudio start ${selectedModel.toLowerCase()} --port 7861`;
    } else {
      return `pip install huggingface-hub`;
    }
  }

  function generateClientInitCode() {
    if (mode === 'local') {
      const port = 7861;
      return `client = InferenceClient(base_url="http://localhost:${port}/api/v1")`;
    } else {
      const endpointModel =
        selectedModel.toLowerCase() === 'chatterbox'
          ? 'ResembleAI/chatterbox'
          : selectedModel.toLowerCase();
      return `client = InferenceClient(
    api_key="YOUR_HF_TOKEN",  # Get your token from https://huggingface.co/settings/tokens
    model="${endpointModel}",
)`;
    }
  }

  function generateImportCode() {
    const clientCode = generateClientInitCode();

    if (mode === 'local') {
      return `from huggingface_hub import InferenceClient

${clientCode}`;
    } else {
      return `from huggingface_hub import InferenceClient

${clientCode}`;
    }
  }

  function generatePythonCode() {
    // Get the actual voice URL
    let voiceUrl = null;

    // Check if this is a user voice (cloned voice)
    if (selectedVoice === 'Yours' && userVoices.length > 0) {
      const userVoice = userVoices[0]; // Use the first (latest) user voice
      if (userVoice && userVoice.voice_url) {
        voiceUrl = window.location.origin + userVoice.voice_url;
      }
    } else {
      // Check built-in voices
      const builtInVoice = voices.find((v) => v.name === selectedVoice);
      if (builtInVoice && builtInVoice.preview_url) {
        voiceUrl = builtInVoice.preview_url;
      }
    }

    const currentText = text || 'Hello, this is a sample text.';

    // Generate imports directly here to avoid function call issues
    const clientCode = generateClientInitCode();
    const imports = `from huggingface_hub import InferenceClient

${clientCode}`;

    return `${imports}

audio_bytes = client.text_to_speech(
    "${currentText.replace(/"/g, '\\"')}",
    extra_body={
        "exaggeration": ${exaggeration},
        "temperature": ${temperature}${
          voiceUrl
            ? `,
        "audio_url": "${voiceUrl}"`
            : ''
        }
    }
)`;
  }

  function copyToClipboard(textToCopy, message = 'Copied to clipboard!') {
    navigator.clipboard.writeText(textToCopy).then(() => {
      copyNotification = message;
      setTimeout(() => {
        copyNotification = null;
      }, 2000);
    });
  }

  function copyAllCode() {
    const parts = [];

    if (setupCode) {
      const isTerminalCommand =
        setupCode.includes('pip install') || setupCode.includes('hfstudio start');
      const language = isTerminalCommand ? 'bash' : '';
      parts.push(`## Setup (Run in Terminal)\n\n\`\`\`${language}\n${setupCode}\n\`\`\``);
    }

    if (pythonCode) {
      parts.push(`## Python Code\n\n\`\`\`python\n${pythonCode}\n\`\`\``);
    }

    const markdownContent = parts.join('\n\n');
    copyToClipboard(markdownContent, 'All code copied as Markdown!');
  }

  // Reactive statements for live code updates
  $: {
    // This block will re-run whenever any of these variables change
    (text, selectedVoice, selectedModel, exaggeration, temperature, userVoices, mode);
    setupCode = generateSetupCode();
    pythonCode = generatePythonCode();
    codeUpdateCounter++;
  }

  onMount(async () => {
    await loadHistoryCount();
    await loadUserVoices();
  });
</script>

<svelte:head>
  <title>Text to Speech - HFStudio</title>
</svelte:head>

<div
  class="flex flex-col h-full"
  on:click={handleClickOutside}
  on:keydown={handleKeyDown}
  role="main"
  tabindex="-1"
>
  <!-- Main content area -->
  <div class="flex-1 flex">
    <!-- Main content area -->
    <div class="flex-1 flex flex-col p-6">
      <!-- Text input area -->
      <div class="relative mb-4">
        <div class="absolute top-3 right-3 flex items-center gap-2 z-10">
          <span class="text-sm text-gray-400">
            {text.length.toLocaleString()} / 1,000 characters
          </span>
          <button
            on:click={refreshText}
            class="p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
            title="Refresh with famous book opening"
          >
            <Shuffle size={16} />
          </button>
        </div>
        <div class="relative">
          <textarea
            bind:value={text}
            maxlength="1000"
            class="w-full h-96 pt-10 px-6 pb-16 bg-white resize-none border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-amber-400 focus:border-transparent text-gray-900 text-lg leading-relaxed"
            placeholder="Type the text you'd like to convert to spoken audio here..."
            on:keydown={handleKeyDown}
            autofocus
          />
          <!-- Generate button embedded in textarea -->
          <button
            on:click={generateSpeech}
            disabled={isGenerating || !text.trim()}
            class="absolute bottom-4 right-4 px-5 py-2.5 bg-gradient-to-r from-amber-400 to-orange-500 text-white rounded-lg font-medium hover:from-amber-500 hover:to-orange-600 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-1.5 shadow-sm text-base"
          >
            {#if isGenerating}
              <Loader2 size={16} class="animate-spin" />
              Generating...
            {:else}
              <Play size={16} />
              Generate speech
            {/if}
          </button>
        </div>
      </div>

      <!-- Settings panel -->
      <div class="p-4 border border-gray-200 rounded-lg bg-white mb-6">
        <div class="grid grid-cols-1 lg:grid-cols-[1fr_1.4fr_1fr] gap-6">
          <!-- Model selector -->
          <div class="model-dropdown">
            <h3 class="text-sm font-medium text-gray-900 mb-2">Model</h3>
            <div class="relative">
              <button
                on:click={() => (modelDropdownOpen = !modelDropdownOpen)}
                class="w-full p-3 border bg-white text-sm focus:outline-none focus:ring-2 focus:ring-amber-400 focus:border-transparent shadow-sm text-left flex items-center justify-between {modelDropdownOpen
                  ? 'rounded-b-lg border-t-0 border-black'
                  : 'rounded-lg border-black'}"
              >
                <span>
                  {#each models as model}
                    {#if model.name === selectedModel}
                      {model.name}{#if model.badge}&nbsp;<span class="text-sm text-gray-500"
                          >({model.badge})</span
                        >{/if}
                    {/if}
                  {/each}
                </span>
                <ChevronDown
                  size={14}
                  class="text-gray-500 transition-transform {modelDropdownOpen ? 'rotate-180' : ''}"
                />
              </button>

              {#if modelDropdownOpen}
                <div
                  class="absolute bottom-full left-0 right-0 border border-gray-200 border-b-0 bg-white shadow-lg rounded-t-lg overflow-hidden z-20"
                >
                  {#each models as model}
                    <button
                      class="w-full px-3 py-2.5 text-left transition-colors text-sm {model.disabled
                        ? 'opacity-50 cursor-not-allowed'
                        : 'hover:bg-gray-50'} {model.name === selectedModel ? 'bg-gray-100' : ''}"
                      disabled={model.disabled}
                      on:click={() => {
                        if (!model.disabled) {
                          selectedModel = model.name;
                          modelDropdownOpen = false;
                        }
                      }}
                    >
                      {model.name}{#if model.badge}&nbsp;<span class="text-sm text-gray-500"
                          >({model.badge})</span
                        >{/if}
                    </button>
                  {/each}
                </div>
              {/if}
            </div>

            <!-- Pricing info -->
            <div class="mt-1.5 text-xs text-gray-500 text-right">
              $0.025 per 1000 chars • <a
                href="https://huggingface.co/settings/billing"
                target="_blank"
                class="text-amber-600 hover:text-amber-700 underline">Billing ⤴</a
              >
            </div>
          </div>

          <!-- Voice selector -->
          <div>
            <h3 class="text-sm font-medium text-gray-900 mb-2">Voice</h3>
            <div class="grid grid-cols-2 gap-2">
              <!-- Andrew -->
              <button
                class="p-3 border rounded-lg transition-colors text-left hover:bg-gray-50 {selectedVoice ===
                'Andrew'
                  ? 'border-black'
                  : 'border-gray-200'}"
                on:click={() => (selectedVoice = 'Andrew')}
              >
                <div class="flex items-center justify-between mb-1">
                  <div class="flex items-center gap-2">
                    <div
                      class="w-6 h-6 bg-gradient-to-br from-amber-400 to-orange-500 rounded-full flex items-center justify-center text-white text-xs font-semibold"
                    >
                      A
                    </div>
                    <span class="text-sm font-medium">Andrew</span>
                  </div>
                  <button
                    on:click={(e) =>
                      playSampleVoice({ name: 'Andrew', sample: '/voices/andrew.mp3' }, e)}
                    class="p-1 rounded-full hover:bg-gray-200 transition-colors w-5 h-5 flex items-center justify-center"
                    title="Play sample"
                  >
                    {#if playingSampleVoice === 'Andrew'}
                      <Pause size={10} class="text-gray-600" />
                    {:else}
                      <Play size={10} class="text-gray-600" />
                    {/if}
                  </button>
                </div>
              </button>

              <!-- Lily -->
              <button
                class="p-3 border rounded-lg transition-colors text-left hover:bg-gray-50 {selectedVoice ===
                'Lily'
                  ? 'border-black'
                  : 'border-gray-200'}"
                on:click={() => (selectedVoice = 'Lily')}
              >
                <div class="flex items-center justify-between mb-1">
                  <div class="flex items-center gap-2">
                    <div
                      class="w-6 h-6 bg-gradient-to-br from-amber-400 to-orange-500 rounded-full flex items-center justify-center text-white text-xs font-semibold"
                    >
                      L
                    </div>
                    <span class="text-sm font-medium">Lily</span>
                  </div>
                  <button
                    on:click={(e) =>
                      playSampleVoice({ name: 'Lily', sample: '/voices/lily.mp3' }, e)}
                    class="p-1 rounded-full hover:bg-gray-200 transition-colors w-5 h-5 flex items-center justify-center"
                    title="Play sample"
                  >
                    {#if playingSampleVoice === 'Lily'}
                      <Pause size={10} class="text-gray-600" />
                    {:else}
                      <Play size={10} class="text-gray-600" />
                    {/if}
                  </button>
                </div>
              </button>

              <!-- Pirate -->
              <button
                class="p-3 border rounded-lg transition-colors text-left hover:bg-gray-50 {selectedVoice ===
                'Pirate'
                  ? 'border-black'
                  : 'border-gray-200'}"
                on:click={() => (selectedVoice = 'Pirate')}
              >
                <div class="flex items-center justify-between mb-1">
                  <div class="flex items-center gap-2">
                    <div
                      class="w-6 h-6 bg-gradient-to-br from-amber-400 to-orange-500 rounded-full flex items-center justify-center text-white text-xs font-semibold"
                    >
                      P
                    </div>
                    <span class="text-sm font-medium">Pirate</span>
                  </div>
                  <button
                    on:click={(e) =>
                      playSampleVoice({ name: 'Pirate', sample: '/voices/pirate.mp3' }, e)}
                    class="p-1 rounded-full hover:bg-gray-200 transition-colors w-5 h-5 flex items-center justify-center"
                    title="Play sample"
                  >
                    {#if playingSampleVoice === 'Pirate'}
                      <Pause size={10} class="text-gray-600" />
                    {:else}
                      <Play size={10} class="text-gray-600" />
                    {/if}
                  </button>
                </div>
              </button>

              <!-- User Voice or Clone CTA -->
              {#if userVoices.length > 0}
                <button
                  class="p-3 border rounded-lg transition-colors text-left hover:bg-gray-50 {selectedVoice ===
                  'Yours'
                    ? 'border-purple-400 bg-purple-50'
                    : 'border-gray-200'}"
                  on:click={() => (selectedVoice = 'Yours')}
                >
                  <div class="flex items-center justify-between mb-1">
                    <div class="flex items-center gap-2">
                      <div
                        class="w-6 h-6 bg-gradient-to-br from-purple-400 to-pink-500 rounded-full flex items-center justify-center text-white text-xs"
                      >
                        🎤
                      </div>
                      <span class="text-xs font-medium">Your cloned voice</span>
                    </div>
                    <button
                      on:click={(e) =>
                        playSampleVoice({ name: 'Yours', sample: userVoices[0].voice_url }, e)}
                      class="p-1 rounded-full hover:bg-gray-200 transition-colors w-5 h-5 flex items-center justify-center"
                      title="Play sample"
                    >
                      {#if playingSampleVoice === 'Yours'}
                        <Pause size={10} class="text-gray-600" />
                      {:else}
                        <Play size={10} class="text-gray-600" />
                      {/if}
                    </button>
                  </div>
                </button>
              {:else}
                <!-- Clone CTA -->
                <a
                  href="/voice-cloning"
                  class="p-3 border border-purple-200 rounded-lg transition-colors text-left hover:bg-purple-50 bg-purple-25"
                >
                  <div class="flex items-center justify-between mb-1">
                    <div class="flex items-center gap-2">
                      <div
                        class="w-6 h-6 bg-gradient-to-br from-purple-400 to-pink-500 rounded-full flex items-center justify-center text-white text-xs font-semibold"
                      >
                        🎤
                      </div>
                      <span class="text-xs font-medium text-purple-900">Clone your voice</span>
                    </div>
                    <div class="w-5 h-5 flex items-center justify-center">
                      <svg
                        class="w-3 h-3 text-purple-600"
                        fill="none"
                        viewBox="0 0 24 24"
                        stroke="currentColor"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          stroke-width="2"
                          d="M9 5l7 7-7 7"
                        />
                      </svg>
                    </div>
                  </div>
                </a>
              {/if}
            </div>
          </div>

          <!-- Settings controls -->
          <div class="space-y-3">
            <!-- Exaggeration control -->
            <div>
              <div class="mb-1">
                <label for="exaggeration-slider" class="text-sm font-medium text-gray-900"
                  >Exaggeration</label
                >
              </div>
              <input
                id="exaggeration-slider"
                type="range"
                bind:value={exaggeration}
                min="0"
                max="1"
                step="0.01"
                class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer slider-hf"
              />
              <div class="flex justify-between text-xs text-gray-400 mt-1">
                <span>None</span>
                <span>More</span>
              </div>
            </div>

            <!-- Stability control -->
            <div>
              <div class="mb-1">
                <label for="temperature-slider" class="text-sm font-medium text-gray-900"
                  >Stability</label
                >
              </div>
              <input
                id="temperature-slider"
                type="range"
                bind:value={temperature}
                min="0"
                max="1"
                step="0.01"
                class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer slider-hf"
              />
              <div class="flex justify-between text-xs text-gray-400 mt-1">
                <span>More stable</span>
                <span>More variable</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Right sidebar - Live Code Display -->
    <div class="w-96 border-l border-gray-200 bg-white overflow-y-auto">
      <div class="p-4">
        <!-- Login prompt if not authenticated -->
        {#if showLoginPrompt}
          <div
            class="mb-4 px-3 py-2 bg-gradient-to-r from-amber-50 to-orange-50 rounded-lg border border-amber-200 relative"
          >
            <!-- Close button -->
            <button
              on:click={() => (showLoginPrompt = false)}
              class="absolute top-2 right-2 text-gray-400 hover:text-gray-600 transition-colors"
              aria-label="Dismiss"
            >
              <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M6 18L18 6M6 6l12 12"
                />
              </svg>
            </button>

            <p class="text-sm font-medium text-gray-700 mb-1 pr-4">
              Hugging Face <span
                class="bg-gradient-to-r from-purple-500 via-pink-500 via-green-500 to-blue-500 bg-clip-text text-transparent font-bold"
                >PRO</span
              >
            </p>
            <p class="text-sm text-gray-600 pr-4">
              Sign in to with your Hugging Face <a
                href="https://huggingface.co/pro"
                target="_blank"
                class="text-amber-600 hover:text-amber-700 underline font-medium">PRO account</a
              > to get started with $2 of free API credits per month. You can add a billing method for
              additional pay-as-you-go usage ⤴
            </p>
          </div>
        {/if}

        <!-- Header -->
        <div class="mb-4">
          <h3 class="text-lg font-semibold text-gray-900 mb-1">Results & Live Documentation</h3>
          <p class="text-sm text-gray-600">The code below will update as you adjust the UI ✨</p>
        </div>

        <!-- Toggle and Copy All button row -->
        <div class="flex items-center justify-between mb-4">
          <!-- API/Local Mode Toggle -->
          <div class="flex items-center bg-gray-100 rounded-md p-0.5">
            <button
              class="px-2 py-1 text-xs font-medium rounded transition-colors {mode === 'api'
                ? 'bg-white shadow-sm'
                : 'text-gray-600'}"
              on:click={() => (mode = 'api')}
            >
              API
            </button>
            <button
              class="px-2 py-1 text-xs font-medium rounded transition-colors {mode === 'local'
                ? 'bg-white shadow-sm'
                : 'text-gray-600'}"
              on:click={() => (mode = 'local')}
            >
              Local
            </button>
          </div>

          <button
            on:click={copyAllCode}
            class="flex items-center bg-gray-100 hover:bg-gray-200 rounded-md px-2 py-1 transition-colors"
          >
            <Copy size={12} class="text-gray-600" />
            <span class="ml-1 text-xs font-medium text-gray-600">Copy all as Markdown</span>
          </button>
        </div>

        <!-- Code sections -->
        <div class="space-y-4">
          <!-- Setup Section -->
          <div class="bg-white rounded-lg border border-gray-200 overflow-hidden">
            <div
              class="flex items-center justify-between px-3 py-2 bg-blue-50 border-b border-blue-200"
            >
              <div class="flex items-center gap-2">
                <span class="text-xs font-medium text-blue-900">Install in Terminal</span>
              </div>
              <button
                on:click={() => copyToClipboard(setupCode)}
                class="p-1 hover:bg-blue-100 rounded transition-colors"
                title="Copy setup code"
              >
                <Copy size={12} class="text-blue-600" />
              </button>
            </div>
            <div class="relative">
              {#key codeUpdateCounter}
                <pre class="p-3 overflow-x-auto bg-gray-50 text-xs"><code class="language-bash"
                    >{@html Prism.highlight(setupCode, Prism.languages.bash, 'bash')}</code
                  ></pre>
              {/key}
            </div>
          </div>

          <!-- Python Code Section (Imports + Generation) -->
          <div class="bg-white rounded-lg border border-gray-200 overflow-hidden">
            <div
              class="flex items-center justify-between px-3 py-2 bg-amber-50 border-b border-amber-200"
            >
              <div class="flex items-center gap-2">
                <span class="text-xs font-medium text-amber-900">Python Code</span>
                <span class="text-xs bg-amber-100 text-amber-700 px-1.5 py-0.5 rounded">Live</span>
              </div>
              <button
                on:click={() => copyToClipboard(pythonCode)}
                class="p-1 hover:bg-amber-100 rounded transition-colors"
                title="Copy Python code"
              >
                <Copy size={12} class="text-amber-600" />
              </button>
            </div>
            <div class="relative">
              {#key codeUpdateCounter}
                <pre class="p-3 overflow-x-auto bg-gray-50 text-xs"><code class="language-python"
                    >{@html Prism.highlight(pythonCode, Prism.languages.python, 'python')}</code
                  ></pre>
              {/key}
            </div>
          </div>

          <!-- Generated Audio Section -->
          {#if audioUrl}
            <div class="bg-white rounded-lg border border-gray-200 overflow-hidden mt-4">
              <div
                class="flex items-center justify-between px-3 py-2 bg-green-50 border-b border-green-200"
              >
                <div class="flex items-center gap-2">
                  <div class="w-1.5 h-1.5 bg-green-500 rounded-full"></div>
                  <span class="text-xs font-medium text-green-900">Generated Audio</span>
                  {#if generationTime > 0 && mode !== 'local'}
                    <span class="text-xs text-green-700">(took {generationTime.toFixed(1)}s)</span>
                  {/if}
                </div>
                <div class="flex items-center gap-1">
                  <button
                    on:click={downloadAudio}
                    class="flex items-center gap-1 px-2 py-1 hover:bg-green-100 rounded transition-colors"
                    title="Download audio"
                  >
                    <span class="text-xs text-green-700">Download</span>
                    <Download size={12} class="text-green-600" />
                  </button>
                </div>
              </div>
              <div class="p-3">
                <!-- Audio info -->
                <div class="mb-3">
                  <h4 class="font-medium text-gray-900 text-xs">{audioTitle}</h4>
                  <p class="text-xs text-gray-500">{selectedVoice} • {formatTime(duration)}</p>
                </div>

                <!-- Audio controls -->
                <div class="flex items-center gap-2">
                  <!-- Play/Pause button -->
                  <button
                    on:click={togglePlayPause}
                    class="w-6 h-6 bg-black rounded-full flex items-center justify-center hover:bg-gray-800 transition-colors flex-shrink-0"
                  >
                    {#if isPlaying}
                      <div class="pause-filled text-white text-xs"></div>
                    {:else}
                      <Play size={10} class="text-white ml-0.5" />
                    {/if}
                  </button>

                  <!-- Progress bar -->
                  <div class="flex-1 flex items-center gap-1">
                    <span class="text-xs text-gray-500 font-mono">{formatTime(currentTime)}</span>
                    <div class="flex-1 h-1 bg-gray-200 rounded-full cursor-pointer">
                      <div
                        class="h-full bg-gradient-to-r from-amber-400 to-orange-500 rounded-full transition-all"
                        style="width: {(currentTime / duration) * 100}%"
                      ></div>
                    </div>
                    <span class="text-xs text-gray-500 font-mono">{formatTime(duration)}</span>
                  </div>
                </div>

                <!-- Hidden audio element -->
                {#if audioUrl}
                  <audio
                    bind:this={audioElement}
                    src={audioUrl}
                    on:loadedmetadata={handleAudioLoad}
                    on:timeupdate={handleTimeUpdate}
                    on:play={handlePlay}
                    on:pause={handlePause}
                    style="display: none;"
                  />
                {/if}
              </div>
            </div>
          {/if}
        </div>
      </div>
    </div>
  </div>
</div>

<!-- Error Modal -->
{#if showErrorModal}
  <div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
    <div class="bg-white rounded-xl shadow-2xl max-w-2xl w-full max-h-[80vh] flex flex-col">
      <!-- Header -->
      <div
        class="flex items-center justify-between p-6 border-b border-gray-200 bg-red-50 flex-shrink-0"
      >
        <div class="flex items-center gap-3 min-w-0">
          <div
            class="w-10 h-10 bg-red-100 rounded-full flex items-center justify-center flex-shrink-0"
          >
            <AlertCircle size={20} class="text-red-600" />
          </div>
          <div class="min-w-0">
            <h3 class="text-lg font-semibold text-gray-900 truncate">{errorMessage}</h3>
            <p class="text-sm text-gray-600">An error occurred while processing your request</p>
          </div>
        </div>
        <button
          on:click={closeErrorModal}
          class="p-2 hover:bg-red-100 rounded-full transition-colors flex-shrink-0"
          title="Close"
        >
          <X size={20} class="text-gray-500" />
        </button>
      </div>

      <!-- Content -->
      <div class="p-6 overflow-y-auto flex-1 min-h-0">
        {#if errorDetails}
          <div class="bg-gray-50 rounded-lg p-4 border">
            <h4 class="text-sm font-medium text-gray-900 mb-2">Error Details:</h4>
            <pre
              class="text-xs text-gray-700 whitespace-pre-wrap font-mono leading-relaxed break-words">{#if errorDetails.includes('exceeded your monthly included credits')}{@html errorDetails.replace(
                  'Subscribe to PRO',
                  '<a href="https://huggingface.co/settings/billing" target="_blank" class="text-amber-600 hover:text-amber-700 underline font-medium">Subscribe to PRO</a>'
                )}{:else}{errorDetails}{/if}</pre>
          </div>
        {/if}
      </div>

      <!-- Footer -->
      <div
        class="flex items-center justify-end gap-3 p-6 border-t border-gray-200 bg-gray-50 flex-shrink-0"
      >
        <button
          on:click={closeErrorModal}
          class="px-6 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors"
        >
          Close
        </button>
      </div>
    </div>
  </div>
{/if}

<!-- Copy notification toast -->
{#if copyNotification}
  <div
    class="fixed bottom-4 right-4 px-4 py-2 bg-gray-900 text-white rounded-lg shadow-lg z-50 animate-fade-in"
  >
    {copyNotification}
  </div>
{/if}

<style>
  @keyframes fade-in {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  .animate-fade-in {
    animation: fade-in 0.3s ease-out;
  }
  .pause-filled::after {
    content: '';
    width: 3px;
    height: 12px;
    background: currentColor;
    display: inline-block;
    margin-right: 2px;
  }
  .pause-filled::before {
    content: '';
    width: 3px;
    height: 12px;
    background: currentColor;
    display: inline-block;
    margin-right: 2px;
  }
</style>
