{% extends "base.html" %}
{% from 'partials/_buttons.html' import button %}

{% block content %}
<style>
  /* Setup page-specific styling */
  #content details > summary {
    color: #3b82f6;
    cursor: pointer;
    font-weight: 500;
  }
  #content details > summary:hover {
    color: #60a5fa;
  }
  #content details > div {
    background: var(--panel) !important;
    border-color: var(--border) !important;
  }
  #content .muted {
    color: #94a3b8;
  }
  /* Make all buttons on this page blue */
  #content button,
  #content input[type="submit"] {
    background: #3b82f6 !important;
    border-color: #3b82f6 !important;
    color: white !important;
  }
  #content button:hover,
  #content input[type="submit"]:hover {
    background: #2563eb !important;
    border-color: #2563eb !important;
  }
  #content button:active,
  #content input[type="submit"]:active {
    background: #1d4ed8 !important;
  }
  /* Progress bars */
  #content [id$="-progress-bar"] {
    background: var(--bg) !important;
  }
  /* Log output areas */
  #content pre {
    background: var(--panel) !important;
    border-color: var(--border) !important;
  }
</style>

<section>
  <h2>Setup / Tagging</h2>
  <p class="muted" style="max-width:70ch;">Prepare or refresh the card database and apply tags. You can run this anytime.</p>

  <details open style="margin-top:.5rem;">
    <summary>Current Status</summary>
    <div id="setup-status" style="margin-top:.5rem; padding:1rem; border:1px solid var(--border); background:var(--panel); border-radius:8px;">
      <div class="muted">Status:</div>
      <div id="setup-status-line" style="margin-top:.25rem;">Checking…</div>
      <div id="setup-progress-line" class="muted" style="margin-top:.25rem; display:none;"></div>
      <div id="setup-progress-bar" style="margin-top:.25rem; width:100%; height:10px; background:var(--bg); border:1px solid var(--border); border-radius:6px; overflow:hidden; display:none;">
        <div id="setup-progress-bar-inner" style="height:100%; width:0%; background:#3b82f6;"></div>
      </div>
      <div id="setup-time-line" class="muted" style="margin-top:.25rem; display:none;"></div>
  <div id="setup-color-line" class="muted" style="margin-top:.25rem; display:none;"></div>
      <details id="setup-log-wrap" style="margin-top:.5rem; display:none;">
        <summary id="setup-log-summary" class="muted" style="cursor:pointer;">Show logs</summary>
        <pre id="setup-log-tail" style="margin-top:.5rem; max-height:240px; overflow:auto; background:var(--panel); border:1px solid var(--border); padding:.5rem; border-radius:6px;"></pre>
      </details>
    </div>
  </details>

  <details style="margin-top:1rem;">
    <summary>Download Pre-tagged Database from GitHub (Optional)</summary>
    <div style="margin-top:.5rem; padding:1rem; border:1px solid var(--border); background:var(--panel); border-radius:8px;">
      <p class="muted" style="margin:0 0 .75rem 0; font-size:.9rem;">
        Download pre-tagged card database and similarity cache from GitHub (updated weekly). 
        <strong>Note:</strong> A fresh local tagging run will be most up-to-date with the latest card data.
      </p>
      {{ button('Download from GitHub', variant='priamry', onclick='downloadFromGitHub()', attrs='id="btn-download-github"') }}
      <div id="download-status" class="muted" style="margin-top:.5rem; display:none;"></div>
    </div>
  </details>

  {% if image_cache_enabled %}
  <details style="margin-top:1rem;">
    <summary>Download Card Images (Optional)</summary>
    <div style="margin-top:.5rem; padding:1rem; border:1px solid var(--border); background:var(--panel); border-radius:8px;">
      <p class="muted" style="margin:0 0 .75rem 0; font-size:.9rem;">
        Download card images from Scryfall CDN for faster loading and offline use.
        <strong>Note:</strong> Requires ~3-6 GB disk space and 1-2 hours download time (~30k cards).
      </p>
      <div id="image-cache-status" style="margin-bottom:.75rem;">
        <div class="muted">Status:</div>
        <div id="image-status-line" style="margin-top:.25rem;">Checking…</div>
        <div class="muted" id="image-stats-line" style="margin-top:.25rem; display:none;"></div>
      </div>
      {{ button('Download Card Images', variant='priamry', onclick='downloadCardImages()', attrs='id="btn-download-images"') }}
      <div id="image-download-status" class="muted" style="margin-top:.5rem; display:none;"></div>
      <div id="image-progress-bar" style="margin-top:.5rem; width:100%; height:10px; background:var(--bg); border:1px solid var(--border); border-radius:6px; overflow:hidden; display:none;">
        <div id="image-progress-bar-inner" style="height:100%; width:0%; background:#3b82f6;"></div>
      </div>
    </div>
  </details>
  {% endif %}

  <div style="margin-top:1rem; display:flex; gap:.5rem; flex-wrap:wrap;">
    <form id="frm-start-setup" action="/setup/start" method="post" onsubmit="event.preventDefault(); startSetup();">
      {{ button('Run Setup/Tagging', variant='primary', type='submit', attrs='id="btn-start-setup"') }}
      <label class="muted" style="margin-left:.75rem; font-size:.9rem;">
        <input type="checkbox" id="chk-force" checked /> Force run
      </label>
    </form>
    <form method="get" action="/setup/running?start=1&force=1">
      {{ button('Open Progress Page', variant='primary', type='submit') }}
    </form>
  </div>

  <details style="margin-top:1.25rem;" open>
    <summary>Theme Catalog Status</summary>
    <div id="themes-status" style="margin-top:.5rem; padding:1rem; border:1px solid var(--border); background:var(--panel); border-radius:8px;">
      <div class="muted">Status:</div>
      <div id="themes-status-line" style="margin-top:.25rem;">Checking…</div>
      <div class="muted" id="themes-meta-line" style="margin-top:.25rem; display:none;"></div>
      <div class="muted" id="themes-stale-line" style="margin-top:.25rem; display:none; color:#f87171;"></div>
    </div>
  </details>
  <div style="margin-top:.75rem; display:flex; gap:.5rem; flex-wrap:wrap;">
    {{ button('Refresh Themes Only', variant='priamry', onclick='refreshThemes()', attrs='id="btn-refresh-themes"') }}
  </div>

  {% if similarity_enabled %}
  <details style="margin-top:1.25rem;" open>
    <summary>Similarity Cache Status</summary>
    <div id="similarity-status" style="margin-top:.5rem; padding:1rem; border:1px solid var(--border); background:var(--panel); border-radius:8px;">
      <div class="muted">Status:</div>
      <div id="similarity-status-line" style="margin-top:.25rem;">Checking…</div>
      <div class="muted" id="similarity-meta-line" style="margin-top:.25rem; display:none;"></div>
      <div class="muted" id="similarity-warning-line" style="margin-top:.25rem; display:none; color:#f59e0b;"></div>
    </div>
  </details>
  <div style="margin-top:.75rem; display:flex; gap:.5rem; flex-wrap:wrap;">
    {{ button('Build Similarity Cache', variant='priamry', onclick='buildSimilarityCache()', attrs='id="btn-build-similarity"') }}
    <label class="muted" style="align-self:center; font-size:.85rem;">
      <input type="checkbox" id="chk-skip-download" /> Skip GitHub download (build locally)
    </label>
    <span class="muted" style="align-self:center; font-size:.85rem;">(~15-20 min local, instant if cached on GitHub)</span>
  </div>
  {% endif %}
</section>
<script>
(function(){
  // Minimal styling helper to unify button widths (only for content buttons)
  try {
    var style = document.createElement('style');
    style.textContent = '.content .btn{min-width:180px;}';
    document.head.appendChild(style);
  } catch(e){}
  function update(data){
    var line = document.getElementById('setup-status-line');
    var colorEl = document.getElementById('setup-color-line');
    var logEl = document.getElementById('setup-log-tail');
  var progEl = document.getElementById('setup-progress-line');
  var timeEl = document.getElementById('setup-time-line');
  var bar = document.getElementById('setup-progress-bar');
  var barIn = document.getElementById('setup-progress-bar-inner');
  var logWrap = document.getElementById('setup-log-wrap');
  var logSummary = document.getElementById('setup-log-summary');
    if (!line) return;
    if (data && data.running) {
      line.textContent = (data.message || 'Working…');
      if (typeof data.percent === 'number') {
        progEl.style.display = '';
        var p = Math.max(0, Math.min(100, data.percent));
        progEl.textContent = 'Progress: ' + p + '%';
        if (bar && barIn) { bar.style.display = ''; barIn.style.width = p + '%'; }
        if (typeof data.color_idx === 'number' && typeof data.color_total === 'number') {
          progEl.textContent += ' • Colors: ' + data.color_idx + ' / ' + data.color_total;
        }
        if (typeof data.eta_seconds === 'number') {
          var mins = Math.floor(data.eta_seconds / 60); var secs = data.eta_seconds % 60;
          progEl.textContent += ' • ETA: ~' + mins + 'm ' + secs + 's';
        }
      } else {
        progEl.style.display = 'none';
        if (bar) bar.style.display = 'none';
      }
      if (data.started_at) {
        timeEl.style.display = '';
        timeEl.textContent = 'Started: ' + data.started_at;
      } else {
        timeEl.style.display = 'none';
      }
      if (data.color) {
        colorEl.style.display = '';
        colorEl.textContent = 'Current color: ' + data.color;
      } else {
        colorEl.style.display = 'none';
      }
      if (data.log_tail) {
        var lines = data.log_tail.split(/\r?\n/).filter(function(x){ return x.trim() !== ''; });
        if (logWrap) logWrap.style.display = '';
        if (logSummary) logSummary.textContent = 'Show logs (' + lines.length + ' lines)';
        logEl.textContent = data.log_tail;
      } else {
        if (logWrap) logWrap.style.display = 'none';
      }
    } else if (data && data.phase === 'done') {
      line.textContent = 'Setup complete.';
      if (typeof data.percent === 'number') {
        progEl.style.display = '';
        var p2 = Math.max(0, Math.min(100, data.percent));
        progEl.textContent = 'Progress: ' + p2 + '%';
        if (bar && barIn) { bar.style.display = ''; barIn.style.width = p2 + '%'; }
      } else {
        progEl.style.display = 'none';
        if (bar) bar.style.display = 'none';
      }
      if (data.started_at || data.finished_at) {
        timeEl.style.display = '';
        var t = [];
        if (data.started_at) t.push('Started: ' + data.started_at);
        if (data.finished_at) t.push('Finished: ' + data.finished_at);
        timeEl.textContent = t.join(' • ');
      } else {
        timeEl.style.display = 'none';
      }
  colorEl.style.display = 'none';
  if (logWrap) logWrap.style.display = 'none';
    } else if (data && data.phase === 'error') {
      line.textContent = (data.message || 'Setup error.');
      if (data.color) {
        colorEl.style.display = '';
        colorEl.textContent = 'While working on: ' + data.color;
      }
    } else {
      line.textContent = 'Idle';
      progEl.style.display = 'none';
      timeEl.style.display = 'none';
  colorEl.style.display = 'none';
  if (logWrap) logWrap.style.display = 'none';
    }
  }
  function poll(){
    fetch('/status/setup', { cache: 'no-store' })
      .then(function(r){ return r.json(); })
      .then(update)
      .catch(function(){});
    pollThemes();
  }
  function pollThemes(){
    fetch('/themes/status', { cache: 'no-store' })
      .then(function(r){ return r.json(); })
      .then(updateThemes)
      .catch(function(){});
  }
  function updateThemes(data){
    var line = document.getElementById('themes-status-line');
    var meta = document.getElementById('themes-meta-line');
    var staleEl = document.getElementById('themes-stale-line');
    var btn = document.getElementById('btn-refresh-themes');
    if(!line) return;
    if(!data || !data.ok){ line.textContent = 'Unavailable'; return; }
    var parts = [];
    if (typeof data.theme_count === 'number') parts.push('Themes: '+data.theme_count);
    if (typeof data.yaml_file_count === 'number') parts.push('YAML: '+data.yaml_file_count);
    if (data.last_export_at) parts.push('Last Export: '+data.last_export_at);
    line.textContent = (data.theme_list_exists ? 'Ready' : 'Not generated');
    if(parts.length){ meta.style.display=''; meta.textContent = parts.join(' • '); } else { meta.style.display='none'; }
    if(data.stale){ staleEl.style.display=''; staleEl.textContent='Stale: needs refresh'; }
    else { staleEl.style.display='none'; }
    // Disable refresh while a theme export phase is active (in orchestrator phases 'themes' / 'themes-fast')
    try {
      if(btn){
        if(data.phase === 'themes' || data.phase === 'themes-fast'){
          btn.disabled = true; btn.textContent='Refreshing…';
        } else {
          if(!data.running){ btn.disabled = false; btn.textContent='Refresh Themes Only'; }
        }
      }
    } catch(e){}
  }
  window.refreshThemes = function(){
    var btn = document.getElementById('btn-refresh-themes');
    if(btn) btn.disabled = true;
    fetch('/themes/refresh', { method:'POST' })
      .then(function(){ setTimeout(function(){ pollThemes(); if(btn) btn.disabled=false; }, 1200); })
      .catch(function(){ if(btn) btn.disabled=false; });
  };
  
  // Card image download functions
  function pollImageStatus(){
    fetch('/api/images/status', { cache: 'no-store' })
      .then(function(r){ return r.json(); })
      .then(function(data){
        var statusLine = document.getElementById('image-status-line');
        var statsLine = document.getElementById('image-stats-line');
        var downloadStatus = document.getElementById('image-download-status');
        var progressBar = document.getElementById('image-progress-bar');
        var progressBarInner = document.getElementById('image-progress-bar-inner');
        
        if (!statusLine) return;
        
        if (data.running) {
          // Download in progress
          var phase = data.phase || 'unknown';
          var message = data.message || 'Downloading...';
          var percentage = data.percentage || 0;
          
          statusLine.textContent = 'Download in progress';
          statusLine.style.color = '#3b82f6';
          
          if (downloadStatus) {
            downloadStatus.style.display = '';
            downloadStatus.textContent = message + ' (' + percentage + '%)';
          }
          
          if (progressBar && progressBarInner) {
            progressBar.style.display = '';
            progressBarInner.style.width = percentage + '%';
          }
        } else if (data.stats) {
          // Show cache statistics
          var stats = data.stats;
          if (stats.enabled === false) {
            statusLine.textContent = 'Image caching disabled';
            statusLine.style.color = '#94a3b8';
            if (statsLine) statsLine.style.display = 'none';
          } else {
            // Card count = use the max across sizes (each card has one image per size, so avoid double-counting)
            var cardCount = Math.max(
              (stats.small && stats.small.count) || 0,
              (stats.normal && stats.normal.count) || 0
            );
            var totalSizeMB = ((stats.small && stats.small.size_mb) || 0) + ((stats.normal && stats.normal.size_mb) || 0);
            var sizeCount = (stats.small ? 1 : 0) + (stats.normal ? 1 : 0);

            if (cardCount > 0) {
              statusLine.textContent = 'Cache exists';
              statusLine.style.color = '#34d399';
              if (statsLine) {
                statsLine.style.display = '';
                var statsText = cardCount.toLocaleString() + ' cards cached • ' + totalSizeMB.toFixed(1) + ' MB';
                // If we have last download info, append new card count
                if (data.last_download) {
                  var ld = data.last_download;
                  if (ld.stats && typeof ld.stats.downloaded === 'number') {
                    var newCards = sizeCount > 0 ? Math.round(ld.stats.downloaded / sizeCount) : ld.stats.downloaded;
                    if (newCards > 0) {
                      statsText += ' • Last run: +' + newCards.toLocaleString() + ' new cards';
                    } else {
                      statsText += ' • Last run: fully up to date';
                    }
                  } else if (ld.message) {
                    statsText += ' • ' + ld.message;
                  }
                }
                statsLine.textContent = statsText;
              }
            } else {
              statusLine.textContent = 'No cards cached';
              statusLine.style.color = '#94a3b8';
              if (statsLine) statsLine.style.display = 'none';
            }
          }
          
          // Hide download progress
          if (downloadStatus) downloadStatus.style.display = 'none';
          if (progressBar) progressBar.style.display = 'none';
        } else if (data.phase === 'error' || data.message) {
          // Previous download failed - show error and allow retry
          statusLine.textContent = 'Last download failed';
          statusLine.style.color = '#f87171';
          if (statsLine) {
            statsLine.style.display = '';
            statsLine.textContent = data.message || 'Unknown error';
          }
          if (downloadStatus) downloadStatus.style.display = 'none';
          if (progressBar) progressBar.style.display = 'none';
        } else {
          // No stats, no error - likely no download attempted yet
          statusLine.textContent = 'No cards cached';
          statusLine.style.color = '#94a3b8';
          if (statsLine) statsLine.style.display = 'none';
          if (downloadStatus) downloadStatus.style.display = 'none';
          if (progressBar) progressBar.style.display = 'none';
        }
      })
      .catch(function(){
        var statusLine = document.getElementById('image-status-line');
        if (statusLine) {
          statusLine.textContent = 'Status unavailable';
          statusLine.style.color = '#94a3b8';
        }
      });
  }
  
  window.downloadCardImages = function(){
    var btn = document.getElementById('btn-download-images');
    var statusEl = document.getElementById('image-download-status');
    
    if (!confirm('Download card images from Scryfall? This will download ~30k images (~3-6 GB) and may take 1-2 hours.')) {
      return;
    }
    
    if (btn) btn.disabled = true;
    if (statusEl) {
      statusEl.style.display = '';
      statusEl.textContent = 'Starting download...';
    }
    
    fetch('/api/images/download', { method: 'POST' })
      .then(function(r){ 
        if (!r.ok) {
          return r.json().then(function(data){ 
            throw new Error(data.message || 'Download failed'); 
          });
        }
        return r.json(); 
      })
      .then(function(data){
        if (statusEl) {
          statusEl.style.color = '#34d399';
          statusEl.textContent = '✓ ' + (data.message || 'Download started');
        }
        
        // Poll status every 2 seconds while downloading
        var pollCount = 0;
        var imagePoll = setInterval(function(){
          pollImageStatus();
          pollCount++;
          // Stop intensive polling after 2 hours (3600 polls)
          if (pollCount > 3600) clearInterval(imagePoll);
        }, 2000);
        
        setTimeout(function(){ 
          if (btn) btn.disabled = false; 
        }, 3000);
      })
      .catch(function(err){
        if (statusEl) {
          statusEl.style.color = '#f87171';
          statusEl.textContent = '✗ ' + (err.message || 'Download failed');
        }
        if (btn) btn.disabled = false;
      });
  };
  
  function rapidPoll(times, delay){
    var i = 0;
    function tick(){
      poll();
      i++;
      if (i < times) setTimeout(tick, delay);
    }
    tick();
  }
  window.downloadFromGitHub = function(){
    var btn = document.getElementById('btn-download-github');
    var statusEl = document.getElementById('download-status');
    if (btn) btn.disabled = true;
    if (statusEl) {
      statusEl.style.display = '';
      statusEl.textContent = 'Downloading from GitHub...';
    }
    
    fetch('/setup/download-github', { method: 'POST' })
      .then(function(r){ 
        if (!r.ok) throw new Error('Download failed'); 
        return r.json(); 
      })
      .then(function(data){
        if (statusEl) {
          statusEl.style.color = '#34d399';
          statusEl.textContent = '✓ ' + (data.message || 'Download complete');
        }
        // Refresh status displays
        poll();
        setTimeout(function(){ if (btn) btn.disabled = false; }, 2000);
      })
      .catch(function(err){
        if (statusEl) {
          statusEl.style.color = '#f87171';
          statusEl.textContent = '✗ Download failed: ' + (err.message || 'Unknown error');
        }
        if (btn) btn.disabled = false;
      });
  };
  window.startSetup = function(){
    var btn = document.getElementById('btn-start-setup');
    var line = document.getElementById('setup-status-line');
    var force = document.getElementById('chk-force') && document.getElementById('chk-force').checked;
    if (btn) btn.disabled = true;
    if (line) line.textContent = 'Starting setup/tagging…';
    // First try POST with JSON body
    fetch('/setup/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ force: !!force }) })
      .then(function(r){ if (!r.ok) throw new Error('POST failed'); return r.json().catch(function(){ return {}; }); })
      .then(function(){ rapidPoll(5, 600); setTimeout(function(){ window.location.href = '/setup/running?start=1' + (force ? '&force=1' : ''); }, 500); })
      .catch(function(){
        // Fallback to GET if POST fails (proxy/middleware issues)
        var url = '/setup/start' + (force ? '?force=1' : '');
        fetch(url, { method: 'GET', cache: 'no-store' })
          .then(function(){ rapidPoll(5, 600); setTimeout(function(){ window.location.href = '/setup/running?start=1' + (force ? '&force=1' : ''); }, 500); })
          .catch(function(){});
      })
      .finally(function(){ if (btn) btn.disabled = false; });
  };

  // Similarity cache status polling
  {% if similarity_enabled %}
  function pollSimilarityStatus(){
    fetch('/status/similarity', { cache: 'no-store' })
      .then(function(r){ return r.json(); })
      .then(function(data){
        var line = document.getElementById('similarity-status-line');
        var metaLine = document.getElementById('similarity-meta-line');
        var warnLine = document.getElementById('similarity-warning-line');
        if (!line) return;
        
        if (data.exists && data.valid) {
          var cardCount = data.card_count ? data.card_count.toLocaleString() : '?';
          var sizeMB = data.size_mb ? data.size_mb.toFixed(1) : '?';
          var ageDays = data.age_days !== null ? data.age_days.toFixed(1) : '?';
          
          line.textContent = 'Cache exists and is valid';
          line.style.color = '#34d399';
          
          if (metaLine) {
            metaLine.style.display = '';
            metaLine.textContent = cardCount + ' cards cached • ' + sizeMB + ' MB • ' + ageDays + ' days old';
          }
          
          if (warnLine && data.needs_refresh) {
            warnLine.style.display = '';
            warnLine.textContent = '⚠ Cache is ' + ageDays + ' days old. Consider rebuilding for fresher data.';
          } else if (warnLine) {
            warnLine.style.display = 'none';
          }
        } else if (data.exists && !data.valid) {
          line.textContent = 'Cache file is invalid or corrupted';
          line.style.color = '#f87171';
          if (metaLine) metaLine.style.display = 'none';
          if (warnLine) {
            warnLine.style.display = '';
            warnLine.textContent = '⚠ Rebuild cache to fix.';
          }
        } else {
          line.textContent = 'No cache found';
          line.style.color = '#94a3b8';
          if (metaLine) metaLine.style.display = 'none';
          if (warnLine) {
            warnLine.style.display = '';
            warnLine.textContent = 'ℹ Build cache to enable similar card features.';
          }
        }
      })
      .catch(function(){});
  }

  window.buildSimilarityCache = function(){
    var btn = document.getElementById('btn-build-similarity');
    var skipDownloadCheckbox = document.getElementById('chk-skip-download');
    if (!btn) return;
    
    var skipDownload = skipDownloadCheckbox && skipDownloadCheckbox.checked;
    var confirmMsg = skipDownload 
      ? 'Build similarity cache locally for ~30k cards? This will take approximately 15-20 minutes and uses parallel processing.'
      : 'Build similarity cache? This will first try to download a pre-built cache from GitHub (instant), or build locally if unavailable (~15-20 minutes).';
    
    if (!confirm(confirmMsg)) {
      return;
    }
    
    btn.disabled = true;
    btn.textContent = 'Building... (check terminal for progress)';
    
    var body = skipDownload ? JSON.stringify({ skip_download: true }) : '{}';
    
    fetch('/similarity/build', { 
      method: 'POST', 
      headers: { 'Content-Type': 'application/json' },
      body: body
    })
      .then(function(r){ 
        if (!r.ok) throw new Error('Build failed'); 
        return r.json(); 
      })
      .then(function(data){ 
        if (data.success) {
          btn.textContent = 'Build Started! Check terminal for progress...';
          // Poll status more frequently while building
          var pollCount = 0;
          var buildPoll = setInterval(function(){
            pollSimilarityStatus();
            pollCount++;
            // Stop intensive polling after 2 minutes, rely on normal polling
            if (pollCount > 40) clearInterval(buildPoll);
          }, 3000);
          
          setTimeout(function(){ 
            btn.textContent = 'Build Similarity Cache';
            btn.disabled = false;
          }, 8000);
        } else {
          btn.textContent = 'Build Failed: ' + (data.error || 'Unknown error');
          setTimeout(function(){ 
            btn.textContent = 'Build Similarity Cache'; 
            btn.disabled = false; 
          }, 3000);
        }
      })
      .catch(function(err){ 
        btn.textContent = 'Build Failed';
        setTimeout(function(){ 
          btn.textContent = 'Build Similarity Cache'; 
          btn.disabled = false; 
        }, 3000);
      });
  };
  
  pollSimilarityStatus();
  setInterval(pollSimilarityStatus, 10000); // Poll every 10s
  {% endif %}

  // Initialize image status polling
  pollImageStatus();
  setInterval(pollImageStatus, 10000); // Poll every 10s

  setInterval(poll, 3000);
  poll();
  pollThemes();
})();
</script>
{% endblock %}
