<script>
  import {
    Play,
    Download,
    Loader2,
    AlertCircle,
    ChevronDown,
    Copy,
    RefreshCw,
    Share,
    MoreHorizontal,
    Settings,
    Sliders,
    Pause,
    SkipBack,
    SkipForward,
    Layout,
    Code,
    X,
    RotateCcw,
  } 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 = 'Lily';
  let selectedModel = 'Chatterbox';
  let mode = 'api';
  let viewMode = 'ui';
  let modelDropdownOpen = false;
  let isGenerating = false;
  let codeHistory = [];
  let setupCode = generateSetupCode(); // Always show setup code
  let importCode = null;
  let audioUrl = null;
  let copyNotification = null;
  let exaggeration = 0.25;
  let temperature = 0.7;
  let showSettings = true;
  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 currentUsername = null;

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

  const voices = [
    {
      id: 'lily',
      name: 'Lily',
      description: 'Warm, conversational voice from a female in her 30s',
      sample: '/voices/lily.mp3',
      preview_url:
        'https://huggingface.co/spaces/abidlabs/hfstudio/resolve/main/frontend/static/voices/lily.mp3',
    },
    {
      id: 'andrew',
      name: 'Andrew',
      description: 'Older British man who speaks clearly and kindly',
      sample: '/voices/andrew.mp3',
      preview_url:
        'https://huggingface.co/spaces/abidlabs/hfstudio/resolve/main/frontend/static/voices/andrew.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',
    },
    {
      id: 'pirate',
      name: 'Pirate',
      description: 'Young pirate that speaks gruffly and passionately',
      sample: '/voices/pirate.mp3',
      preview_url:
        'https://huggingface.co/spaces/abidlabs/hfstudio/resolve/main/frontend/static/voices/pirate.mp3',
    },
  ];

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

    const accessToken = getAccessToken();
    if (!accessToken) {
      window.dispatchEvent(new CustomEvent('show-login-prompt'));
      return;
    }

    isGenerating = true;
    audioUrl = null;
    currentTime = 0;

    // Generate import code when user starts interacting
    if (!importCode) {
      importCode = generateImportCode();
    }

    const ttsCode = generateTTSCode();

    isPlaying = false;

    audioTitle = text.length > 30 ? text.substring(0, 30) + '...' : text;

    try {
      const accessToken = getAccessToken();

      const requestBody = {
        text: text,
        voice_id: selectedVoice.toLowerCase(),
        model_id: selectedModel.toLowerCase(),
        mode: mode,
        access_token: accessToken,
        parameters: {
          exaggeration: exaggeration,
          temperature: temperature,
        },
      };

      const response = await fetch('/api/tts/generate', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        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;

        // Add to history with result
        addCodeToHistory(ttsCode, {
          type: 'audio',
          url: result.audio_url,
          title: audioTitle,
          duration: result.duration,
        });

        if (viewMode === 'ui') {
          // Autoplay the newly generated audio
          setTimeout(() => {
            if (audioElement) {
              audioElement.play().catch(() => {
                // Ignore autoplay failures (browser restrictions)
              });
            }
          }, 100); // Small delay to ensure audio element is ready
        }
      } 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 getAccessToken() {
    if (typeof window !== 'undefined' && window.gradio && window.gradio.auth_token) {
      return window.gradio.auth_token;
    }

    const metaToken = document.querySelector('meta[name="hf-oauth-token"]');
    if (metaToken) {
      const token = metaToken.getAttribute('content');
      if (token) {
        return token;
      }
    }

    const possibleKeys = [
      'hf_access_token',
      'hf_token',
      'huggingface_token',
      'oauth_token',
      'access_token',
    ];

    for (const key of possibleKeys) {
      const token = localStorage.getItem(key);
      if (token) {
        return token;
      }
    }

    for (const key of possibleKeys) {
      const token = sessionStorage.getItem(key);
      if (token) {
        return token;
      }
    }

    const cookies = document.cookie.split(';');
    for (const cookie of cookies) {
      const [name, value] = cookie.trim().split('=');
      if (name && (name.includes('token') || name.includes('hf') || name.includes('oauth'))) {
        return decodeURIComponent(value);
      }
    }

    try {
      const authHeader = document.querySelector('script[data-hf-token]');
      if (authHeader) {
        const token = authHeader.getAttribute('data-hf-token');
        if (token) {
          return token;
        }
      }
    } catch (e) {}

    return null;
  }

  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();
    }
  }

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

  function addCodeToHistory(code, result = null) {
    const entry = {
      id: Date.now() + Math.random(),
      code,
      result,
    };
    codeHistory = [...codeHistory, entry];
    saveHistoryToStorage();
    return entry;
  }

  function saveHistoryToStorage() {
    if (!currentUsername) return;
    const storageKey = `hfstudio_history_${currentUsername}`;
    const historyData = {
      username: currentUsername,
      setupCode,
      importCode,
      history: codeHistory,
    };
    localStorage.setItem(storageKey, JSON.stringify(historyData));
  }

  function loadHistoryFromStorage() {
    if (!currentUsername) return;
    const storageKey = `hfstudio_history_${currentUsername}`;
    const stored = localStorage.getItem(storageKey);
    if (stored) {
      try {
        const data = JSON.parse(stored);
        if (data.username === currentUsername) {
          setupCode = generateSetupCode(); // Always regenerate setup code
          importCode = data.importCode || null;
          codeHistory = data.history || [];
        }
      } catch (e) {
        console.error('Error loading history:', e);
      }
    }
  }

  function resetHistory() {
    codeHistory = [];
    setupCode = generateSetupCode(); // Keep setup code but regenerate it
    importCode = null; // Reset import code to show "Start using UI" message
    if (currentUsername) {
      const storageKey = `hfstudio_history_${currentUsername}`;
      localStorage.removeItem(storageKey);
    }
  }

  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() {
    // Generate the exact same client initialization code used in the server
    if (mode === 'local') {
      const port = 7861; // Default port from server.py line 297
      return `client = InferenceClient(base_url="http://localhost:${port}/api/v1")`;
    } else {
      // Use endpoint_model from spec file (e.g., "ResembleAI/chatterbox" for chatterbox)
      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 generateTTSCode() {
    // Get voice URL from the selected voice data (which comes from the server)
    const selectedVoiceData = voices.find((v) => v.name === selectedVoice);
    const voiceUrl = selectedVoiceData?.preview_url || selectedVoiceData?.sample;

    if (mode === 'local') {
      return `text = """${text}"""

# audio is in bytes format
audio = client.text_to_speech(
    text,
    extra_body={
        "audio_url": "${voiceUrl}",
        "exaggeration": ${exaggeration},
        "temperature": ${temperature}
    }
)`;
    } else {
      return `text = """${text}"""

# audio is in bytes format
audio = client.text_to_speech(
    text,
    extra_body={
        "audio_url": "${voiceUrl}",
        "exaggeration": ${exaggeration},
        "temperature": ${temperature}
    }
)`;
    }
  }

  function generateSaveCode() {
    return `# Save the audio to a file
output_filename = "output_speech.wav"

with open(output_filename, "wb") as f:
    f.write(audio_bytes)
    
print(f"✓ Audio saved to {output_filename}")

# Optional: Play the audio (requires additional packages)
# from playsound import playsound
# playsound(output_filename)`;
  }

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

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

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

  function copyErrorMessage() {
    const fullError = errorDetails ? `${errorMessage}\n\nDetails:\n${errorDetails}` : errorMessage;
    copyToClipboard(fullError, 'Error message copied!');
  }

  function copyAllCode() {
    const parts = [];

    // Add setup section with proper markdown formatting
    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\`\`\``);
    }

    // Add imports section with python code blocks
    if (importCode) {
      parts.push(`## Imports (Python)\n\n\`\`\`python\n${importCode}\n\`\`\``);
    }

    // Add history entries with python code blocks
    codeHistory.forEach((entry, i) => {
      parts.push(`## Cell ${i + 1}\n\n\`\`\`python\n${entry.code}\n\`\`\``);
    });

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

  onMount(() => {
    // Get username from parent layout or localStorage
    const checkUsername = () => {
      const token = localStorage.getItem('hf_access_token');
      if (token) {
        // Try to get username from parent component or make a quick API call
        fetchUserInfo(token);
      }
    };

    checkUsername();

    // Listen for auth changes
    window.addEventListener('storage', (e) => {
      if (e.key === 'hf_access_token') {
        checkUsername();
      }
    });
  });

  async function fetchUserInfo(token) {
    try {
      const response = await fetch('https://huggingface.co/api/whoami-v2', {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });

      if (response.ok) {
        const userData = await response.json();
        currentUsername =
          userData.name || userData.fullname || userData.login || userData.username || 'User';
        loadHistoryFromStorage();
      }
    } catch (error) {
      console.error('Error fetching user info:', error);
    }
  }

  // Update setup code when mode changes
  $: if (mode) {
    setupCode = generateSetupCode();
    // Update import code if it already exists (when mode changes)
    if (importCode) {
      importCode = generateImportCode();
    }
  }

  function toggleHistoryAudio(entry) {
    if (!entry.audioElement) {
      // Create audio element if it doesn't exist
      entry.audioElement = new Audio(entry.result.url);
      entry.audioElement.addEventListener('ended', () => {
        entry.isPlaying = false;
        codeHistory = [...codeHistory]; // Trigger reactivity
      });
    }

    if (entry.isPlaying) {
      entry.audioElement.pause();
      entry.isPlaying = false;
    } else {
      // Pause any other playing audio
      codeHistory.forEach((e) => {
        if (e !== entry && e.isPlaying && e.audioElement) {
          e.audioElement.pause();
          e.isPlaying = false;
        }
      });
      entry.audioElement.play();
      entry.isPlaying = true;
    }
    codeHistory = [...codeHistory]; // Trigger reactivity
  }

  function downloadHistoryAudio(url, title) {
    const link = document.createElement('a');
    link.href = url;
    link.download = `${title || 'audio'}.wav`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }

  function formatDuration(seconds) {
    if (!seconds) return '0:00';
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  }
</script>

<div class="flex flex-col h-full" on:click={handleClickOutside}>
  <!-- Header -->
  <header class="border-b border-gray-200 bg-white">
    <div class="flex items-center justify-end px-4 py-2">
      <div class="flex items-center gap-2">
        <!-- View mode toggle -->
        <div class="flex items-center bg-gray-100 rounded-md p-0.5">
          <button
            class="flex items-center gap-1.5 px-3 py-1 text-sm font-medium rounded transition-colors {viewMode ===
            'ui'
              ? 'bg-white shadow-sm'
              : 'text-gray-600'}"
            on:click={() => (viewMode = 'ui')}
          >
            <Layout size={14} />
            UI
          </button>
          <button
            class="flex items-center gap-1.5 px-3 py-1 text-sm font-medium rounded transition-colors relative {viewMode ===
            'code'
              ? 'bg-white shadow-sm'
              : 'text-gray-600'}"
            on:click={() => (viewMode = 'code')}
          >
            <Code size={14} />
            Code Recorder
            {#if codeHistory.length > 0}
              <span
                class="ml-1 px-1.5 py-0.5 text-xs bg-gray-500 text-white rounded-full min-w-[18px] h-[18px] flex items-center justify-center"
              >
                {codeHistory.length}
              </span>
            {/if}
          </button>
        </div>
      </div>
    </div>
  </header>

  <!-- Main content area -->
  {#if viewMode === 'ui'}
    <div class="flex-1 flex">
      <!-- Main content area -->
      <div class="flex-1 flex flex-col p-6">
        <!-- Text input area -->
        <div class="flex-1 pb-24">
          <textarea
            bind:value={text}
            class="w-full h-full p-6 bg-white resize-none border-0 focus:outline-none text-gray-900 text-base leading-relaxed"
            placeholder="In a hole in the ground there lived a hobbit."
          />
        </div>

        <!-- Fixed bottom generate button -->
        <div class="fixed bottom-0 left-56 right-80 p-4 bg-white border-t border-gray-200">
          <div class="flex items-center justify-between mb-3">
            <span class="text-sm text-gray-500">{text.length} / 5,000 characters</span>
          </div>
          <button
            on:click={generateSpeech}
            disabled={isGenerating || !text.trim()}
            class="w-full px-6 py-3 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-2 shadow-sm"
          >
            {#if isGenerating}
              <Loader2 size={20} class="animate-spin" />
              Generating...
            {:else}
              <Play size={20} />
              Generate speech
            {/if}
          </button>
        </div>

        <!-- Generated audio section -->
        {#if audioUrl}
          <div class="p-4 border border-gray-200 rounded-lg bg-white">
            <!-- Audio title and voice info -->
            <div class="flex items-center gap-3 mb-4">
              <div class="w-2 h-2 bg-green-500 rounded-full"></div>
              <div class="flex-1">
                <h3 class="font-medium text-gray-900 text-sm">{audioTitle}</h3>
                <p class="text-xs text-gray-500">{selectedVoice} • Created 1 second ago</p>
              </div>
              <!-- Mini action buttons -->
              <div class="flex items-center gap-2">
                <button
                  on:click={shareAudio}
                  class="flex items-center gap-1.5 px-3 py-1.5 text-sm border border-gray-200 rounded-md hover:bg-gray-50 transition-colors"
                >
                  <Share size={14} class="text-gray-600" />
                  <span class="text-gray-700">Share</span>
                </button>
                <button
                  on:click={downloadAudio}
                  class="flex items-center gap-1.5 px-3 py-1.5 text-sm border border-gray-200 rounded-md hover:bg-gray-50 transition-colors"
                >
                  <span class="text-gray-700">Download</span>
                  <Download size={14} class="text-gray-600" />
                </button>
              </div>
            </div>

            <!-- Mini audio controls -->
            <div class="flex items-center gap-3 mb-4">
              <!-- Play/Pause button -->
              <button
                on:click={togglePlayPause}
                class="w-8 h-8 bg-black rounded-full flex items-center justify-center hover:bg-gray-800 transition-colors"
              >
                {#if isPlaying}
                  <div class="pause-filled text-white"></div>
                {:else}
                  <Play size={14} class="text-white ml-0.5" />
                {/if}
              </button>

              <!-- Progress bar -->
              <div class="flex-1 flex items-center gap-2">
                <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>

            <!-- Full audio player controls -->
            <div class="flex items-center gap-4 mb-4">
              <!-- Skip back button -->
              <button class="p-2 hover:bg-gray-100 rounded-full" title="Skip back">
                <SkipBack size={20} class="text-gray-600" />
              </button>

              <!-- Play/Pause button -->
              <button
                on:click={togglePlayPause}
                class="w-12 h-12 bg-black rounded-full flex items-center justify-center hover:bg-gray-800 transition-colors"
              >
                {#if isPlaying}
                  <div class="pause-filled text-white scale-150"></div>
                {:else}
                  <Play size={20} class="text-white ml-0.5" />
                {/if}
              </button>

              <!-- Skip forward button -->
              <button class="p-2 hover:bg-gray-100 rounded-full" title="Skip forward">
                <SkipForward size={20} class="text-gray-600" />
              </button>

              <!-- Progress bar -->
              <div class="flex-1 flex items-center gap-3">
                <span class="text-xs text-gray-500 font-mono">{formatTime(currentTime)}</span>
                <div class="flex-1 h-1 bg-gray-200 rounded-full">
                  <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>

              <!-- Action buttons -->
              <div class="flex items-center gap-2">
                <button
                  on:click={shareAudio}
                  class="flex items-center gap-2 px-3 py-1.5 text-sm border border-gray-200 rounded-md hover:bg-gray-50"
                >
                  <Share size={14} />
                  Share
                </button>
                <button
                  on:click={downloadAudio}
                  class="p-2 hover:bg-gray-100 rounded-md"
                  title="Download"
                >
                  <Download size={16} class="text-gray-600" />
                </button>
                <button class="p-2 hover:bg-gray-100 rounded-md" title="More options">
                  <MoreHorizontal size={16} class="text-gray-600" />
                </button>
              </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>
        {/if}
      </div>

      <!-- Right panel -->
      <div class="w-80 border-l border-gray-200 bg-white p-4 overflow-y-auto">
        <!-- Model selector -->
        <div class="mb-6 relative model-dropdown">
          <h3 class="font-medium text-gray-900 mb-3">Model</h3>
          <button
            on:click={() => (modelDropdownOpen = !modelDropdownOpen)}
            class="w-full p-3 border border-gray-200 rounded-lg bg-white text-sm focus:outline-none focus:ring-2 focus:ring-amber-400 focus:border-transparent appearance-none bg-no-repeat bg-right pr-10 shadow-sm text-left flex items-center justify-between"
          >
            <span>
              {#each models as model}
                {#if model.name === selectedModel}
                  {model.name}{#if model.badge}&nbsp;<span class="text-xs text-gray-500"
                      >({model.badge})</span
                    >{/if}
                {/if}
              {/each}
            </span>
            <ChevronDown size={16} class="text-gray-500" />
          </button>

          {#if modelDropdownOpen}
            <div
              class="absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-10"
            >
              {#each models as model}
                <button
                  class="w-full px-3 py-2 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-xs text-gray-500"
                      >({model.badge})</span
                    >{/if}
                </button>
              {/each}
            </div>
          {/if}

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

        <div class="mb-6">
          <div class="mb-3">
            <h3 class="font-medium text-gray-900">Voice</h3>
          </div>

          <div class="space-y-2">
            {#each voices as voice}
              <button
                class="w-full flex items-center justify-between p-2 rounded-lg hover:bg-gray-50 transition-colors text-left group border border-transparent
                   {voice.name === selectedVoice ? 'bg-gray-100 border-gray-200' : ''}"
                on:click={() => (selectedVoice = voice.name)}
              >
                <div class="flex items-center gap-3 flex-1 min-w-0">
                  <div
                    class="w-10 h-10 bg-gradient-to-br from-amber-400 to-orange-500 rounded-full flex items-center justify-center text-white text-sm font-semibold flex-shrink-0"
                  >
                    {voice.name[0]}
                  </div>
                  <div class="flex-1 min-w-0">
                    <div class="text-sm font-medium text-gray-900 mb-1">{voice.name}</div>
                    <div class="text-xs text-gray-500 leading-relaxed">
                      {voice.description}
                    </div>
                  </div>
                </div>
                <button
                  on:click={(e) => playSampleVoice(voice, e)}
                  class="p-2 rounded-full hover:bg-gray-200 transition-colors flex-shrink-0 ml-2 w-8 h-8 flex items-center justify-center"
                  title="Play sample"
                >
                  {#if playingSampleVoice === voice.name}
                    <Pause size={16} class="text-gray-600" />
                  {:else}
                    <Play size={16} class="text-gray-600" />
                  {/if}
                </button>
              </button>
            {/each}

            <!-- Clone voice option -->
            <button
              class="w-full flex items-center justify-between p-2 rounded-lg opacity-50 cursor-not-allowed text-left border border-transparent"
              disabled
            >
              <div class="flex items-center gap-3 flex-1 min-w-0">
                <div
                  class="w-10 h-10 bg-gray-400 rounded-full flex items-center justify-center text-white text-sm font-medium flex-shrink-0"
                >
                  +
                </div>
                <div class="flex-1 min-w-0">
                  <div class="text-sm font-medium text-gray-600 mb-1">Clone your voice</div>
                  <div class="text-xs text-gray-400">(coming soon)</div>
                </div>
              </div>
            </button>
          </div>
        </div>

        <div class="space-y-4 pt-4 border-t border-gray-200">
          <!-- Exaggeration control -->
          <div>
            <div class="flex justify-between mb-1">
              <label for="exaggeration-slider" class="text-sm font-medium text-gray-700"
                >Exaggeration</label
              >
              <span class="text-sm text-gray-500">{exaggeration.toFixed(2)}</span>
            </div>
            <input
              id="exaggeration-slider"
              type="range"
              bind:value={exaggeration}
              min="0"
              max="1"
              step="0.01"
              class="w-full h-1.5 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>Exaggerated</span>
            </div>
          </div>

          <!-- Stability control -->
          <div>
            <div class="flex justify-between mb-1">
              <label for="temperature-slider" class="text-sm font-medium text-gray-700"
                >Stability</label
              >
              <span class="text-sm text-gray-500">{temperature.toFixed(2)}</span>
            </div>
            <input
              id="temperature-slider"
              type="range"
              bind:value={temperature}
              min="0"
              max="1"
              step="0.01"
              class="w-full h-1.5 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>
  {:else}
    <!-- Code view -->
    <div class="flex-1 bg-gray-50 overflow-y-auto">
      <div class="max-w-4xl mx-auto p-8">
        <!-- Header -->
        <div class="mb-6">
          <div>
            <h2 class="text-2xl font-semibold text-gray-900">Code Recorder</h2>
            <p class="text-sm text-gray-600 mt-1">
              {#if mode === 'local'}
                Python code to reproduce your actions using a local HFStudio server
              {:else}
                Python code to reproduce your actions via the API
              {/if}
            </p>
          </div>

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

            {#if codeHistory.length > 0 || setupCode || importCode}
              <div class="flex items-center gap-2">
                <button
                  on:click={resetHistory}
                  class="flex items-center bg-red-50 hover:bg-red-100 rounded-md px-3 py-1.5 transition-colors"
                  title="Clear history"
                >
                  <RotateCcw size={16} class="text-red-600" />
                  <span class="ml-2 text-sm font-medium text-red-600">Reset history</span>
                </button>
                <button
                  on:click={copyAllCode}
                  class="flex items-center bg-gray-100 hover:bg-gray-200 rounded-md px-3 py-1.5 transition-colors"
                >
                  <Copy size={16} class="text-gray-600" />
                  <span class="ml-2 text-sm font-medium text-gray-600">Copy all as Markdown</span>
                </button>
              </div>
            {/if}
          </div>
        </div>

        <!-- Code sections -->
        <div class="space-y-6">
          <!-- Setup Section - Always shown -->
          {#if setupCode}
            <div class="bg-white rounded-lg border border-gray-200 overflow-hidden">
              <div
                class="flex items-center justify-between px-4 py-2 bg-amber-50 border-b border-amber-200"
              >
                <div class="flex items-center gap-2">
                  <span class="text-sm font-medium text-amber-900">Setup (Run in Terminal)</span>
                  <span class="text-xs bg-amber-100 text-amber-700 px-2 py-0.5 rounded"
                    >Run once</span
                  >
                </div>
                <button
                  on:click={() => copyToClipboard(setupCode)}
                  class="p-1.5 hover:bg-amber-100 rounded transition-colors"
                  title="Copy setup code"
                >
                  <Copy size={14} class="text-amber-600" />
                </button>
              </div>
              <div class="relative">
                {#if setupCode === 'pip install huggingface-hub'}
                  <pre class="p-4 overflow-x-auto bg-gray-50"><code
                      class="language-bash text-sm text-black">{setupCode}</code
                    ></pre>
                {:else}
                  <pre class="p-4 overflow-x-auto bg-gray-50"><code class="language-bash text-sm"
                      >{@html Prism.highlight(setupCode, Prism.languages.bash, 'bash')}</code
                    ></pre>
                {/if}
              </div>
            </div>
          {/if}

          <!-- Import Section -->
          {#if importCode}
            <div class="bg-white rounded-lg border border-gray-200 overflow-hidden">
              <div
                class="flex items-center justify-between px-4 py-2 bg-blue-50 border-b border-blue-200"
              >
                <div class="flex items-center gap-2">
                  <span class="text-sm font-medium text-blue-900">Imports (Python)</span>
                  <span class="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded">Run once</span
                  >
                </div>
                <button
                  on:click={() => copyToClipboard(importCode)}
                  class="p-1.5 hover:bg-blue-100 rounded transition-colors"
                  title="Copy import code"
                >
                  <Copy size={14} class="text-blue-600" />
                </button>
              </div>
              <div class="relative">
                <pre class="p-4 overflow-x-auto bg-gray-50"><code class="language-python text-sm"
                    >{@html Prism.highlight(importCode, Prism.languages.python, 'python')}</code
                  ></pre>
              </div>
            </div>
          {/if}

          <!-- Show "start using UI" message when no import code or history -->
          {#if !importCode && codeHistory.length === 0}
            <div class="bg-white rounded-lg border border-gray-200 p-8 text-center">
              <p class="text-gray-500">Start using the UI to see generated code here</p>
              {#if currentUsername}
                <p class="text-xs text-gray-400 mt-2">Logged in as: {currentUsername}</p>
              {/if}
            </div>
          {/if}

          <!-- History entries -->
          {#each codeHistory as entry, i (entry.id)}
            <div class="bg-white rounded-lg border border-gray-200 overflow-hidden shadow-sm">
              <!-- Code cell -->
              <div class="border-b border-gray-200">
                <div
                  class="flex items-center justify-between px-4 py-2 bg-gray-50 border-b border-gray-100"
                >
                  <span class="text-sm font-medium text-gray-700">Cell {i + 1}</span>
                  <button
                    on:click={() => copyToClipboard(entry.code)}
                    class="p-1.5 hover:bg-gray-200 rounded transition-colors"
                    title="Copy code"
                  >
                    <Copy size={14} class="text-gray-600" />
                  </button>
                </div>
                <div class="relative">
                  <pre class="p-4 overflow-x-auto bg-gray-50"><code class="language-python text-sm"
                      >{@html Prism.highlight(entry.code, Prism.languages.python, 'python')}</code
                    ></pre>
                </div>
              </div>

              <!-- Result (audio player) -->
              {#if entry.result && entry.result.type === 'audio'}
                <div class="bg-gradient-to-b from-gray-50 to-white p-4">
                  <div class="bg-white rounded-lg border border-gray-200 p-4 shadow-sm">
                    <div class="flex items-center justify-between">
                      <div class="flex items-center gap-3 flex-1">
                        <button
                          on:click={() => toggleHistoryAudio(entry)}
                          class="w-10 h-10 bg-gradient-to-r from-amber-500 to-orange-500 rounded-full flex items-center justify-center text-white hover:from-amber-600 hover:to-orange-600 transition-colors shadow-md"
                        >
                          {#if entry.isPlaying}
                            <Pause size={18} />
                          {:else}
                            <Play size={18} class="ml-0.5" />
                          {/if}
                        </button>
                        <div class="flex-1">
                          <div class="text-sm font-medium text-gray-900 truncate">
                            {entry.result.title || 'Generated Audio'}
                          </div>
                          <div class="text-xs text-gray-500">
                            Duration: {formatDuration(entry.result.duration || 0)}
                          </div>
                        </div>
                      </div>
                      <div class="flex items-center gap-1">
                        <button
                          on:click={() =>
                            downloadHistoryAudio(entry.result.url, entry.result.title)}
                          class="p-2 hover:bg-gray-100 rounded-lg transition-colors"
                          title="Download"
                        >
                          <Download size={16} class="text-gray-600" />
                        </button>
                        <button
                          class="p-2 hover:bg-gray-100 rounded-lg transition-colors"
                          title="Share"
                        >
                          <Share size={16} class="text-gray-600" />
                        </button>
                      </div>
                    </div>
                    <audio
                      bind:this={entry.audioElement}
                      src={entry.result.url}
                      on:ended={() => (entry.isPlaying = false)}
                      class="hidden"
                    />
                  </div>
                </div>
              {/if}
            </div>
          {/each}
        </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}

  <!-- 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">{errorDetails}</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={copyErrorMessage}
            class="flex items-center gap-2 px-4 py-2 text-gray-700 hover:bg-gray-200 rounded-lg transition-colors"
          >
            <Copy size={16} />
            Copy Error
          </button>
          <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}
</div>

<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;
  }

  @keyframes sweep {
    0% {
      left: -100%;
    }
    20% {
      left: -100%;
    }
    80% {
      left: 100%;
    }
    100% {
      left: 100%;
    }
  }

  @keyframes pulse {
    0% {
      box-shadow: 0 0 0 0 rgba(251, 191, 36, 0);
    }
    50% {
      box-shadow: 0 0 0 6px rgba(251, 191, 36, 0.4);
    }
    100% {
      box-shadow: 0 0 0 0 rgba(251, 191, 36, 0);
    }
  }
</style>
