(function () {
  const params = new URLSearchParams(window.location.search);
  const accessToken = params.get('access_token') || '';
  const apiBase =
    document.querySelector('meta[name="omnl-api-base"]')?.getAttribute('content')?.trim() || '/api/v1';

  const els = {
    status: document.getElementById('load-status'),
    grid: document.getElementById('posture-grid'),
    actions: document.getElementById('pending-actions'),
    evidence: document.getElementById('evidence-kv'),
    safe: document.getElementById('safe-kv'),
    external: document.getElementById('external-kv'),
    triple: document.getElementById('triple-summary'),
    hoLiquidity: document.getElementById('ho-liquidity-kv'),
    signoffs: document.getElementById('signoffs-summary'),
    raw: document.getElementById('raw-json'),
    refreshed: document.getElementById('refreshed-at'),
  };

  function apiHeaders() {
    const h = { Accept: 'application/json' };
    if (accessToken) h.Authorization = 'Bearer ' + accessToken;
    return h;
  }

  function apiUrl(path) {
    const base = apiBase.replace(/\/$/, '');
    const rel = path.startsWith('/') ? path : '/' + path;
    const u = new URL(base + rel, window.location.origin);
    if (accessToken) u.searchParams.set('access_token', accessToken);
    return u.toString();
  }

  function badge(ok, okLabel, badLabel) {
    if (ok === true) return '<span class="badge ok">' + okLabel + '</span>';
    if (ok === false) return '<span class="badge bad">' + badLabel + '</span>';
    return '<span class="badge neutral">Unknown</span>';
  }

  function sevBadge(sev) {
    const map = { critical: 'bad', high: 'bad', medium: 'warn', low: 'neutral' };
    return '<span class="badge ' + (map[sev] || 'neutral') + '">' + sev + '</span>';
  }

  function renderPosture(data) {
    const p = data.posture || {};
    els.grid.innerHTML = [
      card('Reporting', badge(p.reportingCompliant, 'Compliant', 'Not compliant'), ''),
      card('Attestation', badge(!p.attestationStale, 'Fresh', 'Stale'), ''),
      card('Triple reconcile', badge(p.tripleAligned, 'Aligned', 'Breaks'), ''),
      card('Notary gate', badge(p.requireNotarizedEvidence, 'Enforced', 'Not enforced'), 'requireNotarizedEvidence'),
      card('Threshold', '<div class="metric">' + (p.complianceThreshold || '—') + '</div>', 'IPSAS / IFRS / US GAAP'),
      card('Policy v', '<div class="metric">' + (p.jurisdictionPolicyVersion ?? '—') + '</div>', 'ID jurisdiction'),
    ].join('');
  }

  function card(title, body, sub) {
    return (
      '<div class="card"><h2>' +
      title +
      '</h2>' +
      body +
      (sub ? '<small style="color:var(--muted);font-size:0.78rem">' + sub + '</small>' : '') +
      '</div>'
    );
  }

  function renderActions(actions) {
    if (!actions || !actions.length) {
      els.actions.innerHTML = '<p style="color:var(--muted)">No pending actions.</p>';
      return;
    }
    els.actions.innerHTML =
      '<ul class="actions-list">' +
      actions
        .map(function (a) {
          const links = (a.links || [])
            .map(function (l) {
              const href = l.href.startsWith('http') ? l.href : apiUrl(l.href);
              const dl = l.href.indexOf('safe-notary-gate-tx') >= 0 ? ' download="omnl-safe-notary-gate-tx.json"' : '';
              return '<a href="' + href + '"' + dl + '>' + l.label + '</a>';
            })
            .join('');
          return (
            '<li><h3>' +
            sevBadge(a.severity) +
            ' ' +
            esc(a.title) +
            '</h3><p>' +
            esc(a.detail) +
            '</p><div class="link-row">' +
            links +
            '</div></li>'
          );
        })
        .join('') +
      '</ul>';
  }

  function kv(rows) {
    return (
      '<dl class="kv">' +
      rows
        .map(function (r) {
          return '<dt>' + esc(r[0]) + '</dt><dd>' + esc(String(r[1] ?? '—')) + '</dd>';
        })
        .join('') +
      '</dl>'
    );
  }

  function renderEvidence(data) {
    const pr = data.proofReport;
    const gate = data.onChainGate || {};
    const triple = data.tripleReconcile;
    els.evidence.innerHTML = kv([
      ['Evidence hash', pr && pr.evidenceHash],
      ['Merkle root', pr && pr.merkleRoot],
      ['Package 3-of-3', pr && pr.packageNotarized3of3],
      ['Reserve 3-of-3', pr && pr.reserveAttested3of3],
      ['Reserve store', gate.reserveStore],
      ['Notary registry', gate.notaryRegistry],
      ['Attestation threshold', gate.attestationThreshold],
      ['On-chain R', triple && triple.onChain && triple.onChain.r],
    ]);
  }

  function renderSafe(data) {
    const pr = data.proofReport;
    const g = (pr && pr.gnosisSafe) || {};
    const sw = data.safeWallet || {};
    els.safe.innerHTML = kv([
      ['Admin Safe', g.address || data.web3.deployed.GnosisSafeAdmin],
      ['Threshold', g.threshold ? g.threshold + '-of-' + g.owners : '—'],
      ['Safe Wallet registry', sw.npmRegistryHas138 ? 'chain 138 listed' : 'pending PR #1568'],
      ['Registry status', sw.status],
    ]);
  }

  function renderExternal(data) {
    const ev = data.externalVisibility || {};
    els.external.innerHTML = kv([
      ['DefiLlama chain', ev.defiLlama && ev.defiLlama.chainPage],
      ['Pricing PR', ev.defiLlama && ev.defiLlama.pr12094],
      ['Bridge TVL PR', ev.defiLlama && ev.defiLlama.pr19451],
      ['Safe deployments PR', ev.safeDeployments && ev.safeDeployments.pr1568],
    ]);
  }

  function renderHoLiquidity(snap) {
    if (!els.hoLiquidity) return;
    if (!snap) {
      els.hoLiquidity.textContent = 'HO liquidity snapshot unavailable.';
      return;
    }
    const cash = snap.cashInBank || {};
    const cov = snap.reserveCoverage || {};
    els.hoLiquidity.innerHTML = kv([
      ['Generated', snap.generatedAt],
      ['Nostro cash (GL 13010)', cash.cashInBankUsd != null ? '$' + Number(cash.cashInBankUsd).toLocaleString() : '—'],
      ['Reserve coverage', cov.coverageRatio != null ? cov.coverageRatio.toFixed(2) + '×' : '—'],
      ['Reserve assets', cov.reserveAssetsUsd != null ? '$' + Number(cov.reserveAssetsUsd).toLocaleString() : '—'],
      ['Issued c* USD', cov.issuedCStarUsd != null ? '$' + Number(cov.issuedCStarUsd).toLocaleString() : '—'],
      ['Public API', '/token-aggregation/api/v1/omnl/ho-liquidity-snapshot'],
    ]);
  }

  function renderTriple(data) {
    const t = data.tripleReconcile;
    if (!t) {
      els.triple.textContent = 'Triple-state reconcile unavailable.';
      return;
    }
    const breaks = (t.breaks || []).length;
    els.triple.innerHTML =
      badge(t.aligned, 'Aligned', breaks + ' break(s)') +
      ' <span style="color:var(--muted);margin-left:0.5rem;font-size:0.88rem">line ' +
      esc(t.lineId).slice(0, 18) +
      '…</span>';
  }

  function renderSignoffs(data) {
    const s = data.signoffs || {};
    els.signoffs.innerHTML = '<pre class="raw" style="max-height:10rem">' + esc(JSON.stringify(s, null, 2)) + '</pre>';
  }

  function esc(s) {
    return String(s)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;');
  }

  function setStatus(kind, msg) {
    els.status.className = 'status-bar ' + kind;
    els.status.textContent = msg;
  }

  async function load() {
    setStatus('loading', 'Loading compliance console…');
    try {
      const res = await fetch(apiUrl('/omnl/compliance/console'), { headers: apiHeaders() });
      const text = await res.text();
      let data;
      try {
        data = JSON.parse(text);
      } catch {
        throw new Error(res.status + ' — non-JSON response');
      }
      if (!res.ok) throw new Error(data.error || res.statusText);

      renderPosture(data);
      renderActions(data.pendingActions);
      renderEvidence(data);
      renderSafe(data);
      renderExternal(data);
      renderTriple(data);
      try {
        const hoRes = await fetch(apiUrl('/omnl/ho-liquidity-snapshot'), { headers: apiHeaders() });
        if (hoRes.ok) renderHoLiquidity(await hoRes.json());
      } catch (_) {
        renderHoLiquidity(null);
      }
      renderSignoffs(data);
      els.raw.textContent = JSON.stringify(data, null, 2);
      els.refreshed.textContent = 'Updated ' + new Date(data.generatedAt).toLocaleString();
      setStatus('ok', 'Live — ' + data.pendingActions.length + ' pending action(s)');
    } catch (e) {
      setStatus('error', 'Failed to load: ' + (e && e.message ? e.message : e));
    }
  }

  document.getElementById('btn-refresh').addEventListener('click', load);
  document.getElementById('btn-download-safe').addEventListener('click', function () {
    window.location.href = apiUrl('/omnl/compliance/safe-notary-gate-tx');
  });
  document.getElementById('btn-toggle-raw').addEventListener('click', function () {
    document.getElementById('raw-section').classList.toggle('hidden');
  });

  load();
})();
