// eo-modal — unified modal helper. CSS in modal.css under ".eo-modal".
//
// API:
//   const m = openEoModal({
//     id, size, className,                  // 'sm' | 'md' (default) | 'lg'
//     icon, iconAlt, eyebrow, title, desc,  // header
//     body,                                  // string | HTMLElement | array of either
//     actions,                               // [{label, variant, onClick(modal)}]
//     closeOnBackdrop = true,
//     onClose,
//   });
//   m.close();        // remove from DOM, fires onClose
//   m.bodyEl;         // the .eo-modal-body element (mutate as needed)
//   m.contentEl;      // the .eo-modal-content element
//   m.el;             // the backdrop .eo-modal element
//
// Section primitives (return HTML strings; pass as part of body):
//   eoSection(title, content)
//   eoBadgeRow([{icon, label, variant}])      variant: success|info|purple|warning|danger
//   eoUrlList([{url, label}])
//   eoCredList([{title, username, password}])
//   eoEmpty(text)

(function () {
  function escHtml(s) {
    return String(s == null ? '' : s)
      .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  }
  function escAttr(s) {
    return escHtml(s).replace(/"/g, '&quot;').replace(/'/g, '&#39;');
  }
  function toBodyNode(input) {
    if (input == null) return document.createTextNode('');
    if (typeof input === 'string') {
      const t = document.createElement('div');
      t.style.display = 'contents';
      t.innerHTML = input;
      return t;
    }
    if (Array.isArray(input)) {
      const f = document.createDocumentFragment();
      input.forEach((p) => f.appendChild(toBodyNode(p)));
      return f;
    }
    if (input instanceof HTMLElement || input instanceof DocumentFragment) return input;
    return document.createTextNode(String(input));
  }

  window.openEoModal = function openEoModal(opts) {
    opts = opts || {};
    const id = opts.id || `eo-modal-${Math.random().toString(36).slice(2, 9)}`;
    const size = opts.size || 'md';

    const existing = document.getElementById(id);
    if (existing) existing.remove();

    const root = document.createElement('div');
    root.className = `eo-modal ${opts.className || ''}`.trim();
    root.id = id;
    root.dataset.size = size;

    const headerHasIcon = !!opts.icon;
    const titleHtml = `
      <div class="eo-modal-header-text">
        ${opts.eyebrow ? `<div class="eo-modal-eyebrow">${escHtml(opts.eyebrow)}</div>` : ''}
        ${opts.title ? `<h3 class="eo-modal-title">${escHtml(opts.title)}</h3>` : ''}
        ${opts.desc ? `<p class="eo-modal-desc">${escHtml(opts.desc)}</p>` : ''}
      </div>`;

    const endIconHtml = opts.endIcon
      ? `<span class="eo-modal-end-icon" aria-hidden="true">${typeof opts.endIcon === 'string' ? escHtml(opts.endIcon) : ''}</span>`
      : '';

    root.innerHTML = `
      <div class="eo-modal-content">
        ${(opts.icon || opts.title || opts.eyebrow) ? `
          <div class="eo-modal-header">
            <div class="eo-modal-header-info">
              ${headerHasIcon ? `<img src="${escAttr(opts.icon)}" alt="${escAttr(opts.iconAlt || '')}" class="eo-modal-icon" onerror="this.onerror=null;this.src='/icons/apps/default.svg';">` : ''}
              ${titleHtml}
            </div>
            ${endIconHtml}
            <button type="button" class="eo-modal-close" aria-label="Close">&times;</button>
          </div>` : ''}
        <div class="eo-modal-body"></div>
        ${(opts.actions && opts.actions.length) ? '<div class="eo-modal-footer"></div>' : ''}
      </div>`;

    const contentEl = root.querySelector('.eo-modal-content');
    const bodyEl = root.querySelector('.eo-modal-body');
    const footerEl = root.querySelector('.eo-modal-footer');
    const closeBtn = root.querySelector('.eo-modal-close');

    bodyEl.appendChild(toBodyNode(opts.body));

    const m = {
      el: root,
      contentEl,
      bodyEl,
      close: () => {
        root.remove();
        if (typeof opts.onClose === 'function') {
          try { opts.onClose(); } catch (e) { console.error(e); }
        }
      }
    };

    if (closeBtn) closeBtn.addEventListener('click', m.close);
    if (opts.closeOnBackdrop !== false) {
      root.addEventListener('click', (e) => { if (e.target === root) m.close(); });
    }

    if (footerEl && Array.isArray(opts.actions)) {
      opts.actions.forEach((a) => {
        const btn = document.createElement('button');
        btn.type = 'button';
        btn.className = `btn btn-${a.variant || 'secondary'}`;
        btn.textContent = a.label || 'OK';
        btn.addEventListener('click', () => {
          if (typeof a.onClick === 'function') a.onClick(m);
          else m.close();
        });
        footerEl.appendChild(btn);
      });
    }

    document.body.appendChild(root);
    return m;
  };

  // ----- Section primitives -----

  window.eoSection = function (title, content) {
    return `<div class="eo-modal-section">
      ${title ? `<div class="eo-modal-section-title">${escHtml(title)}</div>` : ''}
      ${content || ''}
    </div>`;
  };

  window.eoBadgeRow = function (badges) {
    if (!Array.isArray(badges) || badges.length === 0) return '';
    const html = badges.map((b) => {
      const variant = b.variant ? ` ${b.variant}` : '';
      return `<span class="eo-modal-badge${variant}">${b.icon ? escHtml(b.icon) + ' ' : ''}${escHtml(b.label)}</span>`;
    }).join('');
    return `<div class="eo-modal-badge-row">${html}</div>`;
  };

  window.eoUrlList = function (urls) {
    if (!Array.isArray(urls) || urls.length === 0) return '';
    const arrow = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>`;
    const rows = urls.map((u) => `
      <a class="eo-modal-url-row" href="${escAttr(u.url)}" target="_blank" rel="noopener">
        <span class="eo-modal-url-label">${escHtml(u.label)}</span>
        <span class="eo-modal-url-href">${escHtml(u.url)}</span>
        ${arrow}
      </a>`).join('');
    return `<div class="eo-modal-url-list">${rows}</div>`;
  };

  window.eoCredList = function (creds) {
    if (!Array.isArray(creds) || creds.length === 0) return '';
    const copyBtn = (val) => `<button type="button" class="eo-modal-cred-copy" data-copy="${escAttr(val)}" title="Copy"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></button>`;
    return creds.map((c) => {
      const userLabel = c.userLabel
        || (typeof c.username === 'string' && c.username.includes('@') ? 'Email' : 'User');
      const passLabel = c.passLabel || 'Pass';
      return `
      <div class="eo-modal-cred">
        ${c.title ? `<div class="eo-modal-cred-title">${escHtml(c.title)}</div>` : ''}
        ${c.username != null ? `<div class="eo-modal-cred-row">
          <span class="eo-modal-cred-label">${escHtml(userLabel)}</span>
          <code class="eo-modal-cred-value">${escHtml(c.username)}</code>
          ${copyBtn(c.username)}
        </div>` : ''}
        ${c.password != null ? `<div class="eo-modal-cred-row">
          <span class="eo-modal-cred-label">${escHtml(passLabel)}</span>
          <code class="eo-modal-cred-value eo-cred-pass" data-revealed="false" data-value="${escAttr(c.password)}">••••••••</code>
          <button type="button" class="eo-modal-cred-toggle">Show</button>
          ${copyBtn(c.password)}
        </div>` : ''}
      </div>`;
    }).join('');
  };

  window.eoEmpty = function (text) {
    return `<p class="eo-modal-empty">${escHtml(text || '')}</p>`;
  };

  document.addEventListener('click', (e) => {
    const btn = e.target.closest && e.target.closest('.eo-modal-cred-toggle');
    if (!btn) return;
    const code = btn.parentElement && btn.parentElement.querySelector('.eo-cred-pass');
    if (!code) return;
    const revealed = code.dataset.revealed === 'true';
    code.textContent = revealed ? '••••••••' : code.dataset.value;
    code.dataset.revealed = revealed ? 'false' : 'true';
    btn.textContent = revealed ? 'Show' : 'Hide';
  });

  // Copy-to-clipboard for cred rows. Briefly swaps the icon for a check.
  document.addEventListener('click', (e) => {
    const btn = e.target.closest && e.target.closest('.eo-modal-cred-copy');
    if (!btn) return;
    const value = btn.dataset.copy || '';
    const done = () => {
      btn.classList.add('copied');
      const original = btn.innerHTML;
      btn.innerHTML = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
      setTimeout(() => { btn.classList.remove('copied'); btn.innerHTML = original; }, 1100);
    };
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(value).then(done).catch(() => done());
    } else {
      const ta = document.createElement('textarea');
      ta.value = value; ta.style.position = 'fixed'; ta.style.opacity = '0';
      document.body.appendChild(ta); ta.select();
      try { document.execCommand('copy'); } catch (_) {}
      document.body.removeChild(ta); done();
    }
  });
})();
