<style>
.vv-pt-grid       { display:grid; gap:12px; }
.vv-pt-node       { background:#161616; border:1px solid #2a2a2a; border-radius:6px; padding:12px; min-width:0; }
.vv-pt-node.me    { border-color:#2a3a2a; }
.vv-pt-node-head  { display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:10px; }
.vv-pt-hostname   { font-size:13px; font-weight:bold; color:#ccc; }
.vv-pt-slot       { font-size:10px; color:#444; margin-top:1px; }
.vv-pt-tags       { display:flex; gap:4px; flex-wrap:wrap; justify-content:flex-end; }
.vv-pt-tag        { font-size:8px; padding:1px 5px; border-radius:3px; white-space:nowrap; }
.vv-pt-tag.me     { background:#1a3a1a; color:#4caf50; }
.vv-pt-tag.owner  { background:#1a2a3a; color:#4a9eff; }
.vv-pt-tag.mirror { background:#2a2a1a; color:#ff9800; }
.vv-pt-row        { display:flex; justify-content:space-between; align-items:baseline; margin:3px 0; }
.vv-pt-lbl        { font-size:11px; color:#555; }
.vv-pt-val        { font-size:11px; color:#bbb; text-align:right; }
.vv-pt-sep        { border:none; border-top:1px solid #222; margin:8px 0; }
.vv-pt-state      { font-size:12px; font-weight:500; }
.vv-pt-dot        { width:8px; height:8px; border-radius:50%; display:inline-block; flex-shrink:0; margin-right:5px; }
.vv-pt-actions    { display:flex; gap:10px; flex-wrap:wrap; margin-top:4px; }
.vv-pt-action-btn { padding:5px 16px; border:none; border-radius:4px; cursor:pointer;
                    font-size:12px; font-weight:500; }
.vv-pt-action-btn.run  { background:#1a3a1a; color:#6fcf97; border:1px solid #2e6b2e; }
.vv-pt-action-btn.warn { background:#3a1a1a; color:#f88; border:1px solid #6b2e2e; }
.vv-pt-action-btn.info { background:#1a2a3a; color:#7ab; border:1px solid #2e4a6b; }
.vv-pt-action-btn:disabled { opacity:0.4; cursor:default; }
.vv-pt-transfer-note { font-size:10px; color:#555; margin-top:6px; font-family:monospace; }
.vv-pt-onboard-highlight {
  box-shadow: 0 0 0 2px #4a8, 0 0 12px rgba(100,200,120,.25) !important;
  animation: vvOnboardPulse 1.4s ease-in-out 4;
}
@keyframes vvOnboardPulse {
  0%,100% { box-shadow: 0 0 0 2px #4a8, 0 0 8px rgba(100,200,120,.2); }
  50%     { box-shadow: 0 0 0 4px #4a8, 0 0 18px rgba(100,200,120,.45); }
}
</style>

<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 2px;">
  <span style="font-size:13px;font-weight:bold;color:#888;text-transform:uppercase;letter-spacing:.06em;">Partnership</span>
  <span style="font-size:11px;color:#3a3a3a;" id="vv-pt-ts"></span>
</div>

<!-- Config bar -->
<div class="vv-card" style="margin-bottom:12px;" id="vv-pt-config-card">
  <div id="vv-pt-config-body" style="color:#444;font-size:12px;">Loading…</div>
</div>

<!-- Node grid -->
<div id="vv-pt-nodes" class="vv-pt-grid" style="margin-bottom:12px;">
  <div style="color:#444;font-size:12px;padding:16px 0;text-align:center;">Loading…</div>
</div>

<!-- Actions -->
<div class="vv-card" id="vv-pt-actions-card">
  <h3>Actions</h3>
  <div id="vv-pt-actions-body" style="color:#444;font-size:12px;">Loading…</div>
</div>

<script>
(function() {

// ── Helpers ───────────────────────────────────────────────────────────────────

function _relTime(ts) {
  if (!ts) return '—';
  const d = Math.floor(Date.now() / 1000) - ts;
  if (d < 60)     return 'just now';
  if (d < 3600)   return Math.floor(d / 60) + 'm ago';
  if (d < 86400)  return Math.floor(d / 3600) + 'h ago';
  if (d < 172800) return 'yesterday';
  return Math.floor(d / 86400) + 'd ago';
}

function _uptime(sec) {
  if (!sec) return '—';
  const d = Math.floor(sec / 86400);
  const h = Math.floor((sec % 86400) / 3600);
  const m = Math.floor((sec % 3600) / 60);
  return d > 0 ? `${d}d ${h}h ${m}m` : h > 0 ? `${h}h ${m}m` : `${m}m`;
}

function _row(lbl, val) {
  return `<div class="vv-pt-row"><span class="vv-pt-lbl">${lbl}</span><span class="vv-pt-val">${val}</span></div>`;
}

// ── Config bar ────────────────────────────────────────────────────────────────

function _renderConfig(cfg) {
  const dot   = cfg.enabled ? '#4caf50' : '#555';
  const label = cfg.enabled
    ? `<span style="color:#4caf50;">enabled</span>`
    : `<span style="color:#555;">disabled</span>`;
  const owner = cfg.owner_host || '—';
  const items = [
    label,
    `Owner: <span style="color:#ccc;">${owner}</span>`,
    `Sync: ${cfg.sync_min}min`,
    `Grace: ${cfg.grace_hours}h`,
    `Offline threshold: ${cfg.offline_threshold}d`,
    cfg.remove_tailscale ? 'Tailscale removal: on' : 'Tailscale removal: off',
    cfg.tailscale_configured ? '' : '<span style="color:#ff9800;">⚠ Tailscale API key not set</span>',
  ].filter(Boolean);

  return `<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap;">
    <span class="vv-pt-dot" style="background:${dot}"></span>
    ${items.map(i => `<span style="font-size:11px;color:#666;">${i}</span>`)
           .join('<span style="color:#333;">·</span>')}
  </div>`;
}

// ── Node card ─────────────────────────────────────────────────────────────────

const fbColors = {
  NORMAL:      '#4caf50',
  FAILOVER:    '#f44336',
  NO_INTERNET: '#ff9800',
  DARK:        '#9e9e9e',
  UNKNOWN:     '#444',
};
const fbLabels = {
  NORMAL:      '✓ Nominal',
  FAILOVER:    '⚠ Failover',
  NO_INTERNET: '⚡ No internet',
  DARK:        '◌ Dark mode',
  UNKNOWN:     '— Unknown',
};
const ptStates = {
  ACTIVE:   ['#4caf50', 'Active'],
  INACTIVE: ['#555',    'Inactive'],
  PENDING:  ['#ff9800', 'Pending'],
};

function _nodeCard(node) {
  const tsOnline = node.ts_online;
  const dotCol   = tsOnline === null ? '#555' : tsOnline ? '#4caf50' : '#f44336';
  const dotTip   = tsOnline === null ? 'unknown' : tsOnline ? (node.ts_active ? 'active' : 'idle') : 'offline';

  const tags = [
    node.is_me    ? '<span class="vv-pt-tag me">US</span>'     : '',
    node.is_owner ? '<span class="vv-pt-tag owner">OWNER</span>' : '<span class="vv-pt-tag mirror">MIRROR</span>',
  ].join('');

  // System info
  const sys    = node.system || {};
  const ver    = sys.unraid_version || '—';
  const uptime = sys.uptime_sec ? _uptime(sys.uptime_sec) : '—';

  // Fallback
  const fb     = (node.fallback || 'UNKNOWN').toUpperCase();
  const fbCol  = fbColors[fb] || '#444';
  const fbLbl  = fbLabels[fb] || fb;

  // Partnership DB
  const pt      = node.partnership || {};
  const ptState = (pt.state || '').toUpperCase();
  const [ptCol, ptLbl] = ptStates[ptState] || ['#444', ptState || '—'];
  const ptUpdated = pt.updated ? _relTime(parseInt(pt.updated)) : null;

  let body = '';

  // Network
  body += `<div style="display:flex;align-items:center;gap:6px;margin-bottom:8px;">
    <span class="vv-pt-dot" style="background:${dotCol}"></span>
    <span style="font-size:11px;color:${dotCol};">${dotTip}</span>`;
  if (node.ts_ip) body += `<span style="font-size:10px;color:#444;margin-left:4px;">${node.ts_ip}</span>`;
  body += `</div>`;

  // System
  body += _row('unRAID', ver);
  body += _row('Uptime', uptime);

  body += `<hr class="vv-pt-sep">`;

  // States
  body += `<div class="vv-pt-row">
    <span class="vv-pt-lbl">Fallback</span>
    <span class="vv-pt-state" style="color:${fbCol};">${fbLbl}</span>
  </div>`;
  body += `<div class="vv-pt-row">
    <span class="vv-pt-lbl">Partnership</span>
    <span class="vv-pt-state" style="color:${ptCol};">${ptLbl}${ptUpdated ? `<span style="font-size:9px;color:#444;margin-left:4px;">${ptUpdated}</span>` : ''}</span>
  </div>`;

  if (pt.reason) {
    body += `<div style="font-size:10px;color:#555;margin-top:3px;text-align:right;">${pt.reason}</div>`;
  }

  return `<div class="vv-pt-node${node.is_me ? ' me' : ''}">
    <div class="vv-pt-node-head">
      <div>
        <div class="vv-pt-hostname">${node.hostname}</div>
        <div class="vv-pt-slot">${node.id}</div>
      </div>
      <div class="vv-pt-tags">${tags}</div>
    </div>
    ${body}
  </div>`;
}

// ── Actions ───────────────────────────────────────────────────────────────────

function _renderActions(nodes, cfg) {
  // Onboard: only show when partnership is disabled (not yet set up)
  // Offboard: only when enabled
  // Transfer: only when enabled + we are owner
  const isOwner   = nodes.some(n => n.is_me && n.is_owner);
  const remotes   = nodes.filter(n => !n.is_me);
  const remoteOpts = remotes.map(n =>
    `<option value="${n.slot}">${n.id} — ${n.hostname}</option>`).join('');

  const hasPartner = remotes.length > 0 && remotes.some(n => n.hostname);

  let html = '<div class="vv-pt-actions">';

  // Onboard — disabled until a partner hostname is configured in master.conf
  html += `<button class="vv-pt-action-btn run" onclick="vvPtOnboard(this)"
    ${!hasPartner ? 'disabled title="Add partner hostname to master.conf first (Scheduler → master.conf)"' :
                    'title="Run partnership_onboard.sh — auto-detects role (run on mirror first, then owner)"'}
    ${!hasPartner ? 'style="opacity:.35;cursor:default;"' : ''}>
    ▶ Onboard
  </button>`;

  // Offboard
  html += `<button class="vv-pt-action-btn warn" onclick="vvPtOffboard(this)"
    ${!cfg.enabled ? 'title="No active partnership to offboard" style="opacity:.35;cursor:default;"' : ''}>
    ▶ Offboard
  </button>`;

  html += '</div>';

  // Contextual note under actions
  if (!hasPartner) {
    html += `<div style="font-size:11px;color:#444;margin-top:8px;">
      No partner hostname configured. Edit master.conf (Scheduler tab) and set HOST2.
    </div>`;
  } else if (!cfg.enabled) {
    html += `<div style="font-size:11px;color:#555;margin-top:8px;">
      Onboard will generate your SSH key, exchange it with the partner, and establish the partnership.
      Run on the mirror (HOST2) first, then on the owner (HOST1).
    </div>`;
  }

  // Transfer — show manual command, too destructive to one-click
  if (cfg.enabled && isOwner) {
    const confirmStr = 'i-understand-this-transfers-ownership';
    html += `<div style="margin-top:14px;padding-top:10px;border-top:1px solid #1e1e1e;">
      <span style="font-size:11px;color:#555;">Transfer ownership — run manually from the current owner:</span>
      <div class="vv-pt-transfer-note" style="margin-top:4px;padding:6px 10px;background:#111;border-radius:4px;color:#666;">
        bash Partnership/partnership_transfer.sh --confirm=${confirmStr}
      </div>
    </div>`;
  }

  return html;
}

// ── Main render ───────────────────────────────────────────────────────────────

function _render(data) {
  const cfg   = data.config || {};
  const nodes = data.nodes  || [];

  // Config bar
  document.getElementById('vv-pt-config-body').innerHTML = _renderConfig(cfg);

  // Node grid — columns based on count
  const cols = nodes.length <= 2 ? nodes.length : nodes.length <= 4 ? 2 : 3;
  const grid = document.getElementById('vv-pt-nodes');
  grid.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
  grid.innerHTML = nodes.length
    ? nodes.map(_nodeCard).join('')
    : '<div style="color:#444;font-size:12px;padding:12px 0;">No hosts found in master.conf.</div>';

  // Actions
  document.getElementById('vv-pt-actions-body').innerHTML = _renderActions(nodes, cfg);

  // Highlight Onboard button when arriving from first-run wizard
  if (new URLSearchParams(location.search).get('vv_onboard') === '1') {
    const onboardBtn = document.querySelector('#vv-pt-actions-body .vv-pt-action-btn.run');
    if (onboardBtn) {
      onboardBtn.classList.add('vv-pt-onboard-highlight');
      setTimeout(() => onboardBtn.scrollIntoView({behavior: 'smooth', block: 'center'}), 200);
    }
  }

  // Timestamp
  const ts = data.ts ? new Date(data.ts * 1000).toLocaleString([],
    {month:'numeric',day:'numeric',year:'numeric',hour:'2-digit',minute:'2-digit',second:'2-digit'}) : '';
  document.getElementById('vv-pt-ts').textContent = ts ? 'Updated: ' + ts : '';
}

// ── Actions ───────────────────────────────────────────────────────────────────

function vvPtOnboard(btn) {
  if (!confirm('Run partnership_onboard.sh?\n\nRun on the MIRROR first, then on the OWNER.')) return;
  btn.disabled = true;
  btn.textContent = '⟳ Starting…';
  vvRunById('Partnership/partnership_onboard.sh');
  setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Onboard'; }, 4000);
}

function vvPtOffboard(btn) {
  if (btn.style.opacity === '0.35' || btn.style.cursor === 'default') return;
  if (!confirm('Run partnership_offboard.sh?\n\nThis will end the partnership, reconfigure WebUIs, and revoke SSH access.\n\nContinue?')) return;
  btn.disabled = true;
  btn.textContent = '⟳ Starting…';
  vvRunById('Partnership/partnership_offboard.sh');
  setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Offboard'; }, 4000);
}

// ── Poll ──────────────────────────────────────────────────────────────────────

function vvPtLoad() {
  fetch('/plugins/varaverk/api/partnership.php')
    .then(r => r.json())
    .then(_render)
    .catch(() => {});
}

vvPtLoad();
setInterval(vvPtLoad, 10000);

})();
</script>
