/* ═══════════════════════════════════════════════════════════════════════════
   WCAHT Wallet Extension – Popup Logic
   ═══════════════════════════════════════════════════════════════════════════ */

const KAK_PER_WCAHT = 1_000_000_000;
let currentView = 'lock';
let walletState = {};
let txHistory = [];
let balanceInterval = null;
let dashboardToken = null;  // JWT from dashboard auth
let currentBalanceParts = { native: 0, evm: 0, total: 0 };
let pendingWalletBackup = null;
let backupActionTaken = false;
const DASH_PROFILE_WALLETS_KEY = 'wcaht_dash_profile_wallets';

function shortAddress(addr, head = 8, tail = 6) {
  const s = String(addr || '');
  if (!s || s === '—') return '—';
  return s.length <= head + tail + 1 ? s : s.slice(0, head) + '…' + s.slice(-tail);
}

function normalizeRecipientAddress(address) {
  const s = String(address || '').trim();
  return /^0x[0-9a-fA-F]{40}$/.test(s) ? s.toLowerCase() : s;
}

function isEvmAddress(address) {
  return /^0x[0-9a-fA-F]{40}$/.test(String(address || '').trim());
}

function looksBase58Address(address) {
  return /^[1-9A-HJ-NP-Za-km-z]{32,50}$/.test(String(address || '').trim());
}

function isValidWalletRecipient(address) {
  const s = String(address || '').trim();
  return isEvmAddress(s) || looksBase58Address(s);
}

async function fetchKakBalance(rpcUrl, address) {
  if (!address || address === '—') return 0;
  const resp = await fetch(rpcUrl + '/balance/' + encodeURIComponent(address));
  const text = await resp.text();
  try {
    const parsed = JSON.parse(text);
    return typeof parsed === 'number' ? parsed : (parsed.balance || 0);
  } catch {
    return parseInt(text.trim(), 10) || 0;
  }
}

function formatWcaht(kak, digits = 4) {
  return (Number(kak || 0) / KAK_PER_WCAHT).toFixed(digits);
}

// ── Messaging ───────────────────────────────────────────────────────────────
function sendMsg(msg) {
  return new Promise((resolve) => {
    chrome.runtime.sendMessage(msg, (resp) => {
      resolve(resp || { error: 'No response' });
    });
  });
}

function loadDashProfileWalletMap() {
  try {
    const parsed = JSON.parse(localStorage.getItem(DASH_PROFILE_WALLETS_KEY) || '{}');
    return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
  } catch {
    return {};
  }
}

function saveDashProfileWalletMap(map) {
  localStorage.setItem(DASH_PROFILE_WALLETS_KEY, JSON.stringify(map || {}));
}

function currentDashProfileAddress() {
  return localStorage.getItem('wcaht_dash_addr') || '';
}

function rememberDashWallet(publicKey, profileAddr = currentDashProfileAddress()) {
  if (!profileAddr || !publicKey) return;
  const map = loadDashProfileWalletMap();
  const existing = Array.isArray(map[profileAddr]) ? map[profileAddr] : [];
  map[profileAddr] = Array.from(new Set([profileAddr, ...existing, publicKey]));
  saveDashProfileWalletMap(map);
}

function forgetDashWallet(publicKey) {
  if (!publicKey) return;
  const map = loadDashProfileWalletMap();
  let changed = false;
  for (const profileAddr of Object.keys(map)) {
    const list = Array.isArray(map[profileAddr]) ? map[profileAddr] : [];
    const next = list.filter(addr => addr === profileAddr || addr !== publicKey);
    if (next.length !== list.length) {
      map[profileAddr] = next;
      changed = true;
    }
  }
  if (changed) saveDashProfileWalletMap(map);
}

function walletsForDashProfile(wallets) {
  const profileAddr = currentDashProfileAddress();
  if (!profileAddr) return wallets;
  const map = loadDashProfileWalletMap();
  if (!Array.isArray(map[profileAddr]) || map[profileAddr].length === 0) {
    map[profileAddr] = Array.from(new Set([profileAddr, ...wallets.map(w => w.publicKey).filter(Boolean)]));
    saveDashProfileWalletMap(map);
  }
  const allowed = new Set(map[profileAddr]);
  return wallets.filter(w => allowed.has(w.publicKey));
}

// ── Init ────────────────────────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', async () => {
  wireUpButtons();

  const resp = await sendMsg({ type: 'GET_STATE' });
  walletState = resp;

  if (!resp.hasWallet && !resp.locked) {
    // No password set yet → show setup
    showSetupMode();
  } else if (resp.locked) {
    showLockScreen();
  } else {
    showMainScreen();
  }
});

// ── Wire up all button click handlers (CSP-safe, no inline onclick) ─────────
function wireUpButtons() {
  const on = (id, fn) => { const el = document.getElementById(id); if (el) el.addEventListener('click', fn); };

  // Lock screen
  on('lockBtn', () => handleLock());
  on('btnForgotPassword', () => openForgotModal());
  on('btnForgotCancel',   () => closeForgotModal());
  on('btnForgotConfirm',  () => handleForgotReset());
  on('btnBackupShow', () => toggleBackupSecret());
  on('btnBackupCopy', () => copyBackupSecret());
  on('btnBackupDownload', () => downloadWalletBackup());
  on('btnBackupContinue', () => confirmWalletBackup());
  document.getElementById('backupConfirmed')?.addEventListener('change', updateBackupContinue);
  // PIN pad wiring
  wirePinPad();
  on('tabPassword', () => switchLockMode('password'));
  on('tabPin',      () => switchLockMode('pin'));

  // Header
  on('btnLockWallet', () => lockWallet());
  document.getElementById('networkSelect').addEventListener('change', () => switchNetwork());

  // No-wallets welcome screen
  on('btnCreateFromEmpty', () => showView('create'));
  on('btnImportFromEmpty', () => showView('import'));

  // Wallet selector
  document.getElementById('walletSelect').addEventListener('change', () => selectWallet());
  on('btnNewWallet', () => showView('create'));
  on('btnManageWallets', () => showView('wallets'));

  // Balance card
  on('btnCopyAddr', () => copyAddress());
  on('btnCopyEvmAddr', () => copyEvmAddress());

  // Action row
  on('btnSend', () => showView('send'));
  on('btnReceive', () => showView('receive'));
  on('btnRefresh', () => refreshBalance());
  // btnAccount handled below (after account view wiring)
  on('btnSettings', () => showView('settings'));

  // Send view
  on('btnBackFromSend', () => showView('wallet'));
  on('btnSendMax', () => sendMax());
  on('sendBtn', () => handleSend());

  // Receive view
  on('btnBackFromRecv', () => showView('wallet'));
  on('btnCopyRecvAddr', () => copyAddress());
  on('btnCopyRecvEvmAddr', () => copyEvmAddress());

  // Create view
  on('btnBackFromCreate', () => showView('wallet'));
  on('btnDoCreate', () => handleCreate());

  // Import view
  on('btnBackFromImport', () => showView('wallet'));
  on('btnDoImport', () => handleImport());

  // Settings view
  on('btnBackFromSettings', () => showView('wallet'));
  on('btnRename', () => renameWallet());
  on('btnSetRpc', () => setCustomRpc());
  on('btnExport', () => exportKey());
  on('btnDelete', () => deleteWallet());
  on('btnChangeAuth', () => openChangeAuthForm());

  // Wallets list view
  on('btnBackFromWallets', () => showView('wallet'));
  on('btnCreateFromList', () => showView('create'));
  on('btnImportFromList', () => showView('import'));

  // Account / Dashboard view
  on('btnBackFromAccount', () => showView('wallet'));
  on('btnDashLogin', () => dashboardLogin());
  on('btnDashLogout', () => dashboardLogout());
  on('btnOpenDashboard', () => openDashboard());

  // btnAccount: if already signed in, go straight to embedded dashboard
  on('btnAccount', null); // overridden below — remove the one wired above
  document.getElementById('btnAccount').onclick = () => {
    const token = localStorage.getItem('wcaht_dash_token');
    if (token) { showDashView(); } else { showView('account'); }
  };

  // Enter key on password field
  document.getElementById('lockPw').addEventListener('keydown', (e) => {
    if (e.key === 'Enter') handleLock();
  });
}

// ── Lock Screen ─────────────────────────────────────────────────────────────
function showSetupMode() {
  document.getElementById('lockScreen').style.display = 'block';
  document.getElementById('mainScreen').style.display = 'none';
  document.getElementById('lockSubtitle').textContent = 'Choose how to secure your wallet';
  document.getElementById('lockPwConfirm').style.display = 'block';
  document.getElementById('lockBtn').textContent = 'Create Password';
  document.getElementById('lockBtn').onclick = handleSetup;
  // Show mode tabs so user can pick Password or PIN
  const tabs = document.getElementById('lsModeTabs');
  if (tabs) tabs.style.display = 'flex';
  // Reset PIN state
  pinBuffer = ''; pinConfirmBuffer = ''; pinSetupPhase = 0;
  switchLockMode('password');
  currentView = 'setup';
}

function showLockScreen() {
  document.getElementById('lockScreen').style.display = 'block';
  document.getElementById('mainScreen').style.display = 'none';
  document.getElementById('lockSubtitle').textContent = 'Enter password to unlock';
  document.getElementById('lockPwConfirm').style.display = 'none';
  document.getElementById('lockBtn').textContent = 'Unlock';
  document.getElementById('lockBtn').onclick = handleUnlock;
  document.getElementById('lockPw').value = '';
  document.getElementById('lockError').textContent = '';
  // Reset PIN state
  pinBuffer = ''; pinSetupPhase = 0;
  switchLockMode('password');
  currentView = 'lock';
}

// ── Lock mode toggle ──────────────────────────────────────────────────────────
function switchLockMode(mode) {
  const isPin = mode === 'pin';
  const tabPw  = document.getElementById('tabPassword');
  const tabPin = document.getElementById('tabPin');
  if (tabPw)  tabPw.classList.toggle('active', !isPin);
  if (tabPin) tabPin.classList.toggle('active', isPin);
  const pwSec  = document.getElementById('lsPasswordSection');
  const pinSec = document.getElementById('lsPinSection');
  if (pwSec)  pwSec.style.display  = isPin ? 'none' : 'block';
  if (pinSec) pinSec.style.display = isPin ? 'block' : 'none';
  const sub = document.getElementById('lockSubtitle');
  if (isPin) {
    pinBuffer = '';
    updatePinDots();
    const pinErr = document.getElementById('pinError');
    if (pinErr) pinErr.textContent = '';
    if (sub) sub.textContent = currentView === 'setup' ? 'Choose a 6-digit PIN' : 'Enter your 6-digit PIN';
    // In setup mode show confirm-password field based on active mode
    if (currentView === 'setup') document.getElementById('lockPwConfirm').style.display = 'none';
  } else {
    if (sub) sub.textContent = currentView === 'setup' ? 'Choose how to secure your wallet' : 'Enter password to unlock';
    if (currentView === 'setup') document.getElementById('lockPwConfirm').style.display = 'block';
  }
}

// ── PIN pad logic ─────────────────────────────────────────────────────────────
let pinBuffer = '';
let pinConfirmBuffer = '';
let pinSetupPhase = 0; // 0=enter first, 1=confirm

function updatePinDots() {
  for (let i = 0; i < 6; i++) {
    const dot = document.getElementById('pd' + i);
    if (dot) dot.classList.toggle('filled', i < pinBuffer.length);
  }
}

function wirePinPad() {
  const okBtn = document.getElementById('pinOk');
  const clrBtn = document.getElementById('pinClear');
  if (okBtn)  okBtn.addEventListener('click', handlePinOk);
  if (clrBtn) clrBtn.addEventListener('click', () => {
    pinBuffer = pinBuffer.slice(0, -1);
    updatePinDots();
    const pinErr = document.getElementById('pinError');
    if (pinErr) pinErr.textContent = '';
  });
  document.querySelectorAll('.pin-key[data-v]').forEach(btn => {
    btn.addEventListener('click', () => {
      if (pinBuffer.length >= 6) return;
      pinBuffer += btn.dataset.v;
      updatePinDots();
      if (pinBuffer.length === 6) setTimeout(handlePinOk, 120);
    });
  });
}

async function handlePinOk() {
  const errEl = document.getElementById('pinError');
  if (!errEl) return;
  if (pinBuffer.length < 6) {
    errEl.textContent = 'Enter all 6 digits';
    return;
  }

  if (currentView === 'setup') {
    // First-time setup — PIN becomes the vault password (prefixed)
    if (pinSetupPhase === 0) {
      pinConfirmBuffer = pinBuffer;
      pinBuffer = '';
      updatePinDots();
      document.getElementById('lockSubtitle').textContent = 'Confirm your 6-digit PIN';
      pinSetupPhase = 1;
      return;
    }
    if (pinBuffer !== pinConfirmBuffer) {
      errEl.textContent = 'PINs do not match — try again';
      pinBuffer = ''; pinConfirmBuffer = ''; pinSetupPhase = 0;
      updatePinDots();
      document.getElementById('lockSubtitle').textContent = 'Choose a 6-digit PIN';
      return;
    }
    const resp = await sendMsg({ type: 'SETUP_PASSWORD', password: '__PIN__' + pinBuffer });
    if (resp.error) { errEl.textContent = resp.error; pinBuffer = ''; updatePinDots(); return; }
    pinBuffer = ''; pinSetupPhase = 0;
    showMainScreen();
  } else {
    // Unlock — first try PIN-encrypted-password path, fallback to direct PIN password
    const appState = await sendMsg({ type: 'GET_STATE' });
    let resp;
    if (appState.pinEncryptedPassword) {
      resp = await sendMsg({ type: 'UNLOCK_WITH_PIN', pin: pinBuffer });
    } else {
      // Legacy: user set up initially with PIN as password
      resp = await sendMsg({ type: 'UNLOCK', password: '__PIN__' + pinBuffer });
    }
    if (resp.error) {
      errEl.textContent = 'Incorrect PIN';
      pinBuffer = ''; updatePinDots();
      return;
    }
    pinBuffer = '';
    showMainScreen();
  }
}

async function handleSetup() {
  const pw = document.getElementById('lockPw').value;
  const pw2 = document.getElementById('lockPwConfirm').value;
  const errEl = document.getElementById('lockError');

  if (pw.length < 6) { errEl.textContent = 'Password must be at least 6 characters'; errEl.className = 'error-msg error'; return; }
  if (pw !== pw2) { errEl.textContent = 'Passwords do not match'; errEl.className = 'error-msg error'; return; }

  const resp = await sendMsg({ type: 'SETUP_PASSWORD', password: pw });
  if (resp.error) { errEl.textContent = resp.error; errEl.className = 'error-msg error'; return; }

  showMainScreen();
}

async function handleUnlock() {
  const pw = document.getElementById('lockPw').value;
  const errEl = document.getElementById('lockError');

  if (!pw) { errEl.textContent = 'Enter your password'; errEl.className = 'error-msg error'; return; }

  const resp = await sendMsg({ type: 'UNLOCK', password: pw });
  if (resp.error) { errEl.textContent = resp.error; errEl.className = 'error-msg error'; return; }

  showMainScreen();
}

// Alias for HTML onclick
function handleLock() {
  if (currentView === 'setup') handleSetup();
  else handleUnlock();
}

async function lockWallet() {
  await sendMsg({ type: 'LOCK' });
  clearInterval(balanceInterval);
  showLockScreen();
}

// ── Forgot Password ──────────────────────────────────────────────────────────
function openForgotModal() {
  document.getElementById('fpConfirmInput').value = '';
  document.getElementById('fpSeedError').textContent = '';
  document.getElementById('btnForgotConfirm').disabled = false;
  document.getElementById('btnForgotConfirm').textContent = 'Erase & Reset';
  document.getElementById('forgotModal').style.display = 'flex';
}

function closeForgotModal() {
  document.getElementById('forgotModal').style.display = 'none';
}

async function handleForgotReset() {
  const confirmed = document.getElementById('fpConfirmInput').value.trim();
  const errEl     = document.getElementById('fpSeedError');
  const btn       = document.getElementById('btnForgotConfirm');
  errEl.textContent = '';

  if (confirmed !== 'RESET') {
    errEl.textContent = 'Type RESET (uppercase) to confirm.';
    return;
  }

  btn.disabled = true;
  btn.textContent = 'Resetting…';

  await sendMsg({ type: 'RESET_VAULT' });
  closeForgotModal();
  btn.textContent = 'Erase & Reset';

  // Go to setup screen so user can create a new password and re-import their key
  showSetupMode();
  document.getElementById('lockPw').value = '';
  document.getElementById('lockPwConfirm').value = '';
  document.getElementById('lockError').textContent = '✓ Wallet reset. Create a new password, then import your private key.';
  document.getElementById('lockError').className = 'error-msg success';
}

function showSetupScreen() {
  document.getElementById('lockScreen').style.display = 'block';
  document.getElementById('mainScreen').style.display = 'none';
  document.getElementById('lockSubtitle').textContent = 'Set a new password';
  document.getElementById('lockPwConfirm').style.display = 'block';
  document.getElementById('lockBtn').textContent = 'Create Password';
  document.getElementById('lockBtn').onclick = handleSetup;
  document.getElementById('lockPw').value = '';
  document.getElementById('lockPwConfirm').value = '';
  currentView = 'setup';
}

// ── Main Screen ─────────────────────────────────────────────────────────────
async function showMainScreen() {
  document.getElementById('lockScreen').style.display = 'none';
  document.getElementById('mainScreen').style.display = 'block';
  currentView = 'main';

  await loadWallets();
  updateNetStatus();
  loadTxHistory();

  // Auto-refresh
  balanceInterval = setInterval(() => {
    refreshBalance();
    updateNetStatus();
  }, 10000);
}

async function loadWallets() {
  const resp = await sendMsg({ type: 'GET_WALLETS' });
  if (resp.error) return;

  const wallets = resp.wallets || [];

  if (wallets.length === 0) {
    document.getElementById('noWallets').style.display = 'block';
    document.getElementById('walletView').style.display = 'none';
    return;
  }

  document.getElementById('noWallets').style.display = 'none';
  document.getElementById('walletView').style.display = 'block';

  // Populate selector
  const sel = document.getElementById('walletSelect');
  sel.innerHTML = '';
  for (const w of wallets) {
    const opt = document.createElement('option');
    opt.value = w.id;
    const badge = w.evmAddress ? shortAddress(w.evmAddress, 6, 4) : 'legacy ' + w.publicKey.slice(0, 6) + '…';
    opt.textContent = w.name + ' (' + badge + ')';
    sel.appendChild(opt);
  }

  // Select active
  const stateResp = await sendMsg({ type: 'GET_STATE' });
  if (stateResp.activeWallet) {
    sel.value = stateResp.activeWallet.id || '';
  }

  await refreshBalance();
  updateAddress();
  if (stateResp.activeWallet?.backupRequired) await openWalletBackup(stateResp.activeWallet);
}

async function selectWallet() {
  const id = document.getElementById('walletSelect').value;
  await sendMsg({ type: 'SELECT_WALLET', walletId: id });
  await refreshBalance();
  updateAddress();
}

function renderQR(address) {
  const canvas = document.getElementById('qrCode');
  if (!canvas || !address || typeof qrcode === 'undefined') return;
  try {
    const qr = qrcode(0, 'M');
    qr.addData(address);
    qr.make();
    const size = canvas.parentElement.clientWidth - 16 || 164;
    canvas.width = size;
    canvas.height = size;
    const ctx = canvas.getContext('2d');
    const cells = qr.getModuleCount();
    const cellSize = size / cells;
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, size, size);
    ctx.fillStyle = '#111827';
    for (let row = 0; row < cells; row++) {
      for (let col = 0; col < cells; col++) {
        if (qr.isDark(row, col)) {
          ctx.fillRect(col * cellSize, row * cellSize, cellSize, cellSize);
        }
      }
    }
  } catch (e) { /* ignore */ }
}

function updateAddress() {
  const sel = document.getElementById('walletSelect');
  const opt = sel.selectedOptions[0];
  if (!opt) return;

  // Get address from currently loaded wallets
  sendMsg({ type: 'GET_STATE' }).then(resp => {
    const w = resp.activeWallet;
    if (w) {
      document.getElementById('addrText').textContent = w.publicKey;
      const evmText = document.getElementById('evmAddrText');
      if (evmText) evmText.textContent = w.evmAddress || 'Legacy wallet: no paired 0x address';
      document.getElementById('recvAddr').textContent = w.publicKey;
      const recvEvm = document.getElementById('recvEvmAddr');
      if (recvEvm) recvEvm.textContent = w.evmAddress || 'Legacy wallet: no paired 0x address';
      renderQR(w.publicKey);
    }
  });
}

async function refreshBalance() {
  const st = await sendMsg({ type: 'GET_STATE' });
  const wallet = st.activeWallet;
  if (!wallet?.publicKey) {
    currentBalanceParts = { native: 0, evm: 0, total: 0 };
    document.getElementById('balMain').textContent = '0.0000 WCAHT';
    document.getElementById('balKak').textContent = 'Native 0.0000 • EVM 0.0000 • Total 0.0000';
    return;
  }

  try {
    const parts = await sendMsg({ type: 'GET_BALANCE_PARTS' });
    if (parts.error) throw new Error(parts.error);
    currentBalanceParts = { native: parts.native || 0, evm: parts.evm || 0, total: parts.total || 0 };
    const wcaht = formatWcaht(currentBalanceParts.total);
    document.getElementById('balMain').textContent = wcaht + ' WCAHT';
    const sub = wallet.evmAddress
      ? `Native ${formatWcaht(currentBalanceParts.native)} • EVM ${formatWcaht(currentBalanceParts.evm)} • Total ${wcaht}`
      : `Native ${formatWcaht(currentBalanceParts.native)} • Total ${wcaht}`;
    document.getElementById('balKak').textContent = sub;
    document.getElementById('sendAvailable').textContent = wallet.evmAddress
      ? `Native ${formatWcaht(currentBalanceParts.native)} • EVM ${formatWcaht(currentBalanceParts.evm)} • Total ${wcaht}`
      : `Native ${formatWcaht(currentBalanceParts.native)} WCAHT`;
  } catch {
    currentBalanceParts = { native: 0, evm: 0, total: 0 };
    document.getElementById('balMain').textContent = 'Offline';
    document.getElementById('balKak').textContent = '—';
  }
}

async function updateNetStatus() {
  const dot = document.getElementById('netDot');
  const statusEl = document.getElementById('nodeStatus');
  const st = await sendMsg({ type: 'GET_STATE' });
  const rpcUrl = st.network?.rpcUrl || 'https://dashboard.denvion.com/node';

  try {
    // Fetch status directly from node
    const resp = await fetch(rpcUrl + '/status');
    const data = await resp.json();
    dot.classList.remove('offline');
    statusEl.textContent = `Block ${data.block_height || 0} • Slot ${data.slot || 0} • ${data.peers?.connected || 0} peers`;
  } catch {
    dot.classList.add('offline');
    statusEl.textContent = 'Node offline';
  }
}

// ── View Navigation ─────────────────────────────────────────────────────────
function showView(view) {
  const views = ['walletView', 'sendView', 'receiveView', 'createView', 'importView', 'settingsView', 'noWallets', 'walletsView', 'accountView'];
  for (const v of views) {
    const el = document.getElementById(v);
    if (el) el.style.display = 'none';
  }

  switch (view) {
    case 'wallet':
      loadWallets();
      break;
    case 'wallets':
      document.getElementById('walletsView').style.display = 'block';
      renderWalletsList();
      break;
    case 'account': {
      // If already signed in → show embedded dashboard directly
      const _tok = localStorage.getItem('wcaht_dash_token');
      if (_tok) {
        showDashView();
        return;
      }
      document.getElementById('accountView').style.display = 'block';
      loadAccountState();
      break;
    }
    case 'send':
      document.getElementById('sendView').style.display = 'block';
      document.getElementById('sendTo').value = '';
      document.getElementById('sendAmount').value = '';
      document.getElementById('sendError').textContent = '';
      document.getElementById('sendFee').textContent = 'Native: 0.000005 WCAHT; EVM: calculated at MAX/send';
      document.getElementById('sendFundingSource').textContent = 'Native is used first; EVM is used when native funds are insufficient.';
      refreshBalance();
      break;
    case 'receive':
      document.getElementById('receiveView').style.display = 'block';
      updateAddress();
      break;
    case 'create':
      document.getElementById('createView').style.display = 'block';
      document.getElementById('createName').value = '';
      document.getElementById('createError').textContent = '';
      break;
    case 'import':
      document.getElementById('importView').style.display = 'block';
      document.getElementById('importName').value = '';
      document.getElementById('importKey').value = '';
      document.getElementById('importError').textContent = '';
      break;
    case 'settings':
      document.getElementById('settingsView').style.display = 'block';
      document.getElementById('settingsMsg').textContent = '';
      document.getElementById('settChangeAuthForm').style.display = 'none';
      // Populate current name and auth method label
      sendMsg({ type: 'GET_STATE' }).then(resp => {
        if (resp.activeWallet) {
          document.getElementById('settWalletName').value = resp.activeWallet.name || '';
        }
        const label = document.getElementById('settAuthLabel');
        if (label) {
          const onPin = resp.primaryAuthMethod === 'pin' || resp.pinEncryptedPassword;
          label.textContent = onPin ? 'Login Method: PIN' : 'Login Method: Password';
        }
      });
      break;
  }
}

// ── Create Wallet ───────────────────────────────────────────────────────────
async function handleCreate() {
  const name = document.getElementById('createName').value.trim() || 'Wallet';
  const errEl = document.getElementById('createError');

  const resp = await sendMsg({ type: 'CREATE_WALLET', name });
  if (resp.error) { errEl.textContent = resp.error; errEl.className = 'error-msg error'; return; }

  rememberDashWallet(resp.publicKey);
  await openWalletBackup({
    id: resp.walletId,
    name,
    publicKey: resp.publicKey,
    scheme: resp.scheme,
    evmAddress: resp.evmAddress,
    backupRequired: true,
  });
}

async function openWalletBackup(wallet) {
  if (!wallet?.id || !wallet.backupRequired) return;
  const modal = document.getElementById('backupModal');
  if (modal.style.display === 'flex' && pendingWalletBackup?.walletId === wallet.id) return;

  const exported = await sendMsg({ type: 'EXPORT_KEY', walletId: wallet.id });
  if (exported.error) {
    const errEl = document.getElementById('createError');
    if (errEl) {
      errEl.textContent = 'Wallet was created, but its backup could not be opened: ' + exported.error;
      errEl.className = 'error-msg error';
    }
    return;
  }

  pendingWalletBackup = {
    walletId: wallet.id,
    name: wallet.name || 'WCAHT Wallet',
    scheme: exported.scheme || wallet.scheme || 'secp256k1',
    nativeAddress: wallet.publicKey,
    evmAddress: exported.evmAddress || wallet.evmAddress || null,
    privateKey: exported.privateKey || null,
    secretKey: exported.secretKey,
  };
  backupActionTaken = false;
  document.getElementById('backupNativeAddress').textContent = pendingWalletBackup.nativeAddress;
  document.getElementById('backupEvmAddress').textContent = pendingWalletBackup.evmAddress || 'Legacy native-only wallet';
  document.getElementById('backupSecret').textContent = 'Hidden until you choose Show';
  document.getElementById('btnBackupShow').textContent = 'Show';
  document.getElementById('backupConfirmed').checked = false;
  document.getElementById('backupError').textContent = '';
  updateBackupContinue();
  modal.style.display = 'flex';
}

function backupSecretText() {
  if (!pendingWalletBackup) return '';
  return pendingWalletBackup.privateKey
    ? `EVM private key (recovers both addresses)\n${pendingWalletBackup.privateKey}\n\nBase58 encoding of the same secret\n${pendingWalletBackup.secretKey}`
    : pendingWalletBackup.secretKey;
}

function toggleBackupSecret() {
  if (!pendingWalletBackup) return;
  const secretEl = document.getElementById('backupSecret');
  const showButton = document.getElementById('btnBackupShow');
  const isHidden = showButton.textContent === 'Show';
  secretEl.textContent = isHidden ? backupSecretText() : 'Hidden until you choose Show';
  showButton.textContent = isHidden ? 'Hide' : 'Show';
  if (isHidden) backupActionTaken = true;
  updateBackupContinue();
}

async function copyBackupSecret() {
  if (!pendingWalletBackup) return;
  const secret = pendingWalletBackup.privateKey || pendingWalletBackup.secretKey;
  try {
    await navigator.clipboard.writeText(secret);
    backupActionTaken = true;
    document.getElementById('backupError').textContent = 'Secret copied. Clear your clipboard after storing it securely.';
    updateBackupContinue();
  } catch (e) {
    document.getElementById('backupError').textContent = 'Copy failed: ' + e.message;
  }
}

function downloadWalletBackup() {
  if (!pendingWalletBackup) return;
  const backup = {
    format: 'wcaht-wallet-backup-v1',
    warning: 'Anyone with this file can spend this wallet. Store it offline and never share it.',
    name: pendingWalletBackup.name,
    scheme: pendingWalletBackup.scheme,
    publicKey: pendingWalletBackup.nativeAddress,
    evmAddress: pendingWalletBackup.evmAddress,
    privateKey: pendingWalletBackup.privateKey,
    secretKey: pendingWalletBackup.secretKey,
    createdAt: new Date().toISOString(),
  };
  const blob = new Blob([JSON.stringify(backup, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  const safeName = pendingWalletBackup.name.replace(/[^a-z0-9_-]+/gi, '-').replace(/^-|-$/g, '') || 'wallet';
  link.href = url;
  link.download = `wcaht-${safeName}-backup.json`;
  document.body.appendChild(link);
  link.click();
  link.remove();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
  backupActionTaken = true;
  document.getElementById('backupError').textContent = 'Backup downloaded. Store it somewhere private and offline.';
  updateBackupContinue();
}

function updateBackupContinue() {
  const confirmed = !!document.getElementById('backupConfirmed')?.checked;
  const button = document.getElementById('btnBackupContinue');
  if (button) button.disabled = !(confirmed && backupActionTaken);
}

async function confirmWalletBackup() {
  if (!pendingWalletBackup || !backupActionTaken || !document.getElementById('backupConfirmed').checked) return;
  const result = await sendMsg({ type: 'ACK_WALLET_BACKUP', walletId: pendingWalletBackup.walletId });
  if (result.error) {
    document.getElementById('backupError').textContent = result.error;
    return;
  }
  document.getElementById('backupSecret').textContent = '';
  document.getElementById('backupNativeAddress').textContent = '';
  document.getElementById('backupEvmAddress').textContent = '';
  document.getElementById('backupModal').style.display = 'none';
  pendingWalletBackup = null;
  backupActionTaken = false;
  showToast('Wallet created and recovery backup confirmed', 'success');
  showView('wallet');
}

// ── Import Wallet ───────────────────────────────────────────────────────────
async function handleImport() {
  const name = document.getElementById('importName').value.trim() || 'Imported';
  const key = document.getElementById('importKey').value.trim();
  const errEl = document.getElementById('importError');

  if (!key) { errEl.textContent = 'Enter a secret key'; errEl.className = 'error-msg error'; return; }

  const scheme = /^0x[0-9a-fA-F]{64}$/.test(key) || /^secp256k1:/i.test(key) || /^evm:/i.test(key) ? 'secp256k1' : undefined;
  const resp = await sendMsg({ type: 'IMPORT_WALLET', name, key, scheme });
  if (resp.error) { errEl.textContent = resp.error; errEl.className = 'error-msg error'; return; }

  rememberDashWallet(resp.publicKey);
  showToast(resp.evmAddress ? 'EVM-compatible wallet imported: ' + shortAddress(resp.evmAddress) : 'Legacy wallet imported: ' + shortAddress(resp.publicKey), 'success');
  showView('wallet');
}

// ── Send ────────────────────────────────────────────────────────────────────
async function handleSend() {
  const typedTo = document.getElementById('sendTo').value.trim();
  const to = normalizeRecipientAddress(typedTo);
  const amountStr = document.getElementById('sendAmount').value.trim();
  const errEl = document.getElementById('sendError');
  const btn = document.getElementById('sendBtn');

  if (!typedTo) { errEl.textContent = 'Enter a recipient base58 or EVM 0x address'; errEl.className = 'error-msg error'; return; }
  if (!isValidWalletRecipient(typedTo)) { errEl.textContent = 'Enter a valid WCAHT base58 or EVM 0x address'; errEl.className = 'error-msg error'; return; }
  const amount = parseFloat(amountStr);
  if (!amount || amount <= 0) { errEl.textContent = 'Enter an amount'; errEl.className = 'error-msg error'; return; }

  const amountKak = Math.round(amount * KAK_PER_WCAHT);

  btn.disabled = true;
  btn.textContent = 'Sending…';
  errEl.textContent = '';

  const resp = await sendMsg({ type: 'SEND_TX', to, amount: amountKak });

  btn.disabled = false;
  btn.textContent = 'Send';

  if (resp.error) {
    errEl.textContent = resp.error;
    errEl.className = 'error-msg error';
    return;
  }

  // Save to local history
  saveTxToHistory({
    type: 'send',
    to, amount: amountKak,
    txHash: resp.txHash,
    timestamp: Date.now(),
    status: 'sent',
    fundingSource: resp.fundingSource,
  });

  showToast('Sent ' + amount.toFixed(4) + ' WCAHT from ' + resp.fundingSource + '! TX: ' + (resp.txHash || '').slice(0, 12) + '…', 'success');
  showView('wallet');
  setTimeout(refreshBalance, 2000);
}

async function sendMax() {
  const typedTo = document.getElementById('sendTo').value.trim();
  const to = isValidWalletRecipient(typedTo) ? normalizeRecipientAddress(typedTo) : undefined;
  const errEl = document.getElementById('sendError');
  errEl.textContent = '';
  const quote = await sendMsg({ type: 'GET_MAX_SEND', to });
  if (quote.error) {
    errEl.textContent = quote.error;
    errEl.className = 'error-msg error';
    return;
  }
  document.getElementById('sendAmount').value = (quote.amount / KAK_PER_WCAHT).toFixed(9);
  document.getElementById('sendFee').textContent = `${quote.fundingSource}: ${formatWcaht(quote.fee, 9)} WCAHT (${Number(quote.fee).toLocaleString()} kak)`;
  document.getElementById('sendFundingSource').textContent = `MAX uses the ${quote.fundingSource} account and reserves its fee.`;
}

// ── Settings Actions ────────────────────────────────────────────────────────
async function renameWallet() {
  const name = document.getElementById('settWalletName').value.trim();
  if (!name) return;
  const stateResp = await sendMsg({ type: 'GET_STATE' });
  if (stateResp.activeWallet) {
    await sendMsg({ type: 'RENAME_WALLET', walletId: stateResp.activeWallet.id, name });
    showToast('Renamed to ' + name, 'success');
  }
}

async function setCustomRpc() {
  const url = document.getElementById('settRpcUrl').value.trim();
  if (!url) return;
  await sendMsg({ type: 'SET_NETWORK', name: 'Custom', rpcUrl: url });
  showToast('RPC set to ' + url, 'success');
}

// ── Change Auth Method (Settings) ───────────────────────────────────────────
async function openChangeAuthForm() {
  const st = await sendMsg({ type: 'GET_STATE' });
  // isOnPin = true when vault key IS a PIN (first-time PIN setup) OR when PIN
  // was added on top of a password (pinEncryptedPassword is set)
  const isOnPin = st.primaryAuthMethod === 'pin' || !!st.pinEncryptedPassword;
  // isAddedPin = PIN was added on top of existing password → vault password unchanged
  const isAddedPin = !!st.pinEncryptedPassword;
  const form = document.getElementById('settChangeAuthForm');
  const inner = document.getElementById('settChangeAuthInner');
  const msgEl = document.getElementById('settChangeAuthMsg');
  if (!form || !inner) return;
  msgEl.textContent = '';

  if (isOnPin) {
    // Currently using PIN — offer switch to password
    inner.innerHTML = `
      <p style="font-size:13px;color:var(--text-muted);margin-bottom:8px">
        Currently unlocking with <strong>PIN</strong>. Switch to password-based login?
      </p>
      <input type="password" id="caNewPw" class="input input-sm" placeholder="New password (min 6 chars)" autocomplete="new-password">
      <input type="password" id="caNewPw2" class="input input-sm" style="margin-top:6px" placeholder="Confirm new password" autocomplete="new-password">
      <div style="display:flex;gap:8px;margin-top:8px">
        <button class="btn btn-sm btn-primary" id="caConfirmBtn">Switch to Password</button>
        <button class="btn btn-sm" id="caCancelBtn">Cancel</button>
      </div>`;
    document.getElementById('caConfirmBtn').onclick = async () => {
      const pw = document.getElementById('caNewPw').value;
      const pw2 = document.getElementById('caNewPw2').value;
      if (pw.length < 6) { msgEl.textContent = 'Password must be at least 6 characters'; return; }
      if (pw !== pw2) { msgEl.textContent = 'Passwords do not match'; return; }

      if (isAddedPin) {
        // Scenario B: vault password is unchanged, PIN was just an extra layer
        // Just remove the PIN — user unlocks with their original password
        const rem = await sendMsg({ type: 'REMOVE_PIN' });
        if (rem && rem.error) { msgEl.textContent = rem.error; return; }
        // If they also want a new password, treat as change
        // But the fields say "new password" so re-encrypt if user typed something different
        // For simplicity: re-encrypt with the new password
        const resp = await sendMsg({ type: 'CHANGE_VAULT_PASSWORD', newPassword: pw });
        if (resp && resp.error) { msgEl.textContent = resp.error; return; }
      } else {
        // Scenario A: vault key IS the PIN — must re-encrypt all wallet keys
        const resp = await sendMsg({ type: 'CHANGE_VAULT_PASSWORD', newPassword: pw });
        if (resp && resp.error) { msgEl.textContent = resp.error; return; }
      }

      form.style.display = 'none';
      // Update auth label
      const label = document.getElementById('settAuthLabel');
      if (label) label.textContent = 'Login Method: Password';
      showToast('Switched to password login', 'success');
    };
    document.getElementById('caCancelBtn').onclick = () => { form.style.display = 'none'; };
  } else {
    // Currently using password — offer switch to PIN
    inner.innerHTML = `
      <p style="font-size:13px;color:var(--text-muted);margin-bottom:8px">
        Currently unlocking with <strong>Password</strong>. Switch to 6-digit PIN?
      </p>
      <input type="password" id="caCurPw" class="input input-sm" placeholder="Current password" autocomplete="current-password">
      <input type="text" id="caNewPin" class="input input-sm" style="margin-top:6px" placeholder="New 6-digit PIN" maxlength="6" inputmode="numeric" pattern="[0-9]*">
      <input type="text" id="caNewPin2" class="input input-sm" style="margin-top:6px" placeholder="Confirm PIN" maxlength="6" inputmode="numeric" pattern="[0-9]*">
      <div style="display:flex;gap:8px;margin-top:8px">
        <button class="btn btn-sm btn-primary" id="caConfirmBtn">Switch to PIN</button>
        <button class="btn btn-sm" id="caCancelBtn">Cancel</button>
      </div>`;
    document.getElementById('caConfirmBtn').onclick = async () => {
      const curPw = document.getElementById('caCurPw').value;
      const pin = document.getElementById('caNewPin').value;
      const pin2 = document.getElementById('caNewPin2').value;
      if (!/^\d{6}$/.test(pin)) { msgEl.textContent = 'PIN must be exactly 6 digits'; return; }
      if (pin !== pin2) { msgEl.textContent = 'PINs do not match'; return; }
      const resp = await sendMsg({ type: 'SET_PIN', password: curPw, pin });
      if (resp && resp.error) { msgEl.textContent = resp.error; return; }
      form.style.display = 'none';
      // Update auth label
      const label = document.getElementById('settAuthLabel');
      if (label) label.textContent = 'Login Method: PIN';
      showToast('Switched to PIN login', 'success');
    };
    document.getElementById('caCancelBtn').onclick = () => { form.style.display = 'none'; };
  }

  form.style.display = form.style.display === 'none' ? 'block' : 'none';
}

async function exportKey() {
  if (!confirm('Your private key will be shown. Never share it!')) return;
  const stateResp = await sendMsg({ type: 'GET_STATE' });
  if (!stateResp.activeWallet) return;
  const resp = await sendMsg({ type: 'EXPORT_KEY', walletId: stateResp.activeWallet.id });
  if (resp.error) { document.getElementById('settingsMsg').textContent = resp.error; return; }

  const msgEl = document.getElementById('settingsMsg');
  msgEl.className = 'error-msg';
  const exportText = resp.privateKey
    ? `EVM private key\n${resp.privateKey}\n\nBase58 secret\n${resp.secretKey}`
    : resp.secretKey;
  msgEl.innerHTML = '<div style="white-space:pre-wrap;word-break:break-all;font-family:monospace;font-size:10px;background:var(--bg-input);padding:8px;border-radius:4px;margin-top:8px">' + esc(exportText) + '</div>';
}

async function deleteWallet() {
  if (!confirm('Are you sure? This cannot be undone!')) return;
  if (!confirm('REALLY delete this wallet? Make sure you have your key backed up.')) return;

  const stateResp = await sendMsg({ type: 'GET_STATE' });
  if (!stateResp.activeWallet) return;

  forgetDashWallet(stateResp.activeWallet.publicKey);
  await sendMsg({ type: 'DELETE_WALLET', walletId: stateResp.activeWallet.id });
  showToast('Wallet deleted', 'error');
  showView('wallet');
}

function switchNetwork() {
  const sel = document.getElementById('networkSelect');
  if (sel.value === 'custom') {
    showView('settings');
    return;
  }
  sendMsg({ type: 'SET_NETWORK', name: 'WCAHT Mainnet', rpcUrl: sel.value });
  updateNetStatus();
}

// ── Address Copy ────────────────────────────────────────────────────────────
function copyAddress() {
  const addr = document.getElementById('addrText')?.textContent || document.getElementById('recvAddr')?.textContent;
  if (addr && addr !== '—') {
    navigator.clipboard.writeText(addr);
    showToast('Base58 address copied!', 'success');
  }
}

function copyEvmAddress() {
  const addr = document.getElementById('evmAddrText')?.textContent || document.getElementById('recvEvmAddr')?.textContent;
  if (isEvmAddress(addr)) {
    navigator.clipboard.writeText(addr);
    showToast('EVM 0x address copied!', 'success');
  } else {
    showToast('This legacy wallet has no paired EVM address', 'error');
  }
}

// ── TX History (localStorage) ───────────────────────────────────────────────
function loadTxHistory() {
  try {
    txHistory = JSON.parse(localStorage.getItem('wcaht_ext_txhist') || '[]');
  } catch { txHistory = []; }
  renderTxList();
}

function saveTxToHistory(tx) {
  txHistory.unshift(tx);
  if (txHistory.length > 50) txHistory = txHistory.slice(0, 50);
  localStorage.setItem('wcaht_ext_txhist', JSON.stringify(txHistory));
  renderTxList();
}

function renderTxList() {
  const el = document.getElementById('txList');
  if (!el) return;

  if (txHistory.length === 0) {
    el.innerHTML = '<div class="empty-tx">No transactions yet</div>';
    return;
  }

  let html = '';
  for (const tx of txHistory.slice(0, 20)) {
    const isSend = tx.type === 'send';
    const addr = isSend ? (tx.to || '—') : (tx.from || '—');
    const amtW = (Number(tx.amount || 0) / KAK_PER_WCAHT).toFixed(4);
    const timeStr = tx.timestamp ? timeAgo(tx.timestamp) : '—';

    html += `<div class="tx-item">
      <div class="tx-left">
        <div class="tx-icon ${isSend ? 'send' : 'recv'}">${isSend ? '↑' : '↓'}</div>
        <div>
          <div class="tx-type">${isSend ? 'Sent' : 'Received'}</div>
          <div class="tx-addr">${addr.slice(0, 8)}…${addr.slice(-4)}</div>
        </div>
      </div>
      <div>
        <div class="tx-amount ${isSend ? 'neg' : 'pos'}">${isSend ? '-' : '+'}${amtW}</div>
        <div class="tx-time">${timeStr}</div>
      </div>
    </div>`;
  }
  el.innerHTML = html;
}

function timeAgo(ts) {
  const diff = (Date.now() - ts) / 1000;
  if (diff < 60) return Math.floor(diff) + 's ago';
  if (diff < 3600) return Math.floor(diff / 60) + 'm ago';
  if (diff < 86400) return Math.floor(diff / 3600) + 'h ago';
  return Math.floor(diff / 86400) + 'd ago';
}

// ── Toast ───────────────────────────────────────────────────────────────────
function showToast(msg, type) {
  const el = document.getElementById('toast');
  el.textContent = msg;
  el.className = 'toast show ' + (type || '');
  setTimeout(() => { el.className = 'toast'; }, 3000);
}

// ── Wallets List (All Wallets with Balances) ────────────────────────────────
async function renderWalletsList() {
  const resp = await sendMsg({ type: 'GET_WALLETS' });
  const wallets = resp.wallets || [];
  const stateResp = await sendMsg({ type: 'GET_STATE' });
  const activeId = stateResp.activeWallet?.id;
  const rpcUrl = stateResp.network?.rpcUrl || 'https://dashboard.denvion.com/node';
  const el = document.getElementById('walletsList');

  if (wallets.length === 0) {
    el.innerHTML = '<div class="wl-empty">No wallets yet.<br>Create or import one to get started.</div>';
    return;
  }

  // Render immediately with loading state
  el.innerHTML = wallets.map(w => {
    const isActive = w.id === activeId;
    const letter = (w.name || 'W')[0].toUpperCase();
    return `<div class="wl-item ${isActive ? 'active' : ''}" data-wid="${w.id}">
      ${isActive ? '<div class="wl-active-dot"></div>' : ''}
      <div class="wl-avatar">${letter}</div>
      <div class="wl-info">
        <div class="wl-name">${esc(w.name)}</div>
        <div class="wl-addr">${esc(w.evmAddress ? shortAddress(w.evmAddress) : shortAddress(w.publicKey))}</div>
      </div>
      <div class="wl-bal">
        <div class="wl-bal-main" id="wlbal_${w.id}">…</div>
        <div class="wl-bal-sub" id="wlkak_${w.id}">loading</div>
      </div>
    </div>`;
  }).join('');

  // Click to switch wallet
  el.querySelectorAll('.wl-item').forEach(item => {
    item.addEventListener('click', async () => {
      const wid = item.dataset.wid;
      await sendMsg({ type: 'SELECT_WALLET', walletId: wid });
      showToast('Switched wallet', 'success');
      showView('wallet');
    });
  });

  // Fetch balances in parallel
  const fetchPromises = wallets.map(async w => {
    try {
      const [nativeBal, evmBal] = await Promise.all([
        fetchKakBalance(rpcUrl, w.publicKey),
        w.evmAddress ? fetchKakBalance(rpcUrl, w.evmAddress) : Promise.resolve(0),
      ]);
      const bal = nativeBal + evmBal;

      const mainEl = document.getElementById('wlbal_' + w.id);
      const subEl = document.getElementById('wlkak_' + w.id);
      if (mainEl) mainEl.textContent = formatWcaht(bal) + ' WCAHT';
      if (subEl) subEl.textContent = w.evmAddress ? `N ${formatWcaht(nativeBal)} / E ${formatWcaht(evmBal)}` : Number(bal).toLocaleString() + ' kak';
    } catch {
      const mainEl = document.getElementById('wlbal_' + w.id);
      if (mainEl) mainEl.textContent = 'offline';
    }
  });
  await Promise.all(fetchPromises);
}

function esc(s) {
  const d = document.createElement('div');
  d.textContent = s;
  return d.innerHTML;
}

// ── Dashboard Account Integration ───────────────────────────────────────────
function loadAccountState() {
  // Check if we have a saved dashboard session
  const token = localStorage.getItem('wcaht_dash_token');
  const addr = localStorage.getItem('wcaht_dash_addr');
  const dashUrl = localStorage.getItem('wcaht_dash_url') || 'https://denvion.com';

  document.getElementById('dashboardUrl').value = dashUrl;

  if (token && addr) {
    dashboardToken = token;
    // Already signed in → go straight to embedded dashboard
    showDashView();
  } else {
    showAccountNotLoggedIn();
  }
}

function showAccountLoggedIn(addr) {
  document.getElementById('acctNotLoggedIn').style.display = 'none';
  document.getElementById('acctLoggedIn').style.display = 'block';
  document.getElementById('acctAvatar').textContent = (addr || '?')[0].toUpperCase();
  document.getElementById('acctName').textContent = addr.slice(0, 12) + '…';
  document.getElementById('acctAddr').textContent = addr;
}

function showAccountNotLoggedIn() {
  document.getElementById('acctNotLoggedIn').style.display = 'block';
  document.getElementById('acctLoggedIn').style.display = 'none';
  document.getElementById('acctError').textContent = '';
}

async function dashboardLogin() {
  const errEl = document.getElementById('acctError');
  const dashUrl = document.getElementById('dashboardUrl').value.trim().replace(/\/+$/, '');
  errEl.textContent = '';

  if (!dashUrl) { errEl.textContent = 'Enter dashboard URL'; errEl.className = 'error-msg error'; return; }

  // Get active wallet
  const st = await sendMsg({ type: 'GET_STATE' });
  const wallet = st.activeWallet;
  if (!wallet) { errEl.textContent = 'No active wallet. Create or import one first.'; errEl.className = 'error-msg error'; return; }
  const authAddress = wallet.evmAddress || wallet.publicKey;
  const authScheme = wallet.evmAddress ? 'secp256k1' : 'ed25519';

  errEl.textContent = 'Requesting challenge…';
  errEl.className = 'error-msg';

  try {
    // Step 1: Get challenge nonce from dashboard
    const r1 = await fetch(dashUrl + '/api/auth/challenge', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ address: authAddress }),
    });
    const d1 = await r1.json();
    if (!r1.ok) { errEl.textContent = d1.error || 'Challenge failed'; errEl.className = 'error-msg error'; return; }

    const nonce = d1.nonce;
    errEl.textContent = 'Signing challenge…';

    // Step 2: Sign the nonce with wallet's secret key (service worker decrypts + signs)
    const signResult = await sendMsg({ type: 'SIGN_MESSAGE', message: nonce, walletId: wallet.id });
    if (signResult.error) { errEl.textContent = 'Signing failed: ' + signResult.error; errEl.className = 'error-msg error'; return; }

    // Step 3: Verify signature with dashboard
    const r2 = await fetch(dashUrl + '/api/auth/verify', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ address: authAddress, signature: signResult.signature, scheme: authScheme }),
    });
    const d2 = await r2.json();
    if (!r2.ok) { errEl.textContent = d2.error || 'Verification failed'; errEl.className = 'error-msg error'; return; }

    // Success — save token
    dashboardToken = d2.token;
    localStorage.setItem('wcaht_dash_token', d2.token);
    localStorage.setItem('wcaht_dash_addr', authAddress);
    localStorage.setItem('wcaht_dash_url', dashUrl);
    rememberDashWallet(wallet.publicKey, authAddress);

    showToast('Signed in to Dashboard as ' + shortAddress(authAddress), 'success');
    // Switch directly to embedded dashboard view
    showDashView();
  } catch (e) {
    errEl.textContent = 'Connection failed: ' + e.message;
    errEl.className = 'error-msg error';
  }
}

function dashboardLogout() {
  dashboardToken = null;
  localStorage.removeItem('wcaht_dash_token');
  localStorage.removeItem('wcaht_dash_addr');
  showToast('Signed out from Dashboard', 'success');
  showAccountNotLoggedIn();
}

function openDashboard() {
  // Open embedded dashboard inside popup instead of external tab
  showDashView();
}

// ── Embedded Dashboard View ─────────────────────────────────────────────────
let dashActiveWalletId = null;
let dashWallets = [];
let dashTabsWired = false;

function hideDashView() {
  document.getElementById('dashView').style.display = 'none';
  document.getElementById('mainScreen').style.display = 'block';
  document.body.style.width = '';
}

async function showDashView() {
  document.getElementById('mainScreen').style.display = 'none';
  document.getElementById('lockScreen').style.display = 'none';
  document.getElementById('dashView').style.display = 'block';
  document.body.style.width = '420px';

  const resp = await sendMsg({ type: 'GET_WALLETS' });
  dashWallets = walletsForDashProfile(resp.wallets || []);
  const stResp = await sendMsg({ type: 'GET_STATE' });
  const activeIsVisible = dashWallets.some(w => w.id === stResp.activeWallet?.id);
  dashActiveWalletId = activeIsVisible ? stResp.activeWallet.id : (dashWallets[0]?.id || null);
  if (dashActiveWalletId && !activeIsVisible) {
    await sendMsg({ type: 'SELECT_WALLET', walletId: dashActiveWalletId });
  }

  // Wire static buttons once
  if (!dashTabsWired) {
    dashTabsWired = true;

    document.getElementById('btnBackFromDash').onclick = () => {
      hideDashView();
      showView('wallet');
    };
    document.getElementById('btnDashSignOut').onclick = () => {
      dashboardLogout();
      hideDashView();
      showView('wallet');
    };
    document.getElementById('btnDashNew').onclick = () => {
      hideDashView();
      showView('create');
    };
    document.getElementById('btnDashImport').onclick = () => {
      hideDashView();
      showView('import');
    };
    document.getElementById('btnDashCopyAddr').onclick = () => {
      const addr = document.getElementById('dashWltAddr').textContent;
      if (addr && addr !== '—') {
        navigator.clipboard.writeText(addr);
        showToast((isEvmAddress(addr) ? 'EVM' : 'Base58') + ' address copied!', 'success');
      }
    };
    document.getElementById('btnDashAirdrop').onclick = async () => {
      const wallet = dashWallets.find(w => w.id === dashActiveWalletId) || dashWallets[0];
      if (!wallet) { showToast('No wallet selected', 'error'); return; }
      const st = await sendMsg({ type: 'GET_STATE' });
      const rpcUrl = st.network?.rpcUrl || 'https://dashboard.denvion.com/node';
      try {
        showToast('Requesting airdrop…', 'success');
        const r = await fetch(rpcUrl + '/faucet/request', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ address: wallet.publicKey })
        });
        const data = await r.json();
        if (r.ok) {
          showToast('Airdrop sent! ' + (data.message || ''), 'success');
          setTimeout(() => loadDashWalletData(), 2000);
        } else {
          showToast(data.error || data.message || 'Airdrop failed', 'error');
        }
      } catch (e) {
        showToast('Cannot reach node for airdrop', 'error');
      }
    };
    document.getElementById('btnDashSettings').onclick = () => {
      document.querySelectorAll('#dashTabsRow .dash-tab').forEach(t => t.classList.remove('active'));
      renderDashTab('dsettings');
    };

    // Tab bar — event delegation (works on both .dv-tabs and .dash-tabs-row)
    document.getElementById('dashTabsRow').addEventListener('click', (e) => {
      const tab = e.target.closest('.dash-tab');
      if (!tab) return;
      document.querySelectorAll('#dashTabsRow .dash-tab').forEach(t => t.classList.remove('active'));
      tab.classList.add('active');
      renderDashTab(tab.dataset.tab);
    });
  }

  await renderDashSidebar();
  await loadDashWalletData();

  // Reset to Send tab
  document.querySelectorAll('#dashTabsRow .dash-tab').forEach(t => t.classList.remove('active'));
  document.querySelector('#dashTabsRow .dash-tab[data-tab="send"]').classList.add('active');
  renderDashTab('send');
}

async function renderDashSidebar() {
  const el = document.getElementById('dashSideList');
  if (!el) return;
  if (dashWallets.length === 0) {
    el.innerHTML = '<span style="font-size:11px;color:#9ca3af;padding:0 4px">No wallets yet.</span>';
    return;
  }

  // Render as horizontal pill chips
  el.innerHTML = dashWallets.map(w => {
    const isActive = w.id === dashActiveWalletId;
    const letter = (w.name || 'W')[0].toUpperCase();
    const displayAddr = w.evmAddress || w.publicKey;
    return `<div class="dv-wlt-chip ${isActive ? 'active' : ''}" data-wid="${w.id}">
      <div class="dv-wlt-chip-av">${letter}</div>
      <span class="dv-wlt-chip-name">${esc(w.name)} · ${esc(shortAddress(displayAddr, 6, 4))}</span>
      <span class="dv-wlt-chip-bal" id="dschip_${w.id}">…</span>
    </div>`;
  }).join('');

  // Click to switch active wallet
  el.querySelectorAll('.dv-wlt-chip').forEach(item => {
    item.addEventListener('click', async () => {
      dashActiveWalletId = item.dataset.wid;
      await sendMsg({ type: 'SELECT_WALLET', walletId: dashActiveWalletId });
      await renderDashSidebar();
      await loadDashWalletData();
      document.querySelectorAll('#dashTabsRow .dash-tab').forEach(t => t.classList.remove('active'));
      document.querySelector('#dashTabsRow .dash-tab[data-tab="send"]').classList.add('active');
      renderDashTab('send');
    });
  });

  // Fetch total liquid balances for chips.
  const stResp = await sendMsg({ type: 'GET_STATE' });
  const rpcUrl = stResp.network?.rpcUrl || 'https://dashboard.denvion.com/node';
  for (const w of dashWallets) {
    Promise.all([
      fetchKakBalance(rpcUrl, w.publicKey),
      w.evmAddress ? fetchKakBalance(rpcUrl, w.evmAddress) : Promise.resolve(0),
    ])
      .then(([nativeBal, evmBal]) => {
        const bal = nativeBal + evmBal;
        const chip = document.getElementById('dschip_' + w.id);
        if (chip) chip.textContent = (bal / KAK_PER_WCAHT).toFixed(2);
      })
      .catch(() => {
        const chip = document.getElementById('dschip_' + w.id);
        if (chip) chip.textContent = '—';
      });
  }
}

async function loadDashWalletData() {
  const wallet = dashWallets.find(w => w.id === dashActiveWalletId) || dashWallets[0];
  if (!wallet) return;

  document.getElementById('dashWltName').textContent = wallet.name || 'Wallet';
  document.getElementById('dashWltAddr').textContent = wallet.evmAddress || wallet.publicKey;
  const avatarEl = document.getElementById('dashWltAvatar');
  if (avatarEl) avatarEl.textContent = (wallet.name || 'W')[0].toUpperCase();

  const st = await sendMsg({ type: 'GET_STATE' });
  const rpcUrl = st.network?.rpcUrl || 'https://dashboard.denvion.com/node';

  // Balance — total liquid account. Stake is locked validator stake, not liquid.
  try {
    const [nativeBal, evmBal] = await Promise.all([
      fetchKakBalance(rpcUrl, wallet.publicKey),
      wallet.evmAddress ? fetchKakBalance(rpcUrl, wallet.evmAddress) : Promise.resolve(0),
    ]);
    const bal = nativeBal + evmBal;

    const wcaht = bal / KAK_PER_WCAHT;
    document.getElementById('dashStBal').textContent = wcaht.toLocaleString('en', { maximumFractionDigits: 4 }) + ' WCAHT';
    document.getElementById('dashStKak').textContent = wallet.evmAddress
      ? `Native ${formatWcaht(nativeBal)} • EVM ${formatWcaht(evmBal)} • Total ${formatWcaht(bal)}`
      : `Native ${formatWcaht(nativeBal)} • Total ${formatWcaht(bal)}`;
    const usd = (wcaht * 0.01).toFixed(2);
    document.getElementById('dashStUsd').textContent = '$' + Number(usd).toLocaleString('en', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  } catch {
    document.getElementById('dashStBal').textContent = 'Offline';
    document.getElementById('dashStKak').textContent = '—';
    document.getElementById('dashStUsd').textContent = '—';
  }

  // TX counts from recent_transactions
  try {
    const r2 = await fetch(rpcUrl + '/recent_transactions');
    const txs = await r2.json();
    const addr = wallet.publicKey;
    const evm = wallet.evmAddress;
    document.getElementById('dashStSent').textContent = txs.filter(tx => tx.from === addr || (evm && tx.from === evm)).length;
    document.getElementById('dashStRecv').textContent = txs.filter(tx => tx.to === addr || (evm && tx.to === evm)).length;
  } catch {
    document.getElementById('dashStSent').textContent = '—';
    document.getElementById('dashStRecv').textContent = '—';
  }
}

async function renderDashTab(tab) {
  const body = document.getElementById('dashTabBody');
  switch (tab) {

    case 'send': {
      body.innerHTML = `
        <div class="form-group">
          <label>Recipient Address</label>
          <input type="text" id="dashSendTo" class="input" placeholder="Enter WCAHT base58 or EVM 0x address">
        </div>
        <div class="form-group">
          <label>Amount (WCAHT)</label>
          <div style="display:flex;gap:8px;align-items:center">
            <input type="number" id="dashSendAmt" class="input" placeholder="0.0" step="0.0001" min="0" style="margin-bottom:0;flex:1">
            <button class="link-btn" id="btnDashMax">MAX</button>
          </div>
          <div class="input-hint">1 WCAHT = 1,000,000,000 kak &nbsp;·&nbsp; Fee: 5,000 kak per TX</div>
        </div>
        <div class="form-group">
          <label>Memo (Optional)</label>
          <input type="text" id="dashSendMemo" class="input" placeholder="Add a note to this transaction">
        </div>
        <div class="error-msg" id="dashSendErr"></div>
        <div style="display:flex;gap:8px;margin-top:4px">
          <button class="btn btn-primary" id="btnDashSendTx" style="flex:1">Send WCAHT</button>
          <button class="btn btn-outline" id="btnDashClearSend" style="width:80px">Clear</button>
        </div>`;

      document.getElementById('btnDashSendTx').addEventListener('click', handleDashSend);
      document.getElementById('btnDashClearSend').addEventListener('click', () => {
        document.getElementById('dashSendTo').value = '';
        document.getElementById('dashSendAmt').value = '';
        document.getElementById('dashSendMemo').value = '';
        document.getElementById('dashSendErr').textContent = '';
      });
      document.getElementById('btnDashMax').addEventListener('click', async () => {
        const wallet = dashWallets.find(w => w.id === dashActiveWalletId);
        if (!wallet) return;
        const st = await sendMsg({ type: 'GET_STATE' });
        const rpcUrl = st.network?.rpcUrl || 'https://dashboard.denvion.com/node';
        try {
          const [nativeBal, evmBal] = await Promise.all([
            fetchKakBalance(rpcUrl, wallet.publicKey),
            wallet.evmAddress ? fetchKakBalance(rpcUrl, wallet.evmAddress) : Promise.resolve(0),
          ]);
          const bal = nativeBal + evmBal;
          const max = Math.max(0, (bal / KAK_PER_WCAHT) - 0.000005);
          document.getElementById('dashSendAmt').value = max.toFixed(4);
        } catch {}
      });
      break;
    }

    case 'receive': {
      const wallet = dashWallets.find(w => w.id === dashActiveWalletId) || dashWallets[0];
      const addr = wallet?.publicKey || '—';
      const evmAddr = wallet?.evmAddress || '';
      body.innerHTML = `
        <div style="text-align:center;padding:16px 12px">
          <div style="display:inline-block;background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:10px;margin-bottom:14px">
            <canvas id="dashQrCanvas"></canvas>
          </div>
          <div style="font-size:10px;font-weight:700;color:#6b7280;text-transform:uppercase;text-align:left;margin:0 0 6px">Base58 address</div>
          <div style="font-family:monospace;font-size:10px;word-break:break-all;margin:0 0 12px;padding:8px 10px;background:#f3f4f6;border:1px solid #e5e7eb;border-radius:8px;color:#374151;text-align:left">${esc(addr)}</div>
          <button class="btn btn-outline" id="btnDashCopyRecv" style="width:100%">Copy Base58 Address</button>
          <div style="font-size:10px;font-weight:700;color:#6b7280;text-transform:uppercase;text-align:left;margin:12px 0 6px">EVM 0x address</div>
          <div style="font-family:monospace;font-size:10px;word-break:break-all;margin:0 0 12px;padding:8px 10px;background:#f3f4f6;border:1px solid #e5e7eb;border-radius:8px;color:#374151;text-align:left">${esc(evmAddr || 'Legacy wallet: no paired 0x address')}</div>
          <button class="btn btn-outline" id="btnDashCopyRecvEvm" style="width:100%">Copy EVM Address</button>
        </div>`;
      // Render QR code onto canvas
      const canvas = document.getElementById('dashQrCanvas');
      if (canvas && addr !== '—' && typeof qrcode !== 'undefined') {
        try {
          const qr = qrcode(0, 'M');
          qr.addData(addr);
          qr.make();
          const cells = qr.getModuleCount();
          const size = 160;
          canvas.width = size;
          canvas.height = size;
          const ctx = canvas.getContext('2d');
          const cellSize = size / cells;
          ctx.fillStyle = '#ffffff';
          ctx.fillRect(0, 0, size, size);
          ctx.fillStyle = '#111827';
          for (let row = 0; row < cells; row++) {
            for (let col = 0; col < cells; col++) {
              if (qr.isDark(row, col)) {
                ctx.fillRect(Math.floor(col * cellSize), Math.floor(row * cellSize),
                  Math.ceil(cellSize), Math.ceil(cellSize));
              }
            }
          }
        } catch (e) { canvas.parentElement.textContent = addr; }
      }
      document.getElementById('btnDashCopyRecv').addEventListener('click', () => {
        navigator.clipboard.writeText(addr);
        showToast('Base58 address copied!', 'success');
      });
      document.getElementById('btnDashCopyRecvEvm').addEventListener('click', () => {
        if (!isEvmAddress(evmAddr)) { showToast('This legacy wallet has no paired EVM address', 'error'); return; }
        navigator.clipboard.writeText(evmAddr);
        showToast('EVM 0x address copied!', 'success');
      });
      break;
    }

    case 'stake':
      body.innerHTML = `<div style="color:var(--text-muted);font-size:12px">Loading staking info…</div>`;
      loadDashStaking();
      break;

    case 'history':
      body.innerHTML = '<div style="color:var(--text-muted);font-size:12px">Loading…</div>';
      loadDashHistory();
      break;

    case 'contacts':
      body.innerHTML = `
        <div style="text-align:center;padding:28px 0;color:var(--text-muted)">
          <div style="font-size:36px;margin-bottom:10px">📒</div>
          <div style="font-weight:600;margin-bottom:6px;color:var(--text)">Contacts</div>
          <p style="font-size:12px">Save frequently used addresses for quick access.</p>
          <button class="btn btn-primary btn-sm" style="margin-top:16px" id="btnDashAddContact">+ Add Contact</button>
        </div>`;
      document.getElementById('btnDashAddContact').addEventListener('click', () => showToast('Contacts coming soon', 'success'));
      break;

    case 'dsettings': {
      const curWallet = dashWallets.find(w => w.id === dashActiveWalletId);
      const appState  = await sendMsg({ type: 'GET_STATE' });
      const hasPinSet = !!appState.pinEncryptedPassword;
      body.innerHTML = `
        <div class="settings-list">
          <div class="setting-item">
            <span>Wallet Name</span>
            <input type="text" id="dashSettName" class="input input-sm" value="${esc(curWallet?.name || '')}">
            <button class="btn btn-sm" id="btnDashRename">Save</button>
          </div>
          <div class="setting-item">
            <span>Custom RPC URL</span>
            <input type="text" id="dashSettRpc" class="input input-sm" placeholder="https://dashboard.denvion.com/node">
            <button class="btn btn-sm" id="btnDashSetRpc">Set</button>
          </div>
          <div class="setting-item" id="setPinRow">
            <span>${hasPinSet ? 'PIN unlock is ON' : 'Set 6-digit PIN'}</span>
            <button class="btn btn-sm" id="btnDashSetPin">${hasPinSet ? 'Change PIN' : 'Set PIN'}</button>
            ${hasPinSet ? '<button class="btn btn-sm btn-danger" id="btnDashRemovePin">Remove</button>' : ''}
          </div>
          <div id="setPinForm" style="display:none;padding:8px 0 4px">
            <input type="password" id="setPinCurrentPw" class="input input-sm" placeholder="Current password" autocomplete="off" style="margin-bottom:6px">
            <div style="display:flex;gap:6px;margin-bottom:6px">
              <input type="text" id="setPinVal" class="input input-sm" placeholder="New 6-digit PIN" maxlength="6" pattern="[0-9]{6}" inputmode="numeric">
              <input type="text" id="setPinConfirm" class="input input-sm" placeholder="Confirm PIN" maxlength="6" pattern="[0-9]{6}" inputmode="numeric">
            </div>
            <button class="btn btn-sm" id="btnConfirmSetPin">Save PIN</button>
          </div>
          <div class="error-msg" id="setPinMsg"></div>
          <div class="setting-item danger">
            <span>Export Private Key</span>
            <button class="btn btn-danger btn-sm" id="btnDashExport">Export</button>
          </div>
          <div class="setting-item danger">
            <span>Sign Out Dashboard</span>
            <button class="btn btn-danger btn-sm" id="btnDashSignOutSett">Sign Out</button>
          </div>
        </div>
        <div class="error-msg" id="dashSettMsg"></div>`;

      document.getElementById('btnDashRename').addEventListener('click', async () => {
        const name = document.getElementById('dashSettName').value.trim();
        if (!name) return;
        await sendMsg({ type: 'RENAME_WALLET', walletId: dashActiveWalletId, name });
        const w = dashWallets.find(ww => ww.id === dashActiveWalletId);
        if (w) w.name = name;
        document.getElementById('dashWltName').textContent = name;
        await renderDashSidebar();
        showToast('Renamed to ' + name, 'success');
      });

      document.getElementById('btnDashSetRpc').addEventListener('click', async () => {
        const url = document.getElementById('dashSettRpc').value.trim();
        if (!url) return;
        await sendMsg({ type: 'SET_NETWORK', name: 'Custom', rpcUrl: url });
        showToast('RPC set to ' + url, 'success');
      });

      // ── Set PIN ────────────────────────────────────────────────────────────
      document.getElementById('btnDashSetPin').addEventListener('click', () => {
        const form = document.getElementById('setPinForm');
        form.style.display = form.style.display === 'none' ? 'block' : 'none';
      });

      const removePinBtn = document.getElementById('btnDashRemovePin');
      if (removePinBtn) {
        removePinBtn.addEventListener('click', async () => {
          if (!confirm('Remove PIN unlock?')) return;
          await sendMsg({ type: 'REMOVE_PIN' });
          showToast('PIN removed', 'success');
          renderDashTab('dsettings');
        });
      }

      document.getElementById('btnConfirmSetPin').addEventListener('click', async () => {
        const msgEl = document.getElementById('setPinMsg');
        const pw  = document.getElementById('setPinCurrentPw').value;
        const pin = document.getElementById('setPinVal').value.trim();
        const pin2 = document.getElementById('setPinConfirm').value.trim();
        msgEl.textContent = '';
        if (!pw) { msgEl.textContent = 'Enter your current password'; msgEl.className = 'error-msg error'; return; }
        if (!/^\d{6}$/.test(pin)) { msgEl.textContent = 'PIN must be exactly 6 digits'; msgEl.className = 'error-msg error'; return; }
        if (pin !== pin2) { msgEl.textContent = 'PINs do not match'; msgEl.className = 'error-msg error'; return; }
        const resp = await sendMsg({ type: 'SET_PIN', password: pw, pin });
        if (resp.error) { msgEl.textContent = resp.error; msgEl.className = 'error-msg error'; return; }
        showToast('PIN set! You can now unlock with your PIN.', 'success');
        renderDashTab('dsettings');
      });

      document.getElementById('btnDashExport').addEventListener('click', async () => {
        if (!confirm('Your private key will be shown. Never share it!')) return;
        const resp = await sendMsg({ type: 'EXPORT_KEY', walletId: dashActiveWalletId });
        const msgEl = document.getElementById('dashSettMsg');
        if (resp.error) { msgEl.textContent = resp.error; msgEl.className = 'error-msg error'; return; }
        msgEl.className = 'error-msg';
        const exportText = resp.privateKey
          ? `EVM private key\n${resp.privateKey}\n\nBase58 secret\n${resp.secretKey}`
          : resp.secretKey;
        msgEl.innerHTML = '<div style="white-space:pre-wrap;word-break:break-all;font-family:monospace;font-size:10px;background:var(--bg-input);padding:8px;border-radius:4px;margin-top:8px">' + esc(exportText) + '</div>';
      });

      document.getElementById('btnDashSignOutSett').addEventListener('click', () => {
        dashboardLogout();
        hideDashView();
        showView('wallet');
      });
      break;
    }
  }
}

async function handleDashSend() {
  const typedTo = document.getElementById('dashSendTo').value.trim();
  const to = normalizeRecipientAddress(typedTo);
  const amtStr = document.getElementById('dashSendAmt').value.trim();
  const errEl = document.getElementById('dashSendErr');
  const btn = document.getElementById('btnDashSendTx');

  if (!typedTo) { errEl.textContent = 'Enter a recipient base58 or EVM 0x address'; errEl.className = 'error-msg error'; return; }
  if (!isValidWalletRecipient(typedTo)) { errEl.textContent = 'Enter a valid WCAHT base58 or EVM 0x address'; errEl.className = 'error-msg error'; return; }
  const amount = parseFloat(amtStr);
  if (!amount || amount <= 0) { errEl.textContent = 'Enter an amount'; errEl.className = 'error-msg error'; return; }

  btn.disabled = true;
  btn.textContent = 'Sending…';
  errEl.textContent = '';

  const resp = await sendMsg({ type: 'SEND_TX', to, amount: Math.round(amount * KAK_PER_WCAHT) });

  btn.disabled = false;
  btn.textContent = 'Send WCAHT';

  if (resp.error) { errEl.textContent = resp.error; errEl.className = 'error-msg error'; return; }

  showToast('Sent ' + amount.toFixed(4) + ' WCAHT!', 'success');
  document.getElementById('dashSendTo').value = '';
  document.getElementById('dashSendAmt').value = '';
  const memoEl = document.getElementById('dashSendMemo');
  if (memoEl) memoEl.value = '';
  setTimeout(() => loadDashWalletData(), 2000);
}

async function loadDashStaking() {
  const wallet = dashWallets.find(w => w.id === dashActiveWalletId) || dashWallets[0];
  const body = document.getElementById('dashTabBody');
  if (!wallet || !body) return;

  const st = await sendMsg({ type: 'GET_STATE' });
  const rpcUrl = st.network?.rpcUrl || 'https://dashboard.denvion.com/node';

  let validators = [], epoch = 0, totalStake = 0, stakeBal = 0;
  try {
    const [vRes, sRes] = await Promise.all([
      fetch(rpcUrl + '/validators').then(r => r.json()),
      fetch(rpcUrl + '/balance/stake_' + wallet.publicKey).then(r => r.text()),
    ]);
    validators = vRes.validators || [];
    epoch      = vRes.epoch || 0;
    totalStake = vRes.total_stake || 0;
    stakeBal   = parseInt(sRes.trim(), 10) || 0;
  } catch (e) {
    body.innerHTML = `
      <div style="padding:24px 16px;text-align:center">
        <div style="font-size:28px;margin-bottom:10px">⚠️</div>
        <div style="color:#dc2626;font-weight:600;margin-bottom:6px">Could not reach node</div>
        <div style="color:#6b7280;font-size:11px;margin-bottom:16px">Make sure your node is running and RPC URL is correct.</div>
        <button class="btn btn-outline" id="btnStakeRetry" style="font-size:12px">↻ Retry</button>
      </div>`;
    document.getElementById('btnStakeRetry')?.addEventListener('click', () => {
      body.innerHTML = '<div style="color:#9ca3af;font-size:12px;padding:12px">Loading…</div>';
      loadDashStaking();
    });
    return;
  }

  const myValidator = validators.find(v => v.identity === wallet.publicKey);
  const isValidator = !!myValidator;
  const totalStakeWCAHT = totalStake / KAK_PER_WCAHT;

  // ── My status section ───────────────────────────────────────────
  let mySection = '';
  if (isValidator) {
    const v = myValidator;
    const share = totalStake > 0 ? ((v.stake / totalStake) * 100).toFixed(1) : '0.0';
    const myWCAHT = (v.stake / KAK_PER_WCAHT).toLocaleString('en', { maximumFractionDigits: 0 });
    const badgeCls = v.is_online ? 'online' : 'offline';
    const badgeLabel = v.is_online ? '● Online' : '● Offline';
    const slashCls = v.slash_count > 0 ? 'danger' : '';
    mySection = `
      <div class="sk-section" style="border-color:#00b894">
        <div class="sk-section-head" style="background:#f0fdf9;border-color:#d1fae5">
          <span class="sk-section-title" style="color:#00a37a">My Validator</span>
          <span class="sk-badge ${badgeCls}">${badgeLabel}</span>
        </div>
        <div class="sk-section-body">
          <div class="sk-grid-2">
            <div class="sk-stat">
              <div class="sk-stat-label">Genesis Stake</div>
              <div class="sk-stat-val">${myWCAHT}</div>
              <div class="sk-stat-sub">WCAHT · locked</div>
            </div>
            <div class="sk-stat">
              <div class="sk-stat-label">Network Share</div>
              <div class="sk-stat-val accent">${share}%</div>
              <div class="sk-stat-sub">of total stake</div>
            </div>
            <div class="sk-stat">
              <div class="sk-stat-label">Slashes</div>
              <div class="sk-stat-val ${slashCls}">${v.slash_count}</div>
              <div class="sk-stat-sub">penalty events</div>
            </div>
            <div class="sk-stat">
              <div class="sk-stat-label">Epoch</div>
              <div class="sk-stat-val">#${epoch}</div>
              <div class="sk-stat-sub">current</div>
            </div>
          </div>
        </div>
      </div>`;
  } else {
    const myStakeWCAHT = (stakeBal / KAK_PER_WCAHT).toLocaleString('en', { maximumFractionDigits: 4 });
    mySection = `
      <div class="sk-section">
        <div class="sk-section-head">
          <span class="sk-section-title">My Stake</span>
        </div>
        <div class="sk-section-body sk-not-validator">
          <div class="sk-nv-icon">🪙</div>
          <div class="sk-nv-label">${myStakeWCAHT} WCAHT</div>
          <div class="sk-nv-sub">Observer — not a validator node</div>
        </div>
      </div>`;
  }

  // ── Validator rows ───────────────────────────────────────────────
  const rows = validators.map(v => {
    const isMe = v.identity === wallet.publicKey;
    const dot  = v.is_online ? '🟢' : '🔴';
    const wcaht = (v.stake / KAK_PER_WCAHT).toLocaleString('en', { maximumFractionDigits: 0 });
    const short = v.identity.slice(0, 10) + '…' + v.identity.slice(-6);
    const slashCls = v.slash_count > 0 ? 'danger' : '';
    const meCls = isMe ? 'me' : '';
    return `
      <div class="sk-validator-row ${meCls}">
        <span class="sk-val-dot">${dot}</span>
        <span class="sk-val-addr ${meCls}">${isMe ? '★ ' : ''}${short}</span>
        <span class="sk-val-stake">${wcaht}</span>
        <span class="sk-val-slash ${slashCls}">${v.slash_count > 0 ? '⚠' + v.slash_count : '—'}</span>
      </div>`;
  }).join('');

  body.innerHTML = `
    ${mySection}
    <div class="sk-section">
      <div class="sk-section-head">
        <span class="sk-section-title">Network</span>
        <span class="sk-section-badge">${validators.length} validators · ${totalStakeWCAHT.toLocaleString('en', { maximumFractionDigits: 0 })} WCAHT staked</span>
      </div>
      ${rows}
    </div>
    <button class="sk-refresh-btn" id="btnDashStakeRefresh">↻ Refresh</button>
  `;

  document.getElementById('btnDashStakeRefresh').addEventListener('click', () => {
    body.innerHTML = '<div style="color:#9ca3af;font-size:12px;padding:12px">Loading…</div>';
    loadDashStaking();
  });
}

async function loadDashHistory() {
  const wallet = dashWallets.find(w => w.id === dashActiveWalletId) || dashWallets[0];
  const body = document.getElementById('dashTabBody');
  const st = await sendMsg({ type: 'GET_STATE' });
  const rpcUrl = st.network?.rpcUrl || 'https://dashboard.denvion.com/node';

  try {
    const r = await fetch(rpcUrl + '/recent_transactions');
    const txs = await r.json();
    const addr = wallet?.publicKey;
    const relevant = txs.filter(tx => tx.from === addr || tx.to === addr);

    if (relevant.length === 0) {
      body.innerHTML = '<div style="text-align:center;padding:24px;color:var(--text-muted);font-size:12px">No transactions found for this wallet</div>';
      return;
    }

    let html = '';
    for (const tx of relevant) {
      const isSend = tx.from === addr;
      const amt = (Number(tx.amount || 0) / KAK_PER_WCAHT).toFixed(4);
      const partner = isSend ? tx.to : tx.from;
      const ts = tx.timestamp ? timeAgo(tx.timestamp * 1000) : '—';
      html += `<div style="display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid var(--border)">
        <div style="width:32px;height:32px;border-radius:50%;background:${isSend ? 'var(--red-dim)' : 'var(--accent-dim)'};display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0">${isSend ? '↑' : '↓'}</div>
        <div style="flex:1;min-width:0">
          <div style="font-size:12px;font-weight:600">${isSend ? 'Sent' : 'Received'}</div>
          <div style="font-size:9px;color:var(--text-muted);font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${(partner || '—').slice(0, 14)}…${(partner || '').slice(-6)}</div>
        </div>
        <div style="text-align:right;flex-shrink:0">
          <div style="font-weight:600;font-size:12px;color:${isSend ? 'var(--red)' : 'var(--green)'}">${isSend ? '-' : '+'}${amt}</div>
          <div style="font-size:10px;color:var(--text-muted)">${ts}</div>
        </div>
      </div>`;
    }
    body.innerHTML = html;
  } catch {
    body.innerHTML = '<div style="text-align:center;padding:24px;color:var(--text-muted);font-size:12px">Failed to load history</div>';
  }
}
