{% extends "base.html" %}
{% block content %}
{% set enable_ui = random_ui %}
<section id="random-modes" aria-labelledby="random-heading">
  <h2 id="random-heading">Random Modes</h2>
  {% if not enable_ui %}
    <div class="notice" role="status">Random UI is disabled. Set <code>RANDOM_UI=1</code> to enable.</div>
  {% else %}
  <style>
    .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
    .theme-tooltip{position:relative; display:inline-flex; align-items:center;}
    .theme-tooltip button.help-icon{border:none; background:transparent; color:var(--text-muted,#94a3b8); font-size:14px; cursor:help; border-radius:50%; width:20px; height:20px; line-height:20px; text-align:center; transition:color .2s ease;}
    .theme-tooltip button.help-icon:focus-visible{outline:2px solid var(--accent,#6366f1); outline-offset:2px;}
    .theme-tooltip .tooltip-panel{position:absolute; top:100%; left:50%; transform:translate(-50%,8px); background:var(--panel,#111827); color:var(--text,#f8fafc); border:1px solid var(--border,#334155); border-radius:8px; padding:10px 12px; font-size:12px; width:220px; box-shadow:0 10px 25px rgba(15,23,42,0.35); opacity:0; pointer-events:none; transition:opacity .2s ease; z-index:30;}
    .theme-tooltip[data-open="true"] .tooltip-panel{opacity:1; pointer-events:auto;}
    .theme-tooltip .tooltip-panel p{margin:0; line-height:1.4;}
    .clear-themes-btn{background:transparent; border:none; color:var(--accent,#6366f1); font-size:12px; padding:2px 8px; border-radius:6px; cursor:pointer; text-decoration:underline; transition:color .15s ease, background .15s ease;}
  .clear-themes-btn:hover{color:var(--accent-strong,#818cf8);}
  .clear-themes-btn:focus-visible{outline:2px solid var(--accent,#6366f1); outline-offset:2px;}
  .strict-toggle{display:flex; align-items:center; gap:8px; font-size:12px; color:var(--text-muted,#94a3b8);}
  </style>
  <div class="controls" role="group" aria-label="Random controls" style="display:flex; flex-direction:column; gap:12px;">
  <fieldset class="theme-section" role="group" aria-labelledby="theme-group-label" style="border:1px solid var(--border,#1f2937); border-radius:10px; padding:12px 16px; display:flex; flex-direction:column; gap:10px; min-width:320px; flex:0 0 auto;">
      <legend id="theme-group-label" style="font-size:13px; font-weight:600; letter-spacing:.4px; display:flex; align-items:center; gap:6px; justify-content:space-between; flex-wrap:wrap;">
        <span class="theme-legend-label" style="display:inline-flex; align-items:center; gap:6px;">
          Themes
          <span class="theme-tooltip" data-open="false">
            <button type="button" class="help-icon" aria-expanded="false" aria-controls="theme-tooltip-panel" aria-describedby="theme-tooltip-text">?</button>
            <span id="theme-tooltip-text" class="sr-only">Explain theme fallback order</span>
            <div id="theme-tooltip-panel" class="tooltip-panel" role="dialog" aria-modal="false">
              <p>We attempt your Primary + Secondary + Tertiary first. If that has no hits, we relax to Primary + Secondary, then Primary + Tertiary, Primary only, synergy overlap, and finally the full pool.</p>
            </div>
          </span>
        </span>
        <button type="button" id="random-clear-themes" class="clear-themes-btn" aria-describedby="theme-group-label">Clear themes</button>
      </legend>
      <div style="display:flex; flex-direction:column; gap:10px;" aria-describedby="theme-help">
        <div class="theme-row" style="display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
          <label for="random-primary-theme" class="field-label" style="min-width:110px; font-weight:600;">Primary</label>
          <div style="position:relative; flex:1 1 260px; min-width:220px;">
            <input id="random-primary-theme" name="primary_theme" type="text" placeholder="e.g. Aggro, Goblin Kindred" autocomplete="off" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-owns="primary-theme-suggest-box" aria-controls="primary-theme-suggest-box" aria-describedby="theme-help" aria-haspopup="listbox" />
            <div id="primary-theme-suggest-box" role="listbox" style="display:none; position:absolute; top:100%; left:0; right:0; background:var(--panel,#1e293b); border:1px solid var(--border,#334155); z-index:22; max-height:220px; overflow-y:auto; box-shadow:0 4px 10px rgba(0,0,0,.4); font-size:13px;">
              <!-- suggestions injected here -->
            </div>
          </div>
        </div>
        <div class="theme-row" style="display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
          <label for="random-secondary-theme" class="field-label" style="min-width:110px; font-weight:600;">Secondary <span style="font-size:11px; color:var(--text-muted,#94a3b8); font-weight:400;">(optional)</span></label>
          <div style="position:relative; flex:1 1 260px; min-width:220px;">
            <input id="random-secondary-theme" name="secondary_theme" type="text" placeholder="Optional secondary" autocomplete="off" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-owns="secondary-theme-suggest-box" aria-controls="secondary-theme-suggest-box" aria-describedby="theme-help" aria-haspopup="listbox" />
            <div id="secondary-theme-suggest-box" role="listbox" style="display:none; position:absolute; top:100%; left:0; right:0; background:var(--panel,#1e293b); border:1px solid var(--border,#334155); z-index:21; max-height:220px; overflow-y:auto; box-shadow:0 4px 10px rgba(0,0,0,.4); font-size:13px;">
              <!-- suggestions injected here -->
            </div>
          </div>
        </div>
        <div class="theme-row" style="display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
          <label for="random-tertiary-theme" class="field-label" style="min-width:110px; font-weight:600;">Tertiary <span style="font-size:11px; color:var(--text-muted,#94a3b8); font-weight:400;">(optional)</span></label>
          <div style="position:relative; flex:1 1 260px; min-width:220px;">
            <input id="random-tertiary-theme" name="tertiary_theme" type="text" placeholder="Optional tertiary" autocomplete="off" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-owns="tertiary-theme-suggest-box" aria-controls="tertiary-theme-suggest-box" aria-describedby="theme-help" aria-haspopup="listbox" />
            <div id="tertiary-theme-suggest-box" role="listbox" style="display:none; position:absolute; top:100%; left:0; right:0; background:var(--panel,#1e293b); border:1px solid var(--border,#334155); z-index:20; max-height:220px; overflow-y:auto; box-shadow:0 4px 10px rgba(0,0,0,.4); font-size:13px;">
              <!-- suggestions injected here -->
            </div>
          </div>
        </div>
      </div>
      <div class="auto-fill-toggle" style="display:flex; flex-direction:column; gap:6px; margin-top:4px;">
        <input type="hidden" id="random-auto-fill-state" name="auto_fill_enabled" value="false" />
        <input type="hidden" id="random-auto-fill-secondary-state" name="auto_fill_secondary_enabled" value="false" />
        <input type="hidden" id="random-auto-fill-tertiary-state" name="auto_fill_tertiary_enabled" value="false" />
        <div style="display:flex; align-items:flex-start; gap:12px;">
          <div style="min-width:110px; font-weight:600; margin-top:2px; display:flex; align-items:center; gap:6px;">
            <span>Auto-fill themes</span>
            <span class="theme-tooltip auto-fill-tooltip" data-open="false">
              <button type="button" class="help-icon" aria-expanded="false" aria-controls="auto-fill-tooltip-panel" aria-describedby="auto-fill-tooltip-text">?</button>
              <span id="auto-fill-tooltip-text" class="sr-only">Auto-fill only fills empty slots; manual entries always take priority.</span>
              <div id="auto-fill-tooltip-panel" class="tooltip-panel" role="dialog" aria-modal="false">
                <p>We only auto-fill the theme slots you leave empty. Manual entries always take priority.</p>
              </div>
            </span>
          </div>
          <div style="display:flex; flex-direction:column; gap:4px;">
            <div style="display:flex; align-items:center; gap:16px; flex-wrap:wrap;">
              <label for="random-auto-fill-secondary" style="display:inline-flex; align-items:center; gap:6px; font-size:12px;">
                <input id="random-auto-fill-secondary" type="checkbox" aria-describedby="auto-fill-tooltip-text" />
                <span>Fill Secondary</span>
              </label>
              <label for="random-auto-fill-tertiary" style="display:inline-flex; align-items:center; gap:6px; font-size:12px;">
                <input id="random-auto-fill-tertiary" type="checkbox" aria-describedby="auto-fill-tooltip-text" />
                <span>Fill Tertiary</span>
              </label>
            </div>
          </div>
        </div>
      </div>
      <div class="strict-toggle" style="margin-top:4px;">
        <input type="hidden" id="random-strict-theme-hidden" name="strict_theme_match" value="{{ 'true' if strict_theme_match|default(false) else 'false' }}" />
        <label for="random-strict-theme" style="display:inline-flex; align-items:center; gap:6px; cursor:pointer;">
          <input id="random-strict-theme" type="checkbox" aria-describedby="random-strict-theme-help" {% if strict_theme_match|default(false) %}checked{% endif %} />
          <span>Require exact theme match (no fallbacks)</span>
        </label>
        <span id="random-strict-theme-help" class="sr-only">When enabled, themes must match exactly. No fallback themes will be used.</span>
      </div>
      <input type="hidden" id="random-legacy-theme" name="theme" value="" />
    </fieldset>
    <div class="action-row" style="display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
      {% if show_diagnostics %}
        <div class="diagnostics" style="display:flex; align-items:center; gap:6px; flex-wrap:wrap; font-size:11px;">
          <label for="rand-attempts" style="font-size:11px;">Attempts</label>
          <input id="rand-attempts" name="attempts" type="number" min="1" max="25" value="{{ random_max_attempts }}" style="width:60px; font-size:11px;" title="Override max attempts" />
          <label for="rand-timeout" style="font-size:11px;">Timeout(ms)</label>
          <input id="rand-timeout" name="timeout_ms" type="number" min="100" max="15000" step="100" value="{{ random_timeout_ms }}" style="width:80px; font-size:11px;" title="Override generation timeout in milliseconds" />
        </div>
      {% endif %}
      <div class="button-row" style="display:flex; align-items:center; gap:8px; flex-wrap:wrap;">
        <!-- Added hx-trigger with delay to provide debounce without custom JS recursion -->
  <button id="btn-surprise" class="btn" hx-post="/hx/random_reroll" hx-vals='{"mode":"surprise"}' hx-include="#random-primary-theme,#random-secondary-theme,#random-tertiary-theme,#random-legacy-theme,#random-auto-fill-state,#random-auto-fill-secondary-state,#random-auto-fill-tertiary-state,#random-strict-theme-hidden{% if show_diagnostics %},#rand-attempts,#rand-timeout{% endif %}" hx-target="#random-result" hx-swap="outerHTML" hx-trigger="click" hx-disabled-elt="#btn-surprise,#btn-reroll" aria-label="Surprise me">Surprise me</button>
  <button id="btn-reroll" class="btn" hx-post="/hx/random_reroll" hx-vals='{"mode":"reroll_same_commander"}' hx-include="#current-seed,#current-commander,#current-primary-theme,#current-secondary-theme,#current-tertiary-theme,#current-resolved-themes,#current-auto-fill-enabled,#current-auto-fill-secondary-enabled,#current-auto-fill-tertiary-enabled,#current-strict-theme-match,#random-primary-theme,#random-secondary-theme,#random-tertiary-theme,#random-legacy-theme,#random-auto-fill-state,#random-auto-fill-secondary-state,#random-auto-fill-tertiary-state,#random-strict-theme-hidden{% if show_diagnostics %},#rand-attempts,#rand-timeout{% endif %}" hx-target="#random-result" hx-swap="outerHTML" hx-trigger="click" hx-disabled-elt="#btn-surprise,#btn-reroll" aria-label="Reroll" disabled>Reroll</button>
        <span id="spinner" role="status" aria-live="polite" style="display:none;">Loading…</span>
      </div>
    </div>
  </div>
  <div id="rate-limit-banner" role="status" aria-live="polite" style="display:none; margin-top:8px; padding:6px 8px; border:1px solid #cc9900; background:#fff8e1; color:#5f4200; border-radius:4px;">
    Too many requests. Please wait…
  </div>
  <div id="random-area" style="margin-top:12px;">
    <div id="random-result" class="random-result empty" aria-live="polite">Click “Surprise me” to build a deck.</div>
    <div id="recent-seeds" style="margin-top:10px; font-size:12px; color:var(--text-muted);">
      <button id="btn-load-seeds" class="btn" type="button" style="font-size:11px; padding:2px 6px;">Show Recent Seeds</button>
      <button id="btn-metrics" class="btn" type="button" style="font-size:11px; padding:2px 6px;" title="Download NDJSON metrics" {% if not random_modes %}disabled{% endif %}>Metrics</button>
      <span id="seed-list" style="margin-left:6px;"></span>
      <div id="favorite-seeds" style="margin-top:6px;"></div>
    </div>
  </div>
  <script>
    (function(){
      // Typeahead: debounce + /themes/suggest shared across inputs
      var legacyInput = document.getElementById('random-legacy-theme');
      var AUTO_FILL_KEY = 'random_auto_fill_enabled';
      var AUTO_FILL_SECONDARY_KEY = 'random_auto_fill_secondary_enabled';
      var AUTO_FILL_TERTIARY_KEY = 'random_auto_fill_tertiary_enabled';
      var THEME_KEY = 'random_last_primary_theme';
      var LEGACY_KEY = 'random_last_theme';
      var SECONDARY_KEY = 'random_last_secondary_theme';
      var TERTIARY_KEY = 'random_last_tertiary_theme';
      var themeInputs = {
        primary: {
          input: document.getElementById('random-primary-theme'),
          list: document.getElementById('primary-theme-suggest-box'),
          syncLegacy: true,
        },
        secondary: {
          input: document.getElementById('random-secondary-theme'),
          list: document.getElementById('secondary-theme-suggest-box'),
        },
        tertiary: {
          input: document.getElementById('random-tertiary-theme'),
          list: document.getElementById('tertiary-theme-suggest-box'),
        }
      };
      var primaryInput = themeInputs.primary.input;
      var secondaryInput = themeInputs.secondary.input;
      var tertiaryInput = themeInputs.tertiary.input;
    var clearThemesButton = document.getElementById('random-clear-themes');
      var autoFillHidden = document.getElementById('random-auto-fill-state');
      var autoFillSecondaryHidden = document.getElementById('random-auto-fill-secondary-state');
      var autoFillTertiaryHidden = document.getElementById('random-auto-fill-tertiary-state');
      var autoFillSecondaryInput = document.getElementById('random-auto-fill-secondary');
      var autoFillTertiaryInput = document.getElementById('random-auto-fill-tertiary');
    var strictHidden = document.getElementById('random-strict-theme-hidden');
    var strictCheckbox = document.getElementById('random-strict-theme');
    var STRICT_KEY = 'random_strict_theme_match';
      var debounceTimers = new Map();
      var cache = new Map(); // simple in-memory cache of q -> [names]
      var REROLL_CACHE_STORAGE_KEY = 'random_theme_suggest_cache_v1';
      var throttleRaw = "{{ random_reroll_throttle_ms | default(350) }}";
      var REROLL_THROTTLE_MS = parseInt(throttleRaw, 10);
      if (isNaN(REROLL_THROTTLE_MS) || REROLL_THROTTLE_MS < 0) {
        REROLL_THROTTLE_MS = 0;
      }
  var throttleTimerId = null;
  var throttleUnlockAt = 0;
  var lastRandomRequestAt = 0;
      var rateLimitIntervalId = null;
      var activeIndex = -1; // keyboard highlight
      var activeKey = null;
      try {
        var persistedCache = sessionStorage.getItem(REROLL_CACHE_STORAGE_KEY);
        if (persistedCache) {
          var parsedCache = JSON.parse(persistedCache);
          if (Array.isArray(parsedCache)) {
            parsedCache.forEach(function(entry) {
              if (!entry || typeof entry.q !== 'string') {
                return;
              }
              var key = entry.q.toLowerCase();
              var results = Array.isArray(entry.results) ? entry.results : [];
              cache.set(key, results);
            });
          }
        }
      } catch (e) { /* ignore storage failures */ }

      function enforceTertiaryRequirement(){
        if(autoFillTertiaryInput && autoFillSecondaryInput){
          if(autoFillTertiaryInput.checked && !autoFillSecondaryInput.checked){
            autoFillSecondaryInput.checked = true;
          }
        }
        if(autoFillSecondaryInput && autoFillTertiaryInput){
          var secChecked = !!autoFillSecondaryInput.checked;
          autoFillTertiaryInput.disabled = !secChecked;
          if(!secChecked && autoFillTertiaryInput.checked){
            autoFillTertiaryInput.checked = false;
          }
        } else if(autoFillTertiaryInput){
          autoFillTertiaryInput.disabled = false;
        }
      }

      function currentAutoFillFlags(){
        enforceTertiaryRequirement();
        var secondaryChecked = !!(autoFillSecondaryInput && autoFillSecondaryInput.checked);
        var tertiaryChecked = !!(secondaryChecked && autoFillTertiaryInput && autoFillTertiaryInput.checked);
        return {
          secondary: secondaryChecked,
          tertiary: tertiaryChecked,
        };
      }

      function syncAutoFillHidden(){
        var flags = currentAutoFillFlags();
        if(autoFillSecondaryHidden){ autoFillSecondaryHidden.value = flags.secondary ? 'true' : 'false'; }
        if(autoFillTertiaryHidden){ autoFillTertiaryHidden.value = flags.tertiary ? 'true' : 'false'; }
        if(autoFillHidden){ autoFillHidden.value = (flags.secondary || flags.tertiary) ? 'true' : 'false'; }
      }

      function persistAutoFillPreferences(){
        try{
          var flags = currentAutoFillFlags();
          localStorage.setItem(AUTO_FILL_SECONDARY_KEY, flags.secondary ? '1' : '0');
          localStorage.setItem(AUTO_FILL_TERTIARY_KEY, flags.tertiary ? '1' : '0');
          localStorage.setItem(AUTO_FILL_KEY, (flags.secondary || flags.tertiary) ? '1' : '0');
        }catch(e){ /* ignore */ }
      }

      function syncStrictHidden(){
        if(strictHidden){
          var checked = !!(strictCheckbox && strictCheckbox.checked);
          strictHidden.value = checked ? 'true' : 'false';
        }
      }

      function persistStrictPreference(){
        if(!strictCheckbox) return;
        try{
          localStorage.setItem(STRICT_KEY, strictCheckbox.checked ? '1' : '0');
        }catch(e){ /* ignore */ }
      }

      function hideAllLists(){
        Object.keys(themeInputs).forEach(function(key){
          var cfg = themeInputs[key];
          if(cfg.list){ cfg.list.style.display='none'; }
          if(cfg.input){
            cfg.input.setAttribute('aria-expanded','false');
            cfg.input.removeAttribute('aria-activedescendant');
          }
        });
        activeIndex = -1;
        activeKey = null;
      }
      function syncLegacy(){
        if(!legacyInput) return;
        legacyInput.value = primaryInput && primaryInput.value ? primaryInput.value : '';
      }
      function clearThemeInputs(){
        if(primaryInput){ primaryInput.value = ''; }
        if(secondaryInput){ secondaryInput.value = ''; }
        if(tertiaryInput){ tertiaryInput.value = ''; }
        hideAllLists();
        syncLegacy();
        try{
          localStorage.setItem(THEME_KEY, '');
          localStorage.setItem(LEGACY_KEY, '');
          localStorage.setItem(SECONDARY_KEY, '');
          localStorage.setItem(TERTIARY_KEY, '');
        }catch(e){ /* ignore */ }
        if(primaryInput){ primaryInput.dispatchEvent(new Event('change')); }
        if(secondaryInput){ secondaryInput.dispatchEvent(new Event('change')); }
        if(tertiaryInput){ tertiaryInput.dispatchEvent(new Event('change')); }
        if(primaryInput){ primaryInput.focus(); }
      }
      function collectThemePayload(extra){
        syncAutoFillHidden();
        syncStrictHidden();
        var payload = Object.assign({}, extra || {});
        var primaryVal = primaryInput && primaryInput.value ? primaryInput.value.trim() : null;
        var secondaryVal = secondaryInput && secondaryInput.value ? secondaryInput.value.trim() : null;
        var tertiaryVal = tertiaryInput && tertiaryInput.value ? tertiaryInput.value.trim() : null;
        payload.theme = primaryVal;
        payload.primary_theme = primaryVal;
        payload.secondary_theme = secondaryVal || null;
        payload.tertiary_theme = tertiaryVal || null;
        var flags = currentAutoFillFlags();
        if(!autoFillSecondaryInput && autoFillSecondaryHidden){
          var secVal = (autoFillSecondaryHidden.value || '').toLowerCase();
          flags.secondary = (secVal === 'true' || secVal === '1' || secVal === 'on');
        }
        if(!autoFillTertiaryInput && autoFillTertiaryHidden){
          var terVal = (autoFillTertiaryHidden.value || '').toLowerCase();
          flags.tertiary = (terVal === 'true' || terVal === '1' || terVal === 'on');
        }
        if(flags.tertiary && !flags.secondary){
          flags.secondary = true;
        }
        if(!flags.secondary){
          flags.tertiary = false;
        }
        payload.auto_fill_secondary_enabled = flags.secondary;
        payload.auto_fill_tertiary_enabled = flags.tertiary;
        payload.auto_fill_enabled = flags.secondary || flags.tertiary;
        var strictFlag = false;
        if(strictCheckbox){
          strictFlag = !!strictCheckbox.checked;
        } else if(strictHidden){
          var strictVal = (strictHidden.value || '').toLowerCase();
          strictFlag = (strictVal === 'true' || strictVal === '1' || strictVal === 'on');
        }
        payload.strict_theme_match = strictFlag;
        return payload;
      }

      async function submitRandomPayload(payload){
        if(!payload) payload = {};
        if(!canTriggerRandomRequest()){
          return;
        }
        markRandomRequestStarted();
        var spinner = document.getElementById('spinner');
        if(spinner){ spinner.style.display = 'inline-block'; }
        try{
          var res = await fetch('/hx/random_reroll', {
            method:'POST',
            headers:{'Content-Type':'application/json'},
            body: JSON.stringify(payload),
            credentials: 'same-origin'
          });
          if(res.status === 429){
            var ra = res.headers ? res.headers.get('Retry-After') : null;
            var secs = ra ? parseInt(ra, 10) : null;
            if(window.toast){ try{ toast('Too many requests'); }catch(e){} }
            if(secs && !isNaN(secs)){ applyRetryAfterSeconds(secs); }
            else { showRateLimitBanner(null, 'Too many requests'); }
            return;
          }
          if(!res.ok){
            if(window.toast){ try{ toast('Failed to load random build'); }catch(e){} }
            return;
          }
          var html = await res.text();
          var target = document.getElementById('random-result');
          if(target){ target.outerHTML = html; }
          hideRateLimitBanner();
        }catch(err){
          if(window.toast){ try{ toast('Error contacting server'); }catch(e){} }
        }finally{
          if(spinner){ spinner.style.display = 'none'; }
          enableRandomButtonsIfReady();
        }
      }
      function highlight(text, q){
        try{ if(!q) return text; var i=text.toLowerCase().indexOf(q.toLowerCase()); if(i===-1) return text; return text.substring(0,i)+'<mark style="background:#4f46e5; color:#fff; padding:0 2px; border-radius:2px;">'+text.substring(i,i+q.length)+'</mark>'+text.substring(i+q.length);}catch(e){return text;}}
      function renderList(key, items, q){
        var cfg = themeInputs[key];
        if(!cfg || !cfg.list){ return; }
        var list = cfg.list;
        list.innerHTML='';
        activeIndex = -1;
        if(!items || !items.length){
          list.style.display='none';
          if(cfg.input){
            cfg.input.setAttribute('aria-expanded','false');
            cfg.input.removeAttribute('aria-activedescendant');
          }
          activeKey = null;
          return;
        }
        items.slice(0,50).forEach(function(it, idx){
          var div=document.createElement('div');
          div.setAttribute('role','option');
          div.setAttribute('data-value', it);
          var optionId = key + '-theme-option-' + idx;
          div.id = optionId;
          div.innerHTML=highlight(it, q);
          div.style.cssText='padding:4px 8px; cursor:pointer;';
          div.addEventListener('mouseenter', function(){ setActive(idx); });
          div.addEventListener('mousedown', function(ev){ ev.preventDefault(); pick(key, it); });
          list.appendChild(div);
        });
        list.style.display='block';
        if(cfg.input){
          cfg.input.setAttribute('aria-expanded','true');
          cfg.input.removeAttribute('aria-activedescendant');
        }
        activeKey = key;
      }
      function currentList(){
        if(!activeKey) return null;
        var cfg = themeInputs[activeKey];
        return cfg ? cfg.list : null;
      }
      function setActive(idx){
        var list = currentList();
        if(!list) return;
        var children=[...list.children];
        children.forEach(function(c,i){ c.style.background = (i===idx) ? 'rgba(99,102,241,0.35)' : 'transparent'; });
        var cfg = activeKey ? themeInputs[activeKey] : null;
        if(cfg && cfg.input){
          if(idx >= 0 && children[idx]){
            cfg.input.setAttribute('aria-activedescendant', children[idx].id || '');
          } else {
            cfg.input.removeAttribute('aria-activedescendant');
          }
        }
        activeIndex = idx;
      }
      function move(delta){
        var list = currentList();
        if(!list || list.style.display==='none'){ return; }
        var children=[...list.children]; if(!children.length) return;
        var next = activeIndex + delta; if(next < 0) next = children.length -1; if(next >= children.length) next = 0;
        setActive(next);
        var el = children[next]; if(el && el.scrollIntoView){ el.scrollIntoView({block:'nearest'}); }
      }
      function pick(key, value){
        var cfg = themeInputs[key];
        if(!cfg || !cfg.input) return;
        cfg.input.value = value;
        if(key === 'primary'){ syncLegacy(); }
        hideAllLists();
        cfg.input.dispatchEvent(new Event('change'));
        cfg.input.removeAttribute('aria-activedescendant');
        cfg.input.focus();
      }
      function persistSuggestCache(){
        try{
          if(typeof sessionStorage === 'undefined'){ return; }
          var entries = [];
          cache.forEach(function(results, q){
            entries.push({ q: q, results: Array.isArray(results) ? results.slice(0, 40) : [] });
          });
          if(entries.length > 75){
            entries = entries.slice(entries.length - 75);
          }
          sessionStorage.setItem(REROLL_CACHE_STORAGE_KEY, JSON.stringify(entries));
        }catch(e){ /* ignore */ }
      }

      async function fetchSuggest(q, key){
        try{
          var cachedKey = (q || '').toLowerCase();
          var u = '/themes/api/suggest' + (q? ('?q=' + encodeURIComponent(q)) : '');
          if(cache.has(cachedKey)) { renderList(key, cache.get(cachedKey), q); return; }
          var r = await fetch(u);
          if(r.status === 429){
            var ra = r.headers.get('Retry-After');
            var secs = ra ? parseInt(ra, 10) : null;
            var msg = 'You are being rate limited';
            if(secs && !isNaN(secs)) msg += ' — retry in ' + secs + 's';
            if(window.toast) { toast(msg); } else { console.warn(msg); }
            showRateLimitBanner(secs);
            hideAllLists();
            return;
          }
          if(!r.ok){ renderList(key, [], q); return; }
          var j = await r.json();
          var items = (j && j.themes) || [];
          cache.set(cachedKey, items);
          // cap cache size to 60
          if(cache.size > 60){
            var firstKey = cache.keys().next().value; cache.delete(firstKey);
          }
          persistSuggestCache();
          renderList(key, items, q);
        }catch(e){ /* no-op */ }
      }
      function attachInput(key){
        var cfg = themeInputs[key];
        if(!cfg || !cfg.input) return;
        cfg.input.addEventListener('input', function(){
          if(key === 'primary'){ syncLegacy(); }
          var q = cfg.input.value || '';
          var existingTimer = debounceTimers.get(key);
          if(existingTimer) clearTimeout(existingTimer);
          if(!q || q.length < 2){ hideAllLists(); return; }
          var timerId = setTimeout(function(){ fetchSuggest(q, key); }, 150);
          debounceTimers.set(key, timerId);
        });
        cfg.input.addEventListener('focus', function(){
          var q = cfg.input.value || '';
          if(q && q.length >= 2){ fetchSuggest(q, key); }
        });
        cfg.input.addEventListener('keydown', function(ev){
          if(ev.key === 'ArrowDown'){ ev.preventDefault(); move(1); }
          else if(ev.key === 'ArrowUp'){ ev.preventDefault(); move(-1); }
          else if(ev.key === 'Enter'){
            var list = currentList();
            if(list && activeKey && activeIndex >= 0 && list.children[activeIndex]){
              ev.preventDefault();
              pick(activeKey, list.children[activeIndex].getAttribute('data-value'));
            } else {
              hideAllLists();
            }
          }
          else if(ev.key === 'Escape'){ hideAllLists(); }
        });
      }
      Object.keys(themeInputs).forEach(attachInput);
      document.addEventListener('click', function(ev){
        var target = ev.target;
        var insideInput = Object.keys(themeInputs).some(function(key){ var cfg = themeInputs[key]; return cfg.input && cfg.input === target; });
        var insideList = Object.keys(themeInputs).some(function(key){ var cfg = themeInputs[key]; return cfg.list && cfg.list.contains(target); });
        if(!insideInput && !insideList){ hideAllLists(); }
      });
      if(clearThemesButton){
        clearThemesButton.addEventListener('click', function(){
          clearThemeInputs();
          if(window.toast){ try{ toast('Themes cleared'); }catch(e){ /* ignore */ } }
        });
      }
      if(primaryInput){ primaryInput.addEventListener('change', syncLegacy); syncLegacy(); }
      function disableRandomButtons(){
        var btn1 = document.getElementById('btn-surprise');
        var btn2 = document.getElementById('btn-reroll');
        if(btn1) btn1.disabled = true;
        if(btn2) btn2.disabled = true;
      }

      function enableRandomButtonsIfReady(){
        var btn1 = document.getElementById('btn-surprise');
        var btn2 = document.getElementById('btn-reroll');
        var now = Date.now();
        if(REROLL_THROTTLE_MS > 0 && now < throttleUnlockAt){
          scheduleThrottleUnlock();
          return;
        }
        if(throttleTimerId){
          clearTimeout(throttleTimerId);
          throttleTimerId = null;
        }
        if(btn1) btn1.disabled = false;
        if(btn2){
          btn2.disabled = !document.getElementById('current-seed');
        }
        hideRateLimitBanner();
      }

      function scheduleThrottleUnlock(){
        if(REROLL_THROTTLE_MS <= 0){ return; }
        if(throttleTimerId){ clearTimeout(throttleTimerId); }
        var delay = Math.max(0, throttleUnlockAt - Date.now());
        if(delay === 0){
          enableRandomButtonsIfReady();
          return;
        }
        throttleTimerId = setTimeout(function(){ enableRandomButtonsIfReady(); }, delay);
      }

      function showRateLimitBanner(seconds, message){
        var b = document.getElementById('rate-limit-banner');
        if(!b){ return; }
        var secs = (typeof seconds === 'number' && !isNaN(seconds) && seconds > 0) ? Math.floor(seconds) : null;
        var base = message || 'Please wait before trying again';
        var update = function(){
          if(secs !== null){ b.textContent = base + ' — try again in ' + secs + 's'; }
          else { b.textContent = base + ' — please try again shortly'; }
        };
        update();
        b.style.display = 'block';
        disableRandomButtons();
        if(rateLimitIntervalId){
          clearInterval(rateLimitIntervalId);
          rateLimitIntervalId = null;
        }
        if(secs !== null){
          rateLimitIntervalId = setInterval(function(){
            secs -= 1; update();
            if(secs <= 0){
              if(rateLimitIntervalId){
                clearInterval(rateLimitIntervalId);
                rateLimitIntervalId = null;
              }
              hideRateLimitBanner();
              enableRandomButtonsIfReady();
            }
          }, 1000);
        }
      }

      function hideRateLimitBanner(){
        var b = document.getElementById('rate-limit-banner');
        if(b){ b.style.display = 'none'; }
        if(rateLimitIntervalId){
          clearInterval(rateLimitIntervalId);
          rateLimitIntervalId = null;
        }
      }

      function remainingThrottleMs(){
        if(REROLL_THROTTLE_MS <= 0) return 0;
        return Math.max(0, throttleUnlockAt - Date.now());
      }

      function canTriggerRandomRequest(){
        if(REROLL_THROTTLE_MS <= 0) return true;
        var remaining = remainingThrottleMs();
        if(remaining <= 0){ return true; }
        showRateLimitBanner(Math.ceil(remaining / 1000), 'Hold up — reroll throttle active');
        scheduleThrottleUnlock();
        return false;
      }

      function markRandomRequestStarted(){
        lastRandomRequestAt = Date.now();
        if(REROLL_THROTTLE_MS <= 0){ return; }
        throttleUnlockAt = lastRandomRequestAt + REROLL_THROTTLE_MS;
        disableRandomButtons();
        scheduleThrottleUnlock();
      }

      function applyRetryAfterSeconds(seconds){
        if(!seconds || isNaN(seconds) || seconds <= 0){ return; }
        throttleUnlockAt = Date.now() + (seconds * 1000);
        disableRandomButtons();
        scheduleThrottleUnlock();
        showRateLimitBanner(seconds, 'Too many requests');
      }

      document.addEventListener('htmx:configRequest', function(ev){
        var detail = ev && ev.detail;
        if(!detail) return;
        var path = detail.path || '';
        if(typeof path !== 'string') return;
        if(path.indexOf('/random_reroll') === -1){ return; }
        if(!canTriggerRandomRequest()){
          ev.preventDefault();
          return;
        }
        markRandomRequestStarted();
      });

      document.addEventListener('htmx:afterRequest', function(){
        enableRandomButtonsIfReady();
      });
      // (No configRequest hook needed; using hx-vals + hx-include for simple form-style submission.)
      // Enable reroll once a result exists
      document.addEventListener('htmx:afterSwap', function(ev){
        if (ev && ev.detail && ev.detail.target && ev.detail.target.id === 'random-result'){
          var rr = document.getElementById('btn-reroll');
          if(rr){
            if(remainingThrottleMs() > 0){
              rr.disabled = true;
              scheduleThrottleUnlock();
            } else {
              rr.disabled = false;
            }
          }
          var hiddenAuto = document.getElementById('current-auto-fill-enabled');
          var aggregated = null;
          if(hiddenAuto){
            var aggVal = (hiddenAuto.value || '').toLowerCase();
            if(aggVal){ aggregated = (aggVal === 'true' || aggVal === '1' || aggVal === 'on'); }
          }
          var hiddenSecondary = document.getElementById('current-auto-fill-secondary-enabled');
          var hiddenTertiary = document.getElementById('current-auto-fill-tertiary-enabled');
          if(autoFillSecondaryInput){
            var secNext = null;
            if(hiddenSecondary){
              var secVal = (hiddenSecondary.value || '').toLowerCase();
              secNext = (secVal === 'true' || secVal === '1' || secVal === 'on');
            } else if(aggregated !== null){
              secNext = aggregated;
            }
            if(secNext !== null){ autoFillSecondaryInput.checked = !!secNext; }
          }
          if(autoFillTertiaryInput){
            var terNext = null;
            if(hiddenTertiary){
              var terVal = (hiddenTertiary.value || '').toLowerCase();
              terNext = (terVal === 'true' || terVal === '1' || terVal === 'on');
            } else if(aggregated !== null){
              terNext = aggregated;
            }
            if(terNext !== null){ autoFillTertiaryInput.checked = !!terNext; }
          }
          enforceTertiaryRequirement();
          var currentStrict = document.getElementById('current-strict-theme-match');
          if(strictCheckbox && currentStrict){
            var strictVal = (currentStrict.value || '').toLowerCase();
            strictCheckbox.checked = (strictVal === 'true' || strictVal === '1' || strictVal === 'on');
          } else if(strictHidden && currentStrict){
            var hiddenVal = (currentStrict.value || '').toLowerCase();
            strictHidden.value = (hiddenVal === 'true' || hiddenVal === '1' || hiddenVal === 'on') ? 'true' : 'false';
          }
          syncStrictHidden();
          persistStrictPreference();
          syncAutoFillHidden();
          persistAutoFillPreferences();
          hideRateLimitBanner();
          // Refresh recent seeds asynchronously
          fetch('/api/random/seeds').then(r=>r.json()).then(function(j){
            try{
              if(!j || !j.seeds) return; var span=document.getElementById('seed-list'); if(!span) return;
              span.textContent = j.seeds.join(', ');
            }catch(e){}
          }).catch(function(){});
        }
      });
      // Simple spinner hooks
      document.addEventListener('htmx:beforeRequest', function(){ var s=document.getElementById('spinner'); if(s) s.style.display='inline-block'; });
      document.addEventListener('htmx:afterRequest', function(){ var s=document.getElementById('spinner'); if(s) s.style.display='none'; });
      // HTMX-friendly rate limit message on 429 + countdown banner
      document.addEventListener('htmx:afterOnLoad', function(ev){
        try{
          var xhr = ev && ev.detail && ev.detail.xhr; if(!xhr) return;
          if(xhr.status === 429){
            var ra = xhr.getResponseHeader('Retry-After');
            var secs = ra ? parseInt(ra, 10) : null;
            var msg = 'Too many requests';
            if(secs && !isNaN(secs)) msg += ' — try again in ' + secs + 's';
            if(window.toast) { toast(msg); } else { alert(msg); }
            if(secs && !isNaN(secs)) applyRetryAfterSeconds(secs);
            else showRateLimitBanner(null, 'Too many requests');
          }
        }catch(e){/* no-op */}
      });

      function favoriteButton(seed, favorites){
        var isFav = favorites.includes(seed);
        var b=document.createElement('button');
        b.type='button';
        b.textContent = isFav ? '★' : '☆';
        b.title = isFav ? 'Remove from favorites' : 'Add to favorites';
        b.style.cssText='font-size:12px; margin-left:2px; padding:0 4px; line-height:1;';
        b.addEventListener('click', function(ev){
          ev.stopPropagation();
          fetch('/api/random/seed_favorite', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({seed: seed})})
            .then(r=>r.json()).then(function(){
              // refresh seeds display
              loadSeeds(true);
            }).catch(()=>{});
        });
        return b;
      }
      function renderFavorites(favorites){
        var container=document.getElementById('favorite-seeds'); if(!container) return;
        if(!favorites || !favorites.length){ container.textContent=''; return; }
        container.innerHTML='<span style="margin-right:4px;">Favorites:</span>';
        favorites.forEach(function(s){
          var btn=document.createElement('button'); btn.type='button'; btn.className='btn'; btn.textContent=s; btn.style.cssText='font-size:10px; margin-right:4px; padding:2px 5px;';
          btn.addEventListener('click', function(){
            var payload = collectThemePayload({ seed: s-1 });
            submitRandomPayload(payload);
          });
          container.appendChild(btn);
        });
      }
      function renderSeedList(seeds, favorites){
        var span=document.getElementById('seed-list'); if(!span) return;
        if(!seeds || !seeds.length){ span.textContent='(none yet)'; return; }
        span.innerHTML='';
        seeds.slice().forEach(function(s){
          var b=document.createElement('button');
          b.type='button';
            b.textContent=s;
            b.className='btn seed-btn';
            b.style.cssText='font-size:10px; margin-right:4px; padding:2px 5px;';
            b.setAttribute('aria-label','Rebuild using seed '+s);
            b.addEventListener('click', function(){
              // Post to reroll endpoint but treat as explicit seed build
              var payload = collectThemePayload({ seed: s-1 });
              submitRandomPayload(payload);
            });
            span.appendChild(b);
            span.appendChild(favoriteButton(s, favorites || []));
        });
      }
      function loadSeeds(refreshFavs){
        fetch('/api/random/seeds').then(r=>r.json()).then(function(j){
          if(!j){ renderSeedList([]); return; }
          renderSeedList(j.seeds || [], j.favorites || []);
          if(refreshFavs) renderFavorites(j.favorites || []);
        }).catch(function(){ var span=document.getElementById('seed-list'); if(span) span.textContent='(error)'; });
      }

      // Manual load seeds button
      var btnSeeds = document.getElementById('btn-load-seeds');
      if(btnSeeds){ btnSeeds.addEventListener('click', function(){ loadSeeds(true); }); }
      var btnMetrics = document.getElementById('btn-metrics');
      if(btnMetrics){
        btnMetrics.addEventListener('click', function(){
          fetch('/status/random_metrics_ndjson').then(r=>r.text()).then(function(t){
            try{ var blob=new Blob([t], {type:'application/x-ndjson'}); var url=URL.createObjectURL(blob); var a=document.createElement('a'); a.href=url; a.download='random_metrics.ndjson'; document.body.appendChild(a); a.click(); setTimeout(function(){ URL.revokeObjectURL(url); a.remove(); }, 1000);}catch(e){ console.error(e); }
          });
        });
      }

      // Persist last used theme in localStorage
      try {
        var THEME_KEY='random_last_primary_theme';
        var LEGACY_KEY='random_last_theme';
        var SECONDARY_KEY='random_last_secondary_theme';
        var TERTIARY_KEY='random_last_tertiary_theme';
        if(primaryInput){
          var prev = localStorage.getItem(THEME_KEY) || localStorage.getItem(LEGACY_KEY);
          if(prev && !primaryInput.value){ primaryInput.value = prev; }
          primaryInput.addEventListener('change', function(){
            localStorage.setItem(THEME_KEY, primaryInput.value || '');
            localStorage.setItem(LEGACY_KEY, primaryInput.value || '');
            syncLegacy();
          });
          syncLegacy();
        }
        if(secondaryInput){
          var prevSecondary = localStorage.getItem(SECONDARY_KEY);
          if(prevSecondary && !secondaryInput.value){ secondaryInput.value = prevSecondary; }
          secondaryInput.addEventListener('change', function(){
            localStorage.setItem(SECONDARY_KEY, secondaryInput.value || '');
          });
        }
        if(tertiaryInput){
          var prevTertiary = localStorage.getItem(TERTIARY_KEY);
          if(prevTertiary && !tertiaryInput.value){ tertiaryInput.value = prevTertiary; }
          tertiaryInput.addEventListener('change', function(){
            localStorage.setItem(TERTIARY_KEY, tertiaryInput.value || '');
          });
        }
        var legacyAutoFill = null;
        try { legacyAutoFill = localStorage.getItem(AUTO_FILL_KEY); } catch(e){ legacyAutoFill = null; }
        function restoreAutoFillCheckbox(input, storedValue){
          if(!input) return;
          if(storedValue !== null){
            input.checked = (storedValue === '1' || storedValue === 'true' || storedValue === 'on');
          }
          input.addEventListener('change', function(){
            enforceTertiaryRequirement();
            syncAutoFillHidden();
            persistAutoFillPreferences();
          });
        }
        var storedSecondary = null;
        try { storedSecondary = localStorage.getItem(AUTO_FILL_SECONDARY_KEY); } catch(e){ storedSecondary = null; }
        if(storedSecondary === null){ storedSecondary = legacyAutoFill; }
        restoreAutoFillCheckbox(autoFillSecondaryInput, storedSecondary);

        var storedTertiary = null;
        try { storedTertiary = localStorage.getItem(AUTO_FILL_TERTIARY_KEY); } catch(e){ storedTertiary = null; }
        if(storedTertiary === null){ storedTertiary = legacyAutoFill; }
        restoreAutoFillCheckbox(autoFillTertiaryInput, storedTertiary);

        enforceTertiaryRequirement();
        syncAutoFillHidden();
        persistAutoFillPreferences();

        if(strictCheckbox){
          var storedStrict = null;
          try { storedStrict = localStorage.getItem(STRICT_KEY); } catch(e){ storedStrict = null; }
          if(storedStrict !== null){
            strictCheckbox.checked = (storedStrict === '1' || storedStrict === 'true' || storedStrict === 'on');
          }
          syncStrictHidden();
          strictCheckbox.addEventListener('change', function(){
            syncStrictHidden();
            persistStrictPreference();
          });
          persistStrictPreference();
        } else {
          syncStrictHidden();
        }
  } catch(e) { /* ignore */ }
  syncStrictHidden();

      (function(){
        var tooltipWrappers = document.querySelectorAll('.theme-tooltip');
        if(!tooltipWrappers.length) return;
        tooltipWrappers.forEach(function(tooltipWrapper){
          var button = tooltipWrapper.querySelector('button.help-icon');
          var panel = tooltipWrapper.querySelector('.tooltip-panel');
          if(!button || !panel) return;
          function setOpen(state){
            tooltipWrapper.dataset.open = state ? 'true' : 'false';
            button.setAttribute('aria-expanded', state ? 'true' : 'false');
          }
          function handleDocumentClick(ev){
            if(!tooltipWrapper.contains(ev.target)){ setOpen(false); }
          }
          button.addEventListener('click', function(){
            var isOpen = tooltipWrapper.dataset.open === 'true';
            setOpen(!isOpen);
            if(!isOpen){ panel.focus({preventScroll:true}); }
          });
          button.addEventListener('keypress', function(ev){
            if(ev.key === 'Enter' || ev.key === ' '){ ev.preventDefault(); button.click(); }
          });
          tooltipWrapper.addEventListener('mouseenter', function(){ setOpen(true); });
          tooltipWrapper.addEventListener('mouseleave', function(){ setOpen(false); });
          button.addEventListener('focus', function(){ setOpen(true); });
          button.addEventListener('blur', function(){
            setTimeout(function(){
              if(!tooltipWrapper.contains(document.activeElement)){ setOpen(false); }
            }, 0);
          });
          panel.setAttribute('tabindex','-1');
          panel.addEventListener('keydown', function(ev){ if(ev.key === 'Escape'){ setOpen(false); button.focus(); } });
          document.addEventListener('click', handleDocumentClick);
        });
      })();
    })();
  </script>
  {% endif %}
</section>
{% endblock %}
