// Admin scripts
(function ($) {
  // Auto-dismiss warmup completion notices after 3 seconds
  $(document).ready(function () {
    // --- THEME HANDLING ---
    // Check local storage or default to 'dark' (Cyber Mamba default)
    var savedTheme = localStorage.getItem('mamba_theme') || 'dark';
    $('body').attr('data-mamba-theme', savedTheme);

    // Toggle Handler
    $('#mamba-theme-toggle').on('click', function () {
      var current = $('body').attr('data-mamba-theme');
      var next = current === 'dark' ? 'light' : 'dark';
      $('body').attr('data-mamba-theme', next);
      localStorage.setItem('mamba_theme', next);
    });

    // Permanent Dismissal: Handle 'x' click on Warmup Warning Notices
    $(document).on('click', '.notice-warning.is-dismissible .notice-dismiss', function () {
      var $notice = $(this).closest('.notice');
      // Check if this is a Mamba warmup notice (contains log link or specific text)
      if ($notice.find('.mamba-view-warmup-log').length > 0 || $notice.text().indexOf('Background warmup completed') !== -1) {
        $.post(ajaxurl, {
          action: 'mamba_clear_warmup_notification',
          nonce: (typeof MambaAdmin !== 'undefined' ? MambaAdmin.nonce : '')
        });
      }
    });
    // Check for caching setup modal trigger in URL
    var urlParams = new URLSearchParams(window.location.search);
    if (urlParams.get('show_caching_modal') === '1') {
      // Remove the parameter from URL without page reload
      var newUrl = new URL(window.location);
      newUrl.searchParams.delete('show_caching_modal');
      window.history.replaceState({}, '', newUrl);

      // Show the modal after a short delay to let the success notice be visible
      setTimeout(function () {
        showCachingSetupModal();
      }, 2000); // 2 seconds delay to let the success notice be visible
    }

    $('.notice.notice-success.is-dismissible').each(function () {
      var $notice = $(this);
      var message = $notice.text();

      // Check if this is a warmup completion notice
      if (message.indexOf('Background warmup completed successfully') !== -1 ||
        message.indexOf('Background warmup completed with') !== -1) {

        setTimeout(function () {
          if ($notice.length && $notice.is(':visible')) {
            // Clear the notification from database to prevent reappearance
            $.ajax({
              url: ajaxurl,
              method: 'POST',
              data: {
                action: 'mamba_clear_warmup_notification',
                nonce: typeof MambaAdmin !== 'undefined' ? MambaAdmin.nonce : ''
              }
            }).fail(function () {
              // Silently fail if AJAX doesn't work
            });

            // Trigger an immediate cache-counts refresh so counts update without reload
            try { $(document).trigger('mamba:refreshCacheCounts'); } catch (e) { }

            $notice.fadeOut(500, function () {
              $(this).remove();
            });
          }
        }, 3000); // 3 seconds delay
      }
    });

    // Dashboard live stats polling (updates key metrics every 60s)
    try {
      var $dashboard = $('.mamba-metrics-dashboard');
      if ($dashboard.length && typeof MambaAdmin !== 'undefined' && MambaAdmin.warmupEndpoint) {
        // Build stats endpoint robustly and prefer same-origin to avoid CORS/cookie issues
        var statsEndpoint = MambaAdmin.warmupEndpoint.replace(/\/warmup\/?$/, '/stats');
        try {
          var u = new URL(statsEndpoint, window.location.origin);
          // If REST URL is cross-origin for any reason, fall back to relative path
          if (u.origin !== window.location.origin) {
            statsEndpoint = u.pathname + u.search;
          } else {
            // Use absolute same-origin URL
            statsEndpoint = u.toString();
          }
        } catch (e) {
          // If URL parsing fails, default to relative REST path
          if (typeof window.wpApiSettings !== 'undefined' && window.wpApiSettings.root) {
            statsEndpoint = window.wpApiSettings.root.replace(/\/$/, '') + '/mamba-wc/v1/stats';
          } else {
            statsEndpoint = '/wp-json/mamba-wc/v1/stats';
          }
        }
        try { console.debug('[Mamba] Stats polling initialized:', statsEndpoint); } catch (e) { }
        // Heuristic for cron lag: if stats signature doesn't change across several polls
        var lastStatsSignature = null;
        var stalePolls = 0; // count consecutive polls with no stat changes

        function computeAdjustedRate(byType) {
          try {
            var totalHits = 0, totalMisses = 0;
            Object.keys(byType || {}).forEach(function (key) {
              if (key === 'store_api') return; // exclude store_api like PHP template
              var m = byType[key] || {};
              totalHits += (parseInt(m.hits, 10) || 0);
              totalMisses += (parseInt(m.misses, 10) || 0);
            });
            var denom = totalHits + totalMisses;
            return denom > 0 ? Math.round((totalHits / denom) * 100) : 0;
          } catch (e) { return 0; }
        }

        function updateEfficiency(res) {
          var byType = res.by_type || {};
          var score = computeAdjustedRate(byType);
          var $card = $dashboard.find('.mamba-metric-card.efficiency-score');
          if (!$card.length) return;

          // Determine class and status labels (mirror PHP thresholds)
          var scoreClass = 'poor', scoreStatus = 'Needs Work', benchmark = '';
          if (score >= 90) { scoreClass = 'excellent'; scoreStatus = 'Excellent'; benchmark = 'Top 10% of sites'; }
          else if (score >= 75) { scoreClass = 'good'; scoreStatus = 'Good'; benchmark = 'Above average'; }
          else if (score >= 50) { scoreClass = 'average'; scoreStatus = 'Average'; benchmark = 'Industry average'; }
          else { scoreClass = 'poor'; scoreStatus = 'Needs Work'; benchmark = 'Below average'; }

          // Update badge
          var $badge = $card.find('.score-badge');
          if ($badge.length) {
            $badge.text(String(score));
            $badge.removeClass('excellent good average poor').addClass(scoreClass);
          }

          // Update status value
          var $value = $card.find('.metric-value');
          if ($value.length) { $value.text(scoreStatus); }

          // Update trend text (benchmark)
          var $trend = $card.find('.metric-trend');
          if ($trend.length) {
            $trend.removeClass('excellent good average poor neutral').addClass(scoreClass);
            // Keep the icon span, update trailing text node
            var $textHolder = $trend.find('.dashicons').length ? $trend : $trend;
            // Replace entire text after icon for simplicity
            var iconHtml = $trend.find('.dashicons').prop('outerHTML') || '';
            $trend.html(iconHtml + ' ' + benchmark);
          }
        }

        function updatePageLoadTime(res) {
          var avgGen = parseInt(res.avg_gen_ms, 10) || 0;
          if (avgGen > 2000) avgGen = 2000; // mirror PHP cap
          var $card = $dashboard.find('.mamba-metric-card').filter(function () {
            return $(this).find('.metric-title').text().trim() === 'Page Load Time';
          }).first();
          if (!$card.length) return;

          var $val = $card.find('.metric-value');
          if ($val.length) {
            if (avgGen > 0) $val.text(avgGen + 'ms'); else $val.text('No data yet');
          }

          // Update trend status/class based on thresholds
          var status = 'No Data', klass = 'neutral';
          if (avgGen > 0) {
            if (avgGen < 200) { status = 'Excellent'; klass = 'positive'; }
            else if (avgGen < 500) { status = 'Good'; klass = 'neutral'; }
            else if (avgGen < 1000) { status = 'Average'; klass = 'neutral'; }
            else { status = 'Needs Improvement'; klass = 'negative'; }
          }
          var $trend = $card.find('.metric-trend');
          if ($trend.length) {
            $trend.removeClass('positive neutral negative').addClass(klass);
            var iconHtml = $trend.find('.dashicons').prop('outerHTML') || '';
            $trend.html(iconHtml + ' ' + status);
          }
        }

        function updateTypeCard(label, metrics) {
          var selector = '.mamba-metric-card .metric-title';
          var $title = $dashboard.find(selector).filter(function () {
            return $(this).text().trim() === (label + ' Performance');
          }).first();
          if (!$title.length) return;
          var $card = $title.closest('.mamba-metric-card');
          var h = parseInt((metrics && metrics.hits) || 0, 10);
          var m = parseInt((metrics && metrics.misses) || 0, 10);
          var total = h + m;
          var r = total > 0 ? Math.round((h * 100) / total) : 0;
          var statusClass = r >= 80 ? 'positive' : (r >= 50 ? 'neutral' : 'negative');
          var displayText = (label === 'Store API' && total === 0) ? 'No usage yet' : (h + ' hits, ' + m + ' misses');

          var $val = $card.find('.metric-value');
          if ($val.length) $val.text(r + '%');

          var $trend = $card.find('.metric-trend');
          if ($trend.length) {
            $trend.removeClass('positive neutral negative').addClass(statusClass);
            var iconHtml = $trend.find('.dashicons').prop('outerHTML') || '';
            $trend.html(iconHtml + ' ' + displayText);
          }
        }

        function updateDashboard(res) {
          try {
            updateEfficiency(res);
            updatePageLoadTime(res);
            var bt = res.by_type || {};
            updateTypeCard('Products', bt.product || {});
            updateTypeCard('Categories', bt.category || {});
            updateTypeCard('Shop', bt.shop || {});
            updateTypeCard('Store API', bt.store_api || {});
            updateLastUpdated(res);
            detectCronLag(res);
          } catch (e) { /* no-op */ }
        }

        function updateLastUpdated(res) {
          try {
            var ts = parseInt(res.timestamp, 10);
            if (!ts || isNaN(ts)) return; // require server timestamp
            var d = new Date(ts * 1000);
            var timeStr = d.toLocaleTimeString ? d.toLocaleTimeString() : d.toUTCString();
            var $note = $dashboard.find('.mamba-metric-card.efficiency-score .metric-note');
            if (!$note.length) return;
            var $label = $note.find('.mamba-last-updated');
            if (!$label.length) {
              // Append a dedicated node without altering existing content
              $label = $('<small class="mamba-last-updated"></small>');
              // Insert on a new line but keep existing notes untouched
              $note.append('<br>').append($label);
            }
            $label.text('Last updated: ' + timeStr);
          } catch (e) { /* no-op */ }
        }

        function pollStats() {
          $.ajax({
            url: statsEndpoint,
            method: 'GET',
            xhrFields: { withCredentials: true }, // ensure cookies are sent on same-origin and allowed cross-origin
            beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce || ''); },
          }).done(function (res) {
            try { console.debug('[Mamba] Stats response:', res); } catch (e) { }
            if (res) updateDashboard(res);
          }).fail(function (xhr) {
            try { console.warn('[Mamba] Stats poll failed', xhr && xhr.status, xhr && xhr.responseText); } catch (e) { }
          }).always(function () {
            setTimeout(pollStats, 60000); // 60s
          });
        }

        // Kick off after a brief delay to let initial render settle
        setTimeout(pollStats, 5000);
      }
    } catch (e) { /* defensive */ }

    // Cache counts polling and live updates for Cached Products/Categories and Cache Size
    try {
      var $dashboard2 = $('.mamba-metrics-dashboard');
      if ($dashboard2.length && typeof MambaAdmin !== 'undefined' && MambaAdmin.warmupEndpoint) {
        // Build counts endpoint similar to stats endpoint (prefer same-origin)
        var countsEndpoint = MambaAdmin.warmupEndpoint.replace(/\/warmup\/?$/, '/cache-counts');
        try {
          var cu = new URL(countsEndpoint, window.location.origin);
          if (cu.origin !== window.location.origin) {
            countsEndpoint = cu.pathname + cu.search;
          } else {
            countsEndpoint = cu.toString();
          }
        } catch (e) {
          if (typeof window.wpApiSettings !== 'undefined' && window.wpApiSettings.root) {
            countsEndpoint = window.wpApiSettings.root.replace(/\/$/, '') + '/mamba-wc/v1/cache-counts';
          } else {
            countsEndpoint = '/wp-json/mamba-wc/v1/cache-counts';
          }
        }

        function updateCacheCards(payload) {
          if (!payload || !payload.counts) return;
          var counts = payload.counts || {};
          var sizeBytes = parseInt(payload.size_bytes || 0, 10) || 0;
          var sizeMB = sizeBytes > 0 ? Math.round((sizeBytes / (1024 * 1024)) * 10) / 10 : 0;

          function updateCardByTitle(titleText, value) {
            var $title = $dashboard2.find('.mamba-metric-card .metric-title').filter(function () {
              return $(this).text().trim() === titleText;
            }).first();
            if (!$title.length) return;
            var $card = $title.closest('.mamba-metric-card');
            var $val = $card.find('.metric-value');
            if ($val.length) {
              try {
                $val.text((value != null ? Number(value).toLocaleString() : '0'));
              } catch (e) {
                $val.text(String(value != null ? value : 0));
              }
            }
            return $card;
          }

          // Update Cached Products and Cached Categories
          updateCardByTitle('Cached Products', counts.products || 0);
          updateCardByTitle('Cached Categories', counts.categories || 0);

          // Update Cache Size card value and files count trend
          var $sizeTitle = $dashboard2.find('.mamba-metric-card .metric-title').filter(function () {
            return $(this).text().trim() === 'Cache Size';
          }).first();
          if ($sizeTitle.length) {
            var $sizeCard = $sizeTitle.closest('.mamba-metric-card');
            var $sizeVal = $sizeCard.find('.metric-value');
            if ($sizeVal.length) {
              $sizeVal.text(sizeMB + ' MB');
            }
            var totalFiles = (counts.products || 0) + (counts.categories || 0) + (counts.shop || 0) + (counts.homepage || 0) + (counts.other || 0);
            var $trend = $sizeCard.find('.metric-trend');
            if ($trend.length) {
              var iconHtml = $trend.find('.dashicons').prop('outerHTML') || '';
              $trend.html(iconHtml + ' ' + (totalFiles.toLocaleString ? totalFiles.toLocaleString() : totalFiles) + ' files cached');
            }
          }
        }

        function pollCounts() {
          $.ajax({
            url: countsEndpoint,
            method: 'GET',
            xhrFields: { withCredentials: true },
            beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce || ''); },
          }).done(function (res) {
            try { console.debug('[Mamba] Cache counts response:', res); } catch (e) { }
            updateCacheCards(res);
          }).always(function () { setTimeout(pollCounts, 60000); });
        }

        // Initial slight delay so the page renders first
        setTimeout(pollCounts, 7000);

        // Listen for explicit refresh requests (e.g., after purge/warmup completes)
        $(document).on('mamba:refreshCacheCounts', function () {
          // One-off immediate refresh
          $.ajax({
            url: countsEndpoint,
            method: 'GET',
            xhrFields: { withCredentials: true },
            beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce || ''); },
          }).done(function (res) { updateCacheCards(res); });
        });
      }
    } catch (e) { /* defensive */ }

    // Intercept header Purge form to avoid redirect and use REST instead
    try {
      $(document).on('submit', '.mamba-header-actions form', function (e) {
        var $form = $(this);
        // Only intercept the special purge form in header (hidden mamba_action=purge)
        if ($form.find('input[name="mamba_action"][value="purge"]').length) {
          e.preventDefault();
          var $btn = $form.find('button[type="submit"]');
          var originalHtml = $btn.html();
          var purgeSuccess = false;
          var startedAt = Date.now();
          var minPurgingMs = 900;     // ensure spinner state visible ~0.9s
          var successHoldMs = 2000;   // keep "Purged ✓" visible ~2s on the button
          var $actions = $form.closest('.mamba-header-actions');
          var $inline = $actions.find('.mamba-inline-status');
          if (!$inline.length) {
            $inline = $(`<div class="mamba-inline-status" aria-live="polite"></div>`);
            $actions.append($inline);
          } else {
            $inline.stop(true, true).show();
          }
          function setInlineStatus(text, state) {
            var color = (state === 'success') ? '#16a34a' : (state === 'warning' ? '#d97706' : '#E68057');
            var iconHtml = (state === 'success') ? '<span class="dashicons dashicons-yes-alt" style="color:#16a34a"></span>'
              : (state === 'warning' ? '<span class="dashicons dashicons-warning" style="color:#d97706"></span>'
                : '<span class="spinner is-active" style="margin:0;vertical-align:-2px;transform:scale(0.9);"></span>');
            $inline.attr('data-state', state).css('border-left-color', color);
            $inline.html(iconHtml + '<span>' + text + '</span>');
          }

          setInlineStatus('Purging…', 'busy');
          // Busy state + accessible indicator
          $btn.prop('disabled', true).addClass('is-busy').attr('aria-busy', 'true');
          try {
            $btn.data('orig-html', originalHtml).html('<span class="spinner is-active" style="margin:0 6px 0 0;vertical-align:-2px;"></span> Purging…');
          } catch (e) {
            $btn.text('Purging…');
          }
          // Build purge endpoint from warmupEndpoint
          var purgeEndpoint = (typeof MambaAdmin !== 'undefined' && MambaAdmin.warmupEndpoint)
            ? MambaAdmin.warmupEndpoint.replace(/\/warmup\/?$/, '/purge')
            : ((typeof window.wpApiSettings !== 'undefined' && window.wpApiSettings.root)
              ? window.wpApiSettings.root.replace(/\/$/, '') + '/mamba-wc/v1/purge'
              : '/wp-json/mamba-wc/v1/purge');
          $.ajax({
            url: purgeEndpoint,
            method: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({ scope: 'all' }),
            xhrFields: { withCredentials: true },
            beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', (typeof MambaAdmin !== 'undefined' ? MambaAdmin.nonce : '')); },
          }).done(function (res) {
            try { console.debug('[Mamba] Purge success', res); } catch (e) { }
            purgeSuccess = true;
            // Enforce a minimum visible time for the purging state
            var delay = Math.max(0, minPurgingMs - (Date.now() - startedAt));
            setTimeout(function () {
              // Trigger immediate counts refresh
              $(document).trigger('mamba:refreshCacheCounts');
              // Toast
              if (typeof MambaAdmin !== 'undefined' && MambaAdmin.showToast) {
                MambaAdmin.showToast('Cache purged successfully.', 'success');
              }
              // Button success state then restore after successHoldMs
              try { $btn.html('Purged ✓'); } catch (e) { $btn.text('Purged ✓'); }
              setTimeout(function () {
                var orig = $btn.data('orig-html') || originalHtml;
                $btn.prop('disabled', false).removeClass('is-busy').removeAttr('aria-busy').html(orig);
              }, successHoldMs);

              // Inline status update
              setInlineStatus('Cache purged. Scheduling background warmup…', 'busy');

              // Schedule background warmup to rebuild cache (best-effort)
              var bgEndpoint = (typeof MambaAdmin !== 'undefined' && MambaAdmin.warmupEndpoint)
                ? MambaAdmin.warmupEndpoint.replace('/warmup', '/background-warmup')
                : ((typeof window.wpApiSettings !== 'undefined' && window.wpApiSettings.root)
                  ? window.wpApiSettings.root.replace(/\/$/, '') + '/mamba-wc/v1/background-warmup'
                  : '/wp-json/mamba-wc/v1/background-warmup');
              $.ajax({
                url: bgEndpoint,
                method: 'POST',
                xhrFields: { withCredentials: true },
                beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', (typeof MambaAdmin !== 'undefined' ? MambaAdmin.nonce : '')); },
              }).done(function (r) {
                if (r && r.success) {
                  if (typeof MambaAdmin !== 'undefined' && MambaAdmin.showToast) {
                    MambaAdmin.showToast('Background warmup scheduled. You\'ll be notified when it completes.', 'success');
                  }
                  setInlineStatus('Background warmup scheduled.', 'success');
                } else if (r && r.error) {
                  var errorMsg = r.message || r.error;
                  if (r.error === 'premium_feature') {
                    errorMsg = 'Warmup requires Pro license';
                  }
                  if (typeof MambaAdmin !== 'undefined' && MambaAdmin.showToast) {
                    MambaAdmin.showToast('Warmup not scheduled: ' + errorMsg, 'warning');
                  }
                  setInlineStatus('Purged. ' + errorMsg + '.', 'warning');
                }
              }).fail(function (xhr) {
                var errorMsg = 'Warmup could not be scheduled';
                try {
                  var r = JSON.parse(xhr.responseText);
                  if (r && r.error === 'premium_feature') {
                    errorMsg = 'Warmup requires Pro license';
                  } else if (r && r.message) {
                    errorMsg = r.message;
                  }
                } catch (e) { }
                try { console.warn('[Mamba] Background warmup schedule failed', xhr && xhr.status); } catch (e) { }
                setInlineStatus('Purged. ' + errorMsg + '.', 'warning');
              }).always(function () {
                // Auto-hide inline status after a slightly longer delay so users can read it
                setTimeout(function () { $inline.fadeOut(300, function () { $(this).remove(); }); }, 7000);
              });
            }, delay);
          }).fail(function (xhr) {
            try { console.warn('[Mamba] Purge failed', xhr && xhr.status, xhr && xhr.responseText); } catch (e) { }
            // Fallback: if REST fails, submit normally
            try { $form.off('submit'); $form.trigger('submit'); return; } catch (e) { }
          }).always(function () {
            // On failure, restore immediately; on success, restoration handled in success path
            if (!purgeSuccess) {
              $btn.prop('disabled', false).removeClass('is-busy').removeAttr('aria-busy').html(originalHtml);
            }
          });
        }
      });
    } catch (e) { /* defensive */ }
  });

  // --- Helpers for cron lag indicator ---
  function detectCronLag(res) {
    try {
      if (typeof MambaAdmin !== 'undefined' && MambaAdmin.cacheEnabled === false) {
        // If cache is disabled, don't show lag indicator
        updateCronLagIndicator(false);
        // reset internal state
        if (window.mambaCronLagState) window.mambaCronLagState.stalePolls = 0;
        return;
      }

      // Build a lightweight signature of stats to detect change
      var byType = res.by_type || {};
      var byTypeSum = 0;
      try {
        Object.keys(byType).forEach(function (k) {
          var m = byType[k] || {};
          byTypeSum += (parseInt(m.hits, 10) || 0) + (parseInt(m.misses, 10) || 0);
        });
      } catch (e) { }
      var sig = String(parseInt(res.hits || 0, 10)) + '|' + String(parseInt(res.misses || 0, 10)) + '|' + String(byTypeSum);

      // Persist minimal state on window to avoid scope issues
      if (!window.mambaCronLagState) window.mambaCronLagState = { last: null, stalePolls: 0 };
      var state = window.mambaCronLagState;
      if (state.last !== null && state.last === sig) {
        state.stalePolls += 1;
      } else {
        state.stalePolls = 0;
      }
      state.last = sig;

      // Show indicator if unchanged across >= 3 polls (~3 minutes)
      var show = state.stalePolls >= 3;
      updateCronLagIndicator(show);
    } catch (e) { /* no-op */ }
  }

  function updateCronLagIndicator(show) {
    try {
      var $dashboard = jQuery('.mamba-metrics-dashboard');
      if (!$dashboard.length) return;
      var $note = $dashboard.find('.mamba-metric-card.efficiency-score .metric-note');
      if (!$note.length) return;
      var $label = $note.find('.mamba-cron-lag');
      if (!show) {
        if ($label.length) {
          // Also remove the separator <br> we add when showing the indicator to avoid accumulating breaks
          var $prev = $label.prev();
          if ($prev && $prev.is('br')) { $prev.remove(); }
          $label.remove();
        }
        return;
      }
      if (!$label.length) {
        $label = jQuery('<small class="mamba-cron-lag"></small>');
        $note.append('<br>').append($label);
      }
      $label.text('Data may be delayed (WP-Cron not running?)');
    } catch (e) { /* no-op */ }
  }

  $(document).on('click', '[data-mamba-warmup]', function (e) {
    e.preventDefault();
    var $btn = $(this);
    // If caching engine disabled, prompt
    if (typeof MambaAdmin !== 'undefined' && MambaAdmin.cacheEnabled === false) {
      alert('Enable the caching engine first in Caching → Page Cache.');
      return;
    }
    $btn.prop('disabled', true).addClass('is-busy');

    // Enhanced modal with modern progress UI and error reporting
    var $modal = $('<div class="mamba-modal mamba-warmup-modal">\
      <div class="mamba-modal-overlay"></div>\
      <div class="mamba-modal-content warmup-content">\
        <div class="mamba-modal-header">\
          <h3><span class="dashicons dashicons-update"></span> Cache Warmup</h3>\
          <button class="mamba-modal-close">×</button>\
        </div>\
        <div class="mamba-modal-body">\
          <div class="warmup-loading">\
            <div class="loading-spinner"></div>\
            <p>Scheduling warmup…</p>\
          </div>\
          <div class="warmup-progress" style="display:none;">\
            <div class="progress-header">\
              <div class="progress-ring">\
                <svg width="64" height="64" viewBox="0 0 64 64">\
                  <circle class="progress-ring-bg" cx="32" cy="32" r="28" stroke-width="3" fill="none"/>\
                  <circle class="progress-ring-fill" cx="32" cy="32" r="28" stroke-width="3" fill="none" stroke-dasharray="176" stroke-dashoffset="176"/>\
                </svg>\
                <div class="progress-text">0%</div>\
              </div>\
              <div class="progress-info">\
                <h4>Warmup in Progress</h4>\
                <p class="progress-subtitle">Processing <span class="current-count">0</span> of <span class="total-count">0</span> URLs</p>\
              </div>\
            </div>\
            <div class="warmup-stats">\
              <div class="stat-item">\
                <span class="stat-label">Success</span>\
                <span class="stat-value success-count">0</span>\
              </div>\
              <div class="stat-item">\
                <span class="stat-label">Failed</span>\
                <span class="stat-value failed-count">0</span>\
              </div>\
              <div class="stat-item">\
                <span class="stat-label">Speed</span>\
                <span class="stat-value speed-rate">0/min</span>\
              </div>\
              <div class="stat-item">\
                <span class="stat-label">ETA</span>\
                <span class="stat-value eta-time">-</span>\
              </div>\
            </div>\
            <div class="current-url-section">\
              <div class="url-info">\
                <span class="url-label">Currently Processing:</span>\
                <span class="url-text">-</span>\
              </div>\
              <div class="device-variants">\
                <span class="variant desktop">Desktop ⏳</span>\
                <span class="variant mobile">Mobile ⏳</span>\
              </div>\
            </div>\
            <div class="queue-section">\
              <h5>Next in Queue</h5>\
              <div class="queue-list">\
                <div class="queue-item">-</div>\
                <div class="queue-item">-</div>\
                <div class="queue-item">-</div>\
              </div>\
            </div>\
            <div class="recent-section">\
              <h5>Recently Completed</h5>\
              <div class="recent-list">\
                <div class="recent-item">No completions yet</div>\
              </div>\
            </div>\
            <div class="warmup-actions">\
              <button class="button pause-btn" style="display:none;">⏸ Pause</button>\
              <button class="button cancel-btn">Cancel</button>\
              <button class="button minimize-btn">Minimize</button>\
              <button class="button background-btn">Run in Background</button>\
            </div>\
          </div>\
          <div class="warmup-results" style="display:none;">\
            <div class="results-summary">\
              <h4>Warmup Complete</h4>\
              <p>Success: <span class="final-success">0</span> URLs | Failed: <span class="final-failed">0</span> URLs</p>\
            </div>\
            <div class="error-details" style="display:none;">\
              <h5>Failed URLs (<span class="error-count">0</span>)</h5>\
              <div class="error-list">\
                <!-- Error items will be populated here -->\
              </div>\
            </div>\
            <div class="results-actions">\
              <button class="button retry-btn">Retry Failed URLs</button>\
              <button class="button export-btn">Export Error Report</button>\
              <button class="button close-btn">Close</button>\
            </div>\
          </div>\
        </div>\
      </div>\
    </div>');

    $('body').addClass('mamba-modal-open').append($modal);

    // Close modal handlers
    $modal.on('click', '.mamba-modal-close, .mamba-modal-overlay', function () {
      closeModal();
    });

    // Close button handler
    $modal.on('click', '.close-btn', function () {
      closeModal();
    });

    // Keyboard shortcuts
    $(document).on('keydown.warmup', function (e) {
      if (e.key === 'Escape') closeModal();
    });

    var startTime = Date.now();
    var recentCompletions = [];
    var isPaused = false;
    var pollInterval;
    var isBackgroundMode = false;

    function closeModal() {
      $('body').removeClass('mamba-modal-open');
      $modal.remove();
      $btn.prop('disabled', false).removeClass('is-busy');
      $(document).off('keydown.warmup');
      if (pollInterval) clearTimeout(pollInterval);
    }

    // Start warmup
    $.ajax({
      url: MambaAdmin.warmupEndpoint,
      method: 'POST',
      beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce); },
    }).done(function () {
      $modal.find('.warmup-loading').hide();
      $modal.find('.warmup-progress').show();
      pollWarmup();
    }).fail(function (xhr) {
      var msg = 'Failed to schedule warmup.';
      var redirectUrl = null;
      var isPremiumError = false;

      try {
        var r = JSON.parse(xhr.responseText);
        if (r && r.error === 'cache_disabled') {
          msg = r.message || 'Enable the caching engine first in Caching → Page Cache.';
          redirectUrl = (typeof MambaAdmin !== 'undefined' && MambaAdmin.adminUrl ? MambaAdmin.adminUrl : '/wp-admin/') + 'admin.php?page=mamba&tab=caching';
        } else if (r && r.error === 'premium_feature') {
          msg = r.message || 'Cache Warmup is a premium feature. Please upgrade to unlock.';
          isPremiumError = true;
        } else if (r && r.error === 'job_already_running') {
          msg = 'A warmup job is already running. Please wait for it to complete.';
        } else if (r && r.message) {
          msg = r.message;
        } else if (r && r.error) {
          msg = 'Error: ' + r.error;
        }
      } catch (e) {
        if (xhr.status === 401) {
          msg = 'Authentication failed. Please refresh the page and try again.';
        } else if (xhr.status === 402) {
          msg = 'Cache Warmup is a premium feature. Please upgrade to unlock.';
          isPremiumError = true;
        } else if (xhr.status === 403) {
          msg = 'Permission denied. You need administrator privileges.';
        } else if (xhr.status === 0) {
          msg = 'Network error. Please check your connection and try again.';
        }
      }

      // Re-enable button
      $btn.prop('disabled', false).removeClass('is-busy');

      // Build appropriate modal content based on error type
      var modalContent = '';
      if (isPremiumError) {
        modalContent = '<div class="mamba-premium-notice">' +
          '<div class="premium-icon"><span class="dashicons dashicons-lock"></span></div>' +
          '<h4>Premium Feature</h4>' +
          '<p>' + msg + '</p>' +
          '<div class="premium-actions">' +
          '<a href="' + (typeof MambaAdmin !== 'undefined' && MambaAdmin.adminUrl ? MambaAdmin.adminUrl : '/wp-admin/') + 'admin.php?page=mamba-pricing" class="button button-primary"><span>Upgrade Now</span></a>' +
          '<button class="button mamba-modal-close"><span>Close</span></button>' +
          '</div></div>';
      } else {
        modalContent = '<div class="notice notice-error" style="margin:0;"><p>' + msg + '</p></div>';
      }
      
      $modal.find('.mamba-modal-body').html(modalContent);

      // Show toast notification
      if (typeof MambaAdmin !== 'undefined' && MambaAdmin.showToast) {
        MambaAdmin.showToast('Warmup: ' + msg, isPremiumError ? 'warning' : 'error');
      }

      // Deep link to settings if cache is disabled
      if (redirectUrl) {
        setTimeout(function () {
          if (confirm('Would you like to go to the Caching settings now?')) {
            window.location.href = redirectUrl;
          }
        }, 1000);
      }
    });

    function pollWarmup() {
      if (isPaused) return;

      $.ajax({
        url: MambaAdmin.warmupEndpoint.replace('/warmup', '/warmup-status'),
        method: 'GET',
        beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce); },
      }).done(function (res) {
        if (!res || res.status === 'idle') {
          return done('Idle');
        }

        updateProgress(res);

        if (res.status === 'done' || res.status === 'cancelled') {
          return done(res.status);
        }

        pollInterval = setTimeout(pollWarmup, 2000);
      }).fail(function () {
        pollInterval = setTimeout(pollWarmup, 3000);
      });
    }

    function updateProgress(res) {
      var total = res.total || 0;
      var queued = (res.queued && res.queued.length) ? res.queued.length : 0;
      var success = res.success || 0;
      var failed = res.failed || 0;
      var processed = success + failed;
      var pct = total ? Math.min(100, Math.round((processed / total) * 100)) : 0;
      var currentUrl = res.current_url || '';

      // Update progress ring
      var circumference = 2 * Math.PI * 28;
      var offset = circumference - (pct / 100) * circumference;
      $('.progress-ring-fill').css('stroke-dashoffset', offset);
      $('.progress-text').text(pct + '%');

      // Update counts
      $('.current-count').text(processed);
      $('.total-count').text(total);
      $('.success-count').text(success);
      $('.failed-count').text(failed);

      // Update speed and ETA
      var elapsed = (Date.now() - startTime) / 1000 / 60; // minutes
      var speed = elapsed > 0 ? Math.round(processed / elapsed) : 0;
      $('.speed-rate').text(speed + '/min');

      var remaining = queued;
      var eta = speed > 0 ? Math.round(remaining / speed) : 0;
      $('.eta-time').text(eta > 0 ? eta + 'm' : '-');

      // Update current URL
      if (currentUrl) {
        $('.url-text').text(currentUrl);
        // Simulate device variant progress (in real implementation, this would come from backend)
        setTimeout(function () {
          $('.variant.desktop').text('Desktop ✓');
        }, 1000);
        setTimeout(function () {
          $('.variant.mobile').text('Mobile ✓');
        }, 2000);
      }

      // Update queue preview
      if (res.queued && res.queued.length > 0) {
        var queueItems = res.queued.slice(0, 3);
        $('.queue-list').empty();
        queueItems.forEach(function (item) {
          var url = typeof item === 'object' ? item.url : item;
          $('.queue-list').append('<div class="queue-item">' + url + '</div>');
        });
      }

      // Track recent completions
      if (currentUrl && !recentCompletions.includes(currentUrl)) {
        recentCompletions.unshift(currentUrl);
        if (recentCompletions.length > 5) recentCompletions.pop();

        $('.recent-list').empty();
        recentCompletions.forEach(function (url) {
          $('.recent-list').append('<div class="recent-item success">' + url + ' ✓</div>');
        });
      }
    }

    // Pause/Resume functionality
    $modal.on('click', '.pause-btn', function () {
      isPaused = !isPaused;
      if (isPaused) {
        $(this).text('▶ Resume').addClass('resume');
        $('.progress-ring-fill').addClass('paused');
      } else {
        $(this).text('⏸ Pause').removeClass('resume');
        $('.progress-ring-fill').removeClass('paused');
        pollWarmup();
      }
    });

    // Cancel functionality
    $modal.on('click', '.cancel-btn', function () {
      $.ajax({
        url: MambaAdmin.warmupEndpoint.replace('/warmup', '/warmup-cancel'),
        method: 'POST',
        beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce); }
      });
    });

    // Minimize functionality
    $modal.on('click', '.minimize-btn', function () {
      $modal.addClass('minimized');
      // Show notification
      showNotification('Warmup running in background', 'info');
    });

    // Background processing
    $modal.on('click', '.background-btn', function () {
      var $btn = $(this);
      $btn.prop('disabled', true).text('Scheduling...');

      $.ajax({
        url: MambaAdmin.warmupEndpoint.replace('/warmup', '/background-warmup'),
        method: 'POST',
        beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce); },
      }).done(function (res) {
        if (res.success) {
          isBackgroundMode = true;
          $modal.addClass('background-mode');
          showNotification('Background warmup job scheduled successfully. You\'ll be notified when it completes.', 'success');

          // Update modal content for background mode
          $modal.find('.warmup-progress').html('<div class="background-status">\
            <div class="background-icon">⏳</div>\
            <h4>Background Warmup Scheduled</h4>\
            <p>Job ID: ' + res.job_id + '</p>\
            <p>The warmup is now running in the background. You can continue working while it processes.</p>\
            <div class="background-actions">\
              <button class="button check-status-btn">Check Status</button>\
              <button class="button close-btn">Close</button>\
            </div>\
          </div>');
        } else {
          showNotification('Failed to schedule background warmup: ' + (res.error || 'Unknown error'), 'error');
          $btn.prop('disabled', false).text('Run in Background');
        }
      }).fail(function (xhr) {
        var errorMsg = 'Failed to schedule background warmup';
        try {
          var response = JSON.parse(xhr.responseText);
          if (response && response.error) {
            errorMsg = response.error;
          }
        } catch (e) { }
        showNotification(errorMsg, 'error');
        $btn.prop('disabled', false).text('Run in Background');
      });
    });

    // Check background job status
    $modal.on('click', '.check-status-btn', function () {
      $.ajax({
        url: MambaAdmin.warmupEndpoint.replace('/warmup', '/background-jobs'),
        method: 'GET',
        beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce); },
      }).done(function (res) {
        if (res.jobs && res.jobs.length > 0) {
          var latestJob = res.jobs[0];
          if (latestJob.status === 'completed') {
            showBackgroundResults(latestJob);
          } else if (latestJob.status === 'failed') {
            showNotification('Background warmup failed: ' + (latestJob.error || 'Unknown error'), 'error');
          } else {
            showNotification('Background warmup is still running...', 'info');
          }
        }
      });
    });

    function showBackgroundResults(job) {
      $modal.find('.warmup-progress').html('<div class="background-complete">\
        <div class="complete-icon">✓</div>\
        <h4>Background Warmup Complete</h4>\
        <div class="final-stats">\
          <div class="final-stat">\
            <span class="stat-label">Total Processed:</span>\
            <span class="stat-value">' + job.total_urls + '</span>\
          </div>\
          <div class="final-stat">\
            <span class="stat-label">Success:</span>\
            <span class="stat-value success">' + job.success + '</span>\
          </div>\
          <div class="final-stat">\
            <span class="stat-label">Failed:</span>\
            <span class="stat-value failed">' + job.failed + '</span>\
          </div>\
        </div>\
        <div class="background-actions">\
          <button class="button view-errors-btn">View Errors</button>\
          <button class="button close-btn">Close</button>\
        </div>\
      </div>');
    }

    // View errors functionality
    $modal.on('click', '.view-errors-btn', function () {
      $.ajax({
        url: MambaAdmin.warmupEndpoint.replace('/warmup', '/warmup-errors'),
        method: 'GET',
        beforeSend: function (xhr) { xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce); },
      }).done(function (res) {
        showErrorDetails(res);
      });
    });

    function showErrorDetails(errorData) {
      var errors = errorData.errors || [];
      var grouped = errorData.grouped || {};

      var errorHtml = '<div class="error-summary">';

      // Show error statistics
      if (errorData.stats) {
        errorHtml += '<div class="error-stats">';
        errorHtml += '<h5>Error Summary</h5>';
        errorHtml += '<div class="stat-grid">';
        errorHtml += '<div class="stat-item"><span class="stat-label">Total Errors:</span><span class="stat-value">' + errorData.stats.total_errors + '</span></div>';

        if (errorData.stats.error_types) {
          Object.keys(errorData.stats.error_types).forEach(function (type) {
            errorHtml += '<div class="stat-item"><span class="stat-label">' + type + ':</span><span class="stat-value">' + errorData.stats.error_types[type] + '</span></div>';
          });
        }
        errorHtml += '</div></div>';
      }

      // Show grouped errors
      if (Object.keys(grouped).length > 0) {
        errorHtml += '<div class="error-groups">';
        Object.keys(grouped).forEach(function (errorType) {
          var typeErrors = grouped[errorType];
          errorHtml += '<div class="error-group">';
          errorHtml += '<h6>' + errorType + ' (' + typeErrors.length + ')</h6>';
          errorHtml += '<div class="error-list">';

          typeErrors.slice(0, 10).forEach(function (error) { // Show first 10 of each type
            errorHtml += '<div class="error-item">';
            errorHtml += '<div class="error-url">' + error.url + '</div>';
            errorHtml += '<div class="error-details">';
            errorHtml += '<span class="error-message">' + (error.error_message || 'No message') + '</span>';
            if (error.status_code) errorHtml += '<span class="error-status">HTTP ' + error.status_code + '</span>';
            if (error.response_time) errorHtml += '<span class="error-time">' + error.response_time + 'ms</span>';
            errorHtml += '</div>';
            errorHtml += '</div>';
          });

          if (typeErrors.length > 10) {
            errorHtml += '<div class="error-more">... and ' + (typeErrors.length - 10) + ' more</div>';
          }

          errorHtml += '</div></div>';
        });
        errorHtml += '</div>';
      }

      errorHtml += '</div>';

      $modal.find('.warmup-progress').html(errorHtml);
    }

    function done(status) {
      var statusText = status === 'done' ? 'Completed' : (status === 'cancelled' ? 'Cancelled' : status);
      var statusClass = status === 'done' ? 'success' : 'warning';

      var html = '<div class="warmup-complete ' + statusClass + '">\
        <div class="complete-icon">' + (status === 'done' ? '✓' : '⚠') + '</div>\
        <h4>Warmup ' + statusText + '</h4>\
        <div class="final-stats">\
          <div class="final-stat">\
            <span class="stat-label">Total Processed:</span>\
            <span class="stat-value">' + $('.total-count').text() + '</span>\
          </div>\
          <div class="final-stat">\
            <span class="stat-label">Success:</span>\
            <span class="stat-value success">' + $('.success-count').text() + '</span>\
          </div>\
          <div class="final-stat">\
            <span class="stat-label">Failed:</span>\
            <span class="stat-value failed">' + $('.failed-count').text() + '</span>\
          </div>\
        </div>\
        <p>' + (status === 'done' ? 'Cache warmup completed successfully. Your site should now be faster for visitors.' : 'Warmup was interrupted.') + '</p>\
        <div class="complete-actions">\
          <button class="button view-errors-btn">View Errors</button>\
          <button class="button close-btn">Close</button>\
        </div>\
      </div>';

      $modal.find('.warmup-progress').html(html);

      // After warmup completes or ends, trigger an immediate refresh of cache counts
      try { $(document).trigger('mamba:refreshCacheCounts'); } catch (e) { }

      // Don't auto-close the modal - let user decide when to close
      // setTimeout(function(){ 
      //   if (!$modal.hasClass('minimized')) {
      //     closeModal();
      //   }
      // }, 5000);
    }

    function showNotification(message, type) {
      var $notification = $('<div class="mamba-notification ' + type + '">' + message + '</div>');
      $('body').append($notification);
      setTimeout(function () {
        $notification.addClass('show');
      }, 100);
      setTimeout(function () {
        $notification.removeClass('show');
        setTimeout(function () {
          $notification.remove();
        }, 300);
      }, 3000);
    }

    // Global toast function for other parts of the admin
    window.MambaAdmin = window.MambaAdmin || {};
    window.MambaAdmin.showToast = function (message, type) {
      showNotification(message, type || 'info');
    };

    // Function to show caching setup modal after license activation
    function showCachingSetupModal() {
      // Check if caching is already enabled
      if (typeof MambaAdmin !== 'undefined' && MambaAdmin.cacheEnabled === true) {
        return; // Don't show modal if caching is already enabled
      }

      // Check if we're already on the caching tab to avoid showing the modal
      var currentTab = $('.nav-tab-active').attr('href');
      if (currentTab && currentTab.indexOf('tab=caching') !== -1) {
        return; // Don't show modal if already on caching tab
      }

      var $modal = $('<div class="mamba-modal mamba-caching-setup-modal">\
        <div class="mamba-modal-overlay"></div>\
        <div class="mamba-modal-content">\
          <div class="mamba-modal-header">\
            <h3>\
              <span class="dashicons dashicons-performance"></span>\
              ' + (typeof MambaAdmin !== 'undefined' && MambaAdmin.i18n ? MambaAdmin.i18n.cachingSetupTitle : 'Quick Start: Enable Caching') + '\
            </h3>\
            <button class="mamba-modal-close" type="button">\
              <span class="dashicons dashicons-no-alt"></span>\
            </button>\
          </div>\
          <div class="mamba-modal-body">\
            <div class="mamba-modal-icon">\
              <span class="dashicons dashicons-performance"></span>\
            </div>\
            <p class="mamba-modal-message">' + (typeof MambaAdmin !== 'undefined' && MambaAdmin.i18n ? MambaAdmin.i18n.cachingSetupMessage : 'Great! Your license is now active. To get the most out of Mamba, enable caching for optimal WooCommerce performance.') + '</p>\
            <p class="mamba-modal-subtitle">' + (typeof MambaAdmin !== 'undefined' && MambaAdmin.i18n ? MambaAdmin.i18n.cachingSetupSubtitle : 'Caching will significantly improve your store\'s loading speed and reduce server load.') + '</p>\
            <div class="mamba-modal-actions">\
              <a href="' + (typeof MambaAdmin !== 'undefined' && MambaAdmin.adminUrl ? MambaAdmin.adminUrl : '') + 'admin.php?page=mamba&tab=caching" class="button button-primary">\
                <span class="dashicons dashicons-performance"></span>\
                ' + (typeof MambaAdmin !== 'undefined' && MambaAdmin.i18n ? MambaAdmin.i18n.goToCaching : 'Go to Caching Settings') + '\
              </a>\
              <button class="button button-secondary mamba-modal-close">\
                ' + (typeof MambaAdmin !== 'undefined' && MambaAdmin.i18n ? MambaAdmin.i18n.maybeLater : 'Maybe Later') + '\
              </button>\
            </div>\
          </div>\
        </div>\
      </div>');

      $('body').addClass('mamba-modal-open').append($modal);

      // Close modal handlers
      $modal.on('click', '.mamba-modal-close, .mamba-modal-overlay', function (e) {
        if (e.target === this) {
          closeCachingSetupModal();
        }
      });

      // Keyboard shortcut
      $(document).on('keydown.cachingSetup', function (e) {
        if (e.key === 'Escape') {
          closeCachingSetupModal();
        }
      });

      function closeCachingSetupModal() {
        $('body').removeClass('mamba-modal-open');
        $modal.remove();
        $(document).off('keydown.cachingSetup');
      }
    }

    // Make the function globally available
    window.showCachingSetupModal = showCachingSetupModal;
  });
})(jQuery);

jQuery(function ($) {
  // Warmup Log Viewer Handler
  $(document).on('click', '.mamba-view-warmup-log', function (e) {
    e.preventDefault();
    var jobId = $(this).data('job-id');
    var $btn = $(this);
    $btn.css('opacity', '0.5');

    var endpoint = (typeof MambaAdmin !== 'undefined' && MambaAdmin.warmupEndpoint)
      ? MambaAdmin.warmupEndpoint.replace('/warmup', '/warmup-errors')
      : '/wp-json/mamba-wc/v1/warmup-errors';

    $.ajax({
      url: endpoint + '?job_id=' + jobId,
      method: 'GET',
      beforeSend: function (xhr) {
        if (typeof MambaAdmin !== 'undefined') xhr.setRequestHeader('X-WP-Nonce', MambaAdmin.nonce);
      }
    }).done(function (res) {
      $btn.css('opacity', '1');

      // Normalize response
      var errors = Array.isArray(res) ? res : (res.errors || []);

      // Generate Modal HTML
      var html = '<div class="mamba-modal mamba-log-modal" style="position:fixed;top:0;left:0;right:0;bottom:0;z-index:100000;display:flex;align-items:center;justify-content:center;">' +
        '<div class="mamba-modal-overlay" style="position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);"></div>' +
        '<div class="mamba-modal-content" style="position:relative;background:#fff;width:90%;max-width:800px;max-height:80vh;border-radius:8px;box-shadow:0 20px 50px rgba(0,0,0,0.3);display:flex;flex-direction:column;overflow:hidden;">' +
        '<div class="mamba-modal-header" style="padding:15px 20px;border-bottom:1px solid #eee;display:flex;justify-content:space-between;align-items:center;background:#f8f9fa;">' +
        '<h3 style="margin:0;font-size:16px;">Warmup Errors (Job ' + jobId + ')</h3>' +
        '<button class="mamba-modal-close" style="background:none;border:none;font-size:18px;cursor:pointer;">&times;</button></div>' +
        '<div class="mamba-modal-body" style="flex:1;overflow-y:auto;padding:0;">';

      if (errors && errors.length > 0) {
        html += '<table class="wp-list-table widefat fixed striped" style="margin:0;border:none;box-shadow:none;"><thead><tr><th style="padding:10px 15px;">URL</th><th style="padding:10px 15px;">Error</th><th style="padding:10px 15px;width:100px;">Time</th></tr></thead><tbody>';
        errors.forEach(function (err) {
          var timeStr = err.timestamp ? new Date(err.timestamp * 1000).toLocaleTimeString() : '-';
          html += '<tr><td style="padding:10px 15px;word-break:break-all;">' + (err.url || '-') + '</td><td style="padding:10px 15px;color:#d63638;">' + (err.error_message || err.message || '-') + '</td><td style="padding:10px 15px;">' + timeStr + '</td></tr>';
        });
        html += '</tbody></table>';
      } else {
        html += '<div style="padding:40px;text-align:center;color:#666;">No errors found in log for this job.</div>';
      }

      html += '</div></div></div>';

      var $modal = $(html);
      $('body').append($modal).addClass('mamba-modal-open');

      // Dark mode support for modal
      if ($('body').attr('data-mamba-theme') === 'dark') {
        $modal.find('.mamba-modal-content').css({ background: '#1e293b', color: '#f1f5f9' });
        $modal.find('.mamba-modal-header').css({ background: '#0f172a', borderColor: '#334155' });
        $modal.find('h3').css({ color: '#f1f5f9' });
        $modal.find('button').css({ color: '#94a3b8' });
        $modal.find('table').css({ background: 'transparent', color: '#f1f5f9' });
        $modal.find('th').css({ color: '#94a3b8', background: '#0f172a', borderColor: '#334155' });
        $modal.find('td').css({ borderColor: '#334155' });
        // striping
        $modal.find('tr:nth-child(odd) td').css({ background: 'rgba(255,255,255,0.03)' });
        $modal.find('tr:nth-child(even) td').css({ background: 'transparent' });
      }

      $modal.on('click', '.mamba-modal-close, .mamba-modal-overlay', function () {
        $modal.remove();
        $('body').removeClass('mamba-modal-open');
      });
    }).fail(function () {
      $btn.css('opacity', '1');
      alert('Failed to load log data. It may be expired.');
    });
  });

  // --- GENERIC LIVE SETTINGS SAVE ---
  // This enables auto-save for toggle switches and select dropdowns across all tabs
  (function initLiveSettings() {
    var saveNonce = null;
    var $saveIndicator = null;
    
    // Create save indicator
    function showSaved() {
      if (!$saveIndicator) {
        $saveIndicator = $('<div id="mamba-save-indicator" style="position:fixed;top:50px;right:20px;background:#10b981;color:white;padding:10px 20px;border-radius:6px;z-index:99999;display:none;font-weight:500;box-shadow:0 4px 12px rgba(0,0,0,0.15);"><span class="dashicons dashicons-yes" style="margin-right:5px;"></span>Saved</div>');
        $('body').append($saveIndicator);
      }
      $saveIndicator.stop(true, true).fadeIn(200).delay(1000).fadeOut(200);
    }
    
    function showError(msg) {
      if (!$saveIndicator) {
        $saveIndicator = $('<div id="mamba-save-indicator" style="position:fixed;top:50px;right:20px;background:#ef4444;color:white;padding:10px 20px;border-radius:6px;z-index:99999;display:none;font-weight:500;box-shadow:0 4px 12px rgba(0,0,0,0.15);"></div>');
        $('body').append($saveIndicator);
      }
      $saveIndicator.html('<span class="dashicons dashicons-warning" style="margin-right:5px;"></span>' + (msg || 'Error'));
      $saveIndicator.css('background', '#ef4444').stop(true, true).fadeIn(200).delay(2000).fadeOut(200, function() {
        $saveIndicator.css('background', '#10b981');
      });
    }
    
    // Get nonce from page or generate via AJAX
    function getNonce(callback) {
      if (saveNonce) {
        callback(saveNonce);
        return;
      }
      // Try to get from MambaAdmin
      if (typeof MambaAdmin !== 'undefined' && MambaAdmin.saveNonce) {
        saveNonce = MambaAdmin.saveNonce;
        callback(saveNonce);
        return;
      }
      // Fallback: get from hidden field on page
      var $nonceField = $('input[name="mamba_save_setting_nonce"]');
      if ($nonceField.length) {
        saveNonce = $nonceField.val();
        callback(saveNonce);
        return;
      }
      // No nonce available - form will need to be submitted traditionally
      callback(null);
    }
    
    // Save a single setting via AJAX
    function saveSetting(name, value, callback) {
      getNonce(function(nonce) {
        if (!nonce) {
          // No nonce - can't save via AJAX
          if (callback) callback(false);
          return;
        }
        
        $.ajax({
          url: ajaxurl,
          type: 'POST',
          data: {
            action: 'mamba_save_setting',
            nonce: nonce,
            setting: name,
            value: value
          },
          timeout: 10000
        }).done(function(response) {
          if (response.success) {
            showSaved();
            if (callback) callback(true);
          } else {
            showError(response.data ? response.data.message : 'Save failed');
            if (callback) callback(false);
          }
        }).fail(function() {
          showError('Network error');
          if (callback) callback(false);
        });
      });
    }
    
    // Helper to check if element is inside a form-based tab (Media, DB, etc.)
    // These tabs use form submission, not AJAX live-save
    function isInFormBasedTab($el) {
      return $el.closest('.mamba-media-form, form[action*="admin-post.php"]').length > 0;
    }
    
    // Attach to toggle switches (checkboxes in .mamba-toggle-switch)
    $(document).on('change', '.mamba-toggle-switch input[type="checkbox"]', function() {
      var $input = $(this);
      var name = $input.attr('name');
      if (!name || !name.startsWith('mamba_')) return; // Only handle mamba settings
      
      // Skip if inside a form-based tab (these use form submission)
      if (isInFormBasedTab($input)) return;
      
      var value = $input.is(':checked') ? 1 : 0;
      saveSetting(name, value);
    });
    
    // Attach to select dropdowns with mamba_ names
    $(document).on('change', 'select[name^="mamba_"]', function() {
      var $select = $(this);
      var name = $select.attr('name');
      
      // Skip if inside a form-based tab (these use form submission)
      if (isInFormBasedTab($select)) return;
      
      var value = $select.val();
      saveSetting(name, value);
    });
    
    // Attach to number/text inputs with mamba_ names (on blur to avoid too many saves)
    $(document).on('blur', 'input[type="number"][name^="mamba_"], input[type="text"][name^="mamba_"]', function() {
      var $input = $(this);
      var name = $input.attr('name');
      
      // Skip if inside a form-based tab (these use form submission)
      if (isInFormBasedTab($input)) return;
      
      var value = $input.val();
      saveSetting(name, value);
    });
    
    // Also save on Enter key for inputs
    $(document).on('keypress', 'input[type="number"][name^="mamba_"], input[type="text"][name^="mamba_"]', function(e) {
      if (e.which === 13) {
        e.preventDefault();
        var $input = $(this);
        var name = $input.attr('name');
        
        // Skip if inside a form-based tab (these use form submission)
        if (isInFormBasedTab($input)) return;
        
        var value = $input.val();
        saveSetting(name, value);
      }
    });
    
    // Expose for manual use
    window.MambaSaveSetting = saveSetting;
  })();
  
  // --- UNSAVED CHANGES INDICATOR ---
  // For tabs that use form submission (Caching, Media, DB, etc.)
  (function() {
    // Only run on Mamba admin pages
    var urlParams = new URLSearchParams(window.location.search);
    if (urlParams.get('page') !== 'mamba') return;
    
    var hasUnsavedChanges = false;
    var $forms = $('form[method="post"]').filter(function() {
      // Only track forms with mamba nonce fields (our settings forms)
      // Exclude Media tab form - it has its own AJAX live-save mechanism
      if ($(this).hasClass('mamba-media-form')) return false;
      return $(this).find('input[name$="_nonce"]').length > 0;
    });
    
    if (!$forms.length) return;
    
    // Track initial form state
    var initialStates = {};
    $forms.each(function(index) {
      var $form = $(this);
      $form.attr('data-mamba-form-index', index);
      initialStates[index] = $form.serialize();
    });
    
    // Create floating save reminder
    var $reminder = $('<div class="mamba-unsaved-reminder" style="display:none;">\
      <span class="dashicons dashicons-warning"></span>\
      <span class="reminder-text">You have unsaved changes</span>\
      <button type="button" class="reminder-save-btn">Save Now</button>\
    </div>');
    $('body').append($reminder);
    
    // Check for changes on any input change
    $forms.on('change input', 'input, select, textarea', function() {
      var $form = $(this).closest('form');
      var index = $form.attr('data-mamba-form-index');
      var currentState = $form.serialize();
      
      if (currentState !== initialStates[index]) {
        hasUnsavedChanges = true;
        showReminder($form);
      } else {
        // Check if ALL forms are unchanged
        var anyChanged = false;
        $forms.each(function() {
          var idx = $(this).attr('data-mamba-form-index');
          if ($(this).serialize() !== initialStates[idx]) {
            anyChanged = true;
            return false;
          }
        });
        if (!anyChanged) {
          hasUnsavedChanges = false;
          hideReminder();
        }
      }
    });
    
    function showReminder($form) {
      // Store reference to the form that needs saving
      $reminder.data('target-form', $form);
      
      // Position near the save button or at bottom
      var $saveBtn = $form.find('.mamba-save-button, button[type="submit"]').first();
      if ($saveBtn.length) {
        $reminder.addClass('has-target');
      }
      
      $reminder.slideDown(200);
      
      // Also highlight the save button
      $saveBtn.addClass('mamba-pulse-attention');
    }
    
    function hideReminder() {
      $reminder.slideUp(200);
      $('.mamba-save-button, button[type="submit"]').removeClass('mamba-pulse-attention');
    }
    
    // Click handler for reminder save button
    var isSaving = false;
    $reminder.on('click', '.reminder-save-btn', function() {
      if (isSaving) return; // Prevent double-click during save
      var $form = $reminder.data('target-form');
      if ($form && $form.length) {
        $form.find('.mamba-save-button, button[type="submit"]').first().trigger('click');
      }
    });
    
    // Update initial state after successful form submission
    $forms.on('submit', function() {
      var $form = $(this);
      var index = $form.attr('data-mamba-form-index');
      // Mark as saving to prevent duplicate submissions
      isSaving = true;
      hasUnsavedChanges = false;
      
      // Update reminder to show saving state
      $reminder.find('.reminder-text').text('Saving...');
      $reminder.find('.reminder-save-btn').prop('disabled', true).text('Saving...');
      
      // Hide reminder after a brief moment (form will reload page)
      setTimeout(function() {
        hideReminder();
      }, 500);
    });
    
    // Warn before leaving page with unsaved changes
    $(window).on('beforeunload', function(e) {
      if (hasUnsavedChanges) {
        var msg = 'You have unsaved changes. Are you sure you want to leave?';
        e.returnValue = msg;
        return msg;
      }
    });
    
    // Don't warn when clicking save buttons
    $(document).on('click', '.mamba-save-button, button[type="submit"]', function() {
      hasUnsavedChanges = false;
    });
  })();
});
