/**
 * tvLoadError — make a FAILED load look different from an EMPTY one.
 *
 * WHY
 * ---
 * Health surfaces here repeatedly did:
 *     .then(function(r) { return r.ok ? r.json() : null; })
 *     .then(function(d) { if (!d) return; render(d); })
 *     .catch(function() { /* silent *\/ });
 * so a 500, a dropped connection or an auth expiry rendered the SAME empty state
 * as "no run yet". On a monitoring product that reads as ALL CLEAR, which is the
 * worst possible default: the one time the loader breaks is the one time the user
 * most needs to know. Two real instances shipped this way (Deep EBS sanity and
 * the 12.2 module checks), and the parseList bug fixed alongside them blanked an
 * entire page for the same reason.
 *
 * USE
 * ---
 *   fetch(url)
 *     .then(function(r){ if(!r.ok) throw new Error('HTTP '+r.status); return r.json(); })
 *     .then(function(d){ tvLoadError.clear('sanityPanel'); render(d); })
 *     .catch(function(e){ tvLoadError.show('sanityPanel', e, {
 *        what: 'the latest sanity run', retry: loadLatestSanityRun }); });
 *
 * The banner is INSERTED next to the container, never replacing its contents, so
 * an existing empty state stays visible underneath and nothing is destroyed.
 */
(function () {
  var STYLE_ID = 'tv-load-error-style';

  function ensureStyle() {
    if (document.getElementById(STYLE_ID)) return;
    var s = document.createElement('style');
    s.id = STYLE_ID;
    s.textContent =
      '.tv-load-error{display:flex;align-items:flex-start;gap:10px;margin:10px 0;padding:11px 13px;' +
      'border:1px solid rgba(248,113,113,0.32);border-radius:8px;background:rgba(248,113,113,0.07);' +
      'font-size:13px;line-height:1.45;color:var(--text,#e6e6e6)}' +
      '.tv-load-error .tv-le-icon{flex:0 0 auto;color:#f87171;font-weight:700;line-height:1.3}' +
      '.tv-load-error .tv-le-body{flex:1 1 auto;min-width:0}' +
      '.tv-load-error .tv-le-title{font-weight:600;color:#f87171}' +
      '.tv-load-error .tv-le-detail{margin-top:3px;font-size:11.5px;color:var(--text-dim,#9a9aa2);' +
      'font-family:"JetBrains Mono",ui-monospace,monospace;word-break:break-word}' +
      '.tv-load-error .tv-le-retry{flex:0 0 auto;cursor:pointer;font-size:12px;font-weight:600;' +
      'padding:4px 10px;border-radius:6px;border:1px solid rgba(248,113,113,0.4);' +
      'background:transparent;color:#f87171}' +
      '.tv-load-error .tv-le-retry:hover{background:rgba(248,113,113,0.12)}';
    document.head.appendChild(s);
  }

  function resolve(target) {
    if (!target) return null;
    return (typeof target === 'string') ? document.getElementById(target) : target;
  }

  function bannerId(el) { return 'tv-le-' + (el.id || 'anon'); }

  window.tvLoadError = {
    /**
     * @param target  element or element id the failure relates to
     * @param err     Error, Response-ish, or string
     * @param opts    { what: 'the latest sanity run', retry: fn }
     */
    show: function (target, err, opts) {
      var el = resolve(target);
      if (!el) return;
      opts = opts || {};
      ensureStyle();

      var detail = '';
      if (err) {
        if (typeof err === 'string') detail = err;
        else if (err.message) detail = err.message;
        else if (err.status) detail = 'HTTP ' + err.status;
        else { try { detail = String(err); } catch (_) { detail = 'unknown error'; } }
      }

      var id = bannerId(el);
      var box = document.getElementById(id);
      if (!box) {
        box = document.createElement('div');
        box.id = id;
        box.className = 'tv-load-error';
        el.parentNode.insertBefore(box, el);
      }
      box.style.display = '';

      var what = opts.what || 'this data';
      box.innerHTML = '';

      var icon = document.createElement('span');
      icon.className = 'tv-le-icon';
      icon.textContent = '!';
      box.appendChild(icon);

      var body = document.createElement('div');
      body.className = 'tv-le-body';
      var t = document.createElement('div');
      t.className = 'tv-le-title';
      // The wording is the whole point: say it FAILED, not that there is nothing.
      t.textContent = 'Could not load ' + what + ' — this is a load failure, not an empty result.';
      body.appendChild(t);
      if (detail) {
        var d = document.createElement('div');
        d.className = 'tv-le-detail';
        d.textContent = detail;
        body.appendChild(d);
      }
      box.appendChild(body);

      if (typeof opts.retry === 'function') {
        var btn = document.createElement('button');
        btn.className = 'tv-le-retry';
        btn.type = 'button';
        btn.textContent = 'Retry';
        btn.addEventListener('click', function () {
          window.tvLoadError.clear(el);
          try { opts.retry(); } catch (_) { /* retry threw; banner already cleared */ }
        });
        box.appendChild(btn);
      }
    },

    clear: function (target) {
      var el = resolve(target);
      if (!el) return;
      var box = document.getElementById(bannerId(el));
      if (box && box.parentNode) box.parentNode.removeChild(box);
    }
  };
})();
