<script lang="ts">
  import Dataframe from '@gradio/dataframe';
  import { onMount } from 'svelte';
  import { pipeline, TextStreamer } from "@huggingface/transformers";

  // Global state to avoid reloading model
  type LLMGlobal = { generator: any | null };
  const g = globalThis as any;
  let __LLM: LLMGlobal = g.__LLM || { generator: null };
  g.__LLM = __LLM;

  let isModelReady = !!__LLM.generator;
  let modelStatus = __LLM.generator ? '✅ AI ready! Ask me anything about the data.' : 'Loading AI model...';
  let loadingProgress = __LLM.generator ? 100 : 0;

  // Sample data for the dataframe
  let value: { data: string[][]; headers: string[] } = {
    headers: ['Name', 'Age', 'City', 'Score', 'Status'],
    data: [
      ['Alice Johnson', '28', 'New York', '92.5', 'Active'],
      ['Bob Smith', '34', 'Los Angeles', '87.3', 'Active'],
      ['Carol Davis', '29', 'Chicago', '95.1', 'Inactive'],
      ['David Wilson', '42', 'Houston', '78.9', 'Active'],
      ['Eva Brown', '31', 'Phoenix', '88.7', 'Active'],
      ['Frank Miller', '37', 'Philadelphia', '91.2', 'Inactive'],
      ['Grace Lee', '26', 'San Antonio', '94.8', 'Active'],
      ['Henry Taylor', '45', 'San Diego', '82.6', 'Active']
    ]
  };

  function handleChange(event: CustomEvent) {
    value = event.detail;
  }

  let query = 'How old is Alice?';
  let response = '';
  let isSearching = false;

  onMount(async () => {
    if (__LLM.generator) return; // Already loaded
    
    try {
      modelStatus = '📦 Loading model components...';
      loadingProgress = 10;
      
      const generator = await pipeline("text-generation", "onnx-community/gemma-3-270m-it-ONNX", {
        dtype: "fp32",
        device: "webgpu",
        progress_callback: (item) => {
          if (item.status === "progress" && item.file?.endsWith?.("onnx_data")) {
            loadingProgress = Math.min(100, item.progress || 0);
            modelStatus = `🚀 Loading model... ${Math.round(loadingProgress)}%`;
          }
        },
      });
      
      __LLM.generator = generator;
      isModelReady = true;
      loadingProgress = 100;
      modelStatus = '✅ AI ready! Ask me anything about the data.';
      
      console.log('Gemma-3 model loaded successfully');
    } catch (error) {
      console.error('Failed to initialize model:', error);
      modelStatus = '⚠️ Failed to load AI model. Using fallback responses.';
      isModelReady = false;
      loadingProgress = 0;
    }
  });

  async function searchData() {
    if (!query.trim()) return;
    
    isSearching = true;
    response = '';
    
    if (!isModelReady || !__LLM.generator) {
      response = '⏳ AI model is still initializing. Please wait...';
      isSearching = false;
      return;
    }

    const userMessage = query.trim();
    
    try {
      response = '🤔 Thinking...';
      await new Promise(resolve => requestAnimationFrame(resolve));
      
      const systemPrompt = `You are a helpful AI assistant that answers questions about employee data. Here's the current data:

${value.headers.join(' | ')}
${value.data.map(row => row.join(' | ')).join('\n')}

Keep your responses concise and helpful. Answer questions about the data above. Use emojis to make responses engaging.`;

      const messages = [
        { role: "system", content: systemPrompt },
        { role: "user", content: userMessage }
      ];

      let fullResponse = '';
      const streamer = new TextStreamer(__LLM.generator.tokenizer, {
        skip_prompt: true,
        skip_special_tokens: true,
        callback_function: (token: string) => {
          fullResponse += token;
          response = fullResponse;
        },
      });

      await __LLM.generator(messages, {
        max_new_tokens: 256,
        do_sample: false,
        streamer,
      });

      response = fullResponse || 'Sorry, I couldn\'t generate a response.';
      
    } catch (error) {
      console.error('Generation error:', error);
      
      // Fallback to smart responses based on query analysis
      const lowerQuery = userMessage.toLowerCase();
      
      if (lowerQuery.includes('how many') || lowerQuery.includes('count')) {
        if (lowerQuery.includes('active')) {
          const activeCount = value.data.filter(row => row[4] === 'Active').length;
          response = `📊 There are ${activeCount} active users in the dataset.`;
        } else if (lowerQuery.includes('inactive')) {
          const inactiveCount = value.data.filter(row => row[4] === 'Inactive').length;
          response = `📊 There are ${inactiveCount} inactive users in the dataset.`;
        } else {
          response = `📊 There are ${value.data.length} total records in the dataset.`;
        }
      } else if (lowerQuery.includes('highest score') || lowerQuery.includes('best score')) {
        const scores = value.data.map(row => parseFloat(row[3]));
        const maxScore = Math.max(...scores);
        const topUser = value.data.find(row => parseFloat(row[3]) === maxScore);
        response = `🏆 ${topUser?.[0]} has the highest score of ${maxScore} from ${topUser?.[2]}.`;
      } else if (lowerQuery.includes('lowest score') || lowerQuery.includes('worst score')) {
        const scores = value.data.map(row => parseFloat(row[3]));
        const minScore = Math.min(...scores);
        const bottomUser = value.data.find(row => parseFloat(row[3]) === minScore);
        response = `📉 ${bottomUser?.[0]} has the lowest score of ${minScore} from ${bottomUser?.[2]}.`;
      } else if (lowerQuery.includes('average age') || lowerQuery.includes('mean age')) {
        const ages = value.data.map(row => parseInt(row[1]));
        const avgAge = (ages.reduce((sum, age) => sum + age, 0) / ages.length).toFixed(1);
        response = `👥 The average age of users is ${avgAge} years old.`;
      } else {
        response = `⚠️ Sorry, I encountered an error processing your request. Please try a different question about the data.`;
      }
    } finally {
      isSearching = false;
    }
  }

  function handleKeyPress(event: KeyboardEvent) {
    if (event.key === 'Enter') {
      searchData();
    }
  }
</script>

<div class="fullscreen-dataframe">
  <div class="dataframe-container">
    <Dataframe
      bind:value={value}
      show_row_numbers={true}
      editable={true}
      on:change={handleChange}
    />
  </div>
  
  <div class="search-panel">
    <div class="search-container">
      <div class="search-header">
        <h2>✨ Ask me anything about your data</h2>
        <p>Try: "How old is Alice?"</p>
        <div class="built-with">
          ❤︎ &nbsp; Built with Gemma 3 270M Onnx & <a href="https://www.gradio.app/docs/js/dataframe" target="_blank" rel="noopener noreferrer">Gradio's Dataframe.js</a>
        </div>
      </div>
      
      <div class="search-input-container">
        {#if !isModelReady}
          <div class="progress-container">
            <div class="progress-bar">
              <div class="progress-fill" style="width: {loadingProgress}%"></div>
            </div>
            <div class="progress-text">{modelStatus}</div>
          </div>
        {:else}
          <input
            type="text"
            bind:value={query}
            on:keypress={handleKeyPress}
            class="search-input"
            disabled={isSearching}
          />
          <button 
            class="search-button"
            on:click={searchData}
            disabled={isSearching || !query.trim()}
          >
            {#if isSearching}
              <div class="spinner"></div>
            {:else}
              🔍 Ask
            {/if}
          </button>
        {/if}
      </div>
      
      {#if response}
        <div class="response-container">
          <div class="response-text">
            {response}
          </div>
        </div>
      {/if}
    </div>
  </div>
</div>

<style>
  :global(*) {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  :global(body, html) {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
  }

  .fullscreen-dataframe {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    background: white;
    display: flex;
    flex-direction: column;
  }

  .dataframe-container {
    flex: 1;
    overflow: hidden;
  }

  .search-panel {
    background: linear-gradient(135deg, #ff6b35 0%, #1a1a1a 100%);
    padding: 2rem;
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.1);
  }

  .search-container {
    max-width: 800px;
    margin: 0 auto;
  }

  .search-header {
    text-align: center;
    margin-bottom: 1.5rem;
  }

  .search-header h2 {
    color: white;
    font-size: 1.8rem;
    font-weight: 700;
    margin: 0 0 0.5rem 0;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  }

  .search-header p {
    color: rgba(255, 255, 255, 0.9);
    font-size: 1rem;
    margin: 0;
    opacity: 0.9;
  }

  .built-with {
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.85rem;
    margin-top: 0.5rem;
    font-style: italic;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  }

  .built-with a {
    color: rgba(255, 255, 255, 0.9);
    text-decoration: underline;
    text-decoration-color: rgba(255, 255, 255, 0.5);
    transition: all 0.2s ease;
  }

  .built-with a:hover {
    color: white;
    text-decoration-color: white;
  }

  .search-input-container {
    display: flex;
    gap: 1rem;
    margin-bottom: 1.5rem;
  }

  .progress-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
  }

  .progress-bar {
    height: 60px;
    background: rgba(255, 255, 255, 0.2);
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-radius: 50px;
    overflow: hidden;
    backdrop-filter: blur(10px);
    position: relative;
    padding: 0;
  }

  .progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #ff6b35, rgba(255, 255, 255, 0.8));
    border-radius: 0;
    transition: width 0.5s ease-out;
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
  }

  .progress-fill::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    animation: shimmer 2s infinite;
  }

  .progress-text {
    color: white;
    text-align: center;
    font-weight: 600;
    font-size: 1rem;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  }

  .search-input {
    flex: 1;
    padding: 1rem 1.5rem;
    border: none;
    border-radius: 50px;
    font-size: 1.1rem;
    background: white;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    outline: none;
    transition: all 0.3s ease;
  }

  .search-input:focus {
    box-shadow: 0 6px 25px rgba(0, 0, 0, 0.15);
    transform: translateY(-2px);
  }

  .search-input:disabled {
    opacity: 0.7;
  }

  .search-button {
    padding: 1rem 2rem;
    background: rgba(255, 255, 255, 0.2);
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-radius: 50px;
    color: white;
    font-weight: 600;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    backdrop-filter: blur(10px);
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }

  .search-button:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.3);
    border-color: rgba(255, 255, 255, 0.5);
    transform: translateY(-2px);
  }

  .search-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }

  .response-container {
    background: rgba(255, 255, 255, 0.95);
    border-radius: 20px;
    padding: 1.5rem 2rem;
    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
    backdrop-filter: blur(10px);
    animation: slideUp 0.5s ease-out;
  }

  .response-text {
    font-size: 1.1rem;
    line-height: 1.6;
    color: #2d3748;
    margin: 0;
  }

  .spinner {
    width: 20px;
    height: 20px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-top: 2px solid white;
    border-radius: 50%;
    animation: spin 1s linear infinite;
  }

  @keyframes spin {
    to { transform: rotate(360deg); }
  }

  @keyframes slideUp {
    from {
      opacity: 0;
      transform: translateY(20px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  @keyframes shimmer {
    0% {
      left: -100%;
    }
    100% {
      left: 100%;
    }
  }
</style>