import { createWallet, importMnemonic, importPrivateKey } from './wallet_crypto.mjs';

const VAULTS_KEY = 'mazexchain.wallet.vaults';
const ACTIVE_ADDRESS_KEY = 'mazexchain.wallet.active.address';
const SESSION_WALLET_KEY = 'mazexchain.session.wallet';
const CONNECTED_ORIGINS_KEY = 'mazexchain.connected.origins';
const NODE_URL_KEY = 'mazexchain.node.url';
const LEGACY_WALLET_KEY = 'mazexchain.native.wallet';
const CUSTOM_ASSETS_KEY = 'mazexchain.wallet.custom.assets';
const KDF_ITERATIONS = 180000;

const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();

const el = {
  views: {
    landing: document.querySelector('#viewLanding'),
    register: document.querySelector('#viewRegister'),
    login: document.querySelector('#viewLogin'),
    dashboard: document.querySelector('#viewDashboard'),
    settings: document.querySelector('#viewSettings'),
  },
  lockBadge: document.querySelector('#lockBadge'),
  registerStatus: document.querySelector('#registerStatus'),
  loginStatus: document.querySelector('#loginStatus'),
  dashboardStatus: document.querySelector('#dashboardStatus'),
  dashboardAddressText: document.querySelector('#dashboardAddressText'),
  settingsStatus: document.querySelector('#settingsStatus'),
  accountTitle: document.querySelector('#accountTitle'),
  accountSelect: document.querySelector('#accountSelect'),
  loginAccountSelect: document.querySelector('#loginAccountSelect'),
  address: document.querySelector('#address'),
  confirmed: document.querySelector('#confirmed'),
  pending: document.querySelector('#pending'),
  nonce: document.querySelector('#nonce'),
  assetMazexBalance: document.querySelector('#assetMazexBalance'),
  nodeUrl: document.querySelector('#nodeUrl'),
  registerPassword: document.querySelector('#registerPassword'),
  registerPasswordStep: document.querySelector('#registerPasswordStep'),
  registerBackupStep: document.querySelector('#registerBackupStep'),
  registerVerifyStep: document.querySelector('#registerVerifyStep'),
  mnemonicWords: document.querySelector('#mnemonicWords'),
  verifyFields: document.querySelector('#verifyFields'),
  unlockPassword: document.querySelector('#unlockPassword'),
  loginPhrasePassword: document.querySelector('#loginPhrasePassword'),
  loginMnemonic: document.querySelector('#loginMnemonic'),
  loginPrivatePassword: document.querySelector('#loginPrivatePassword'),
  loginPrivateKey: document.querySelector('#loginPrivateKey'),
  backupMnemonic: document.querySelector('#backupMnemonic'),
  backupPrivateKey: document.querySelector('#backupPrivateKey'),
  connectedOrigins: document.querySelector('#connectedOrigins'),
  registerNavBtn: document.querySelector('#registerNavBtn'),
  loginNavBtn: document.querySelector('#loginNavBtn'),
  generatePhraseBtn: document.querySelector('#generatePhraseBtn'),
  continueVerifyBtn: document.querySelector('#continueVerifyBtn'),
  createBtn: document.querySelector('#createBtn'),
  unlockBtn: document.querySelector('#unlockBtn'),
  loginPhraseBtn: document.querySelector('#loginPhraseBtn'),
  loginPrivateKeyBtn: document.querySelector('#loginPrivateKeyBtn'),
  lockBtn: document.querySelector('#lockBtn'),
  copyAddressBtn: document.querySelector('#copyAddressBtn'),
  copyPhraseBtn: document.querySelector('#copyPhraseBtn'),
  removeAccountBtn: document.querySelector('#removeAccountBtn'),
  refreshAccountBtn: document.querySelector('#refreshAccountBtn'),
  disconnectSitesBtn: document.querySelector('#disconnectSitesBtn'),
  addAccountBtn: document.querySelector('#addAccountBtn'),
  addTokenBtn: document.querySelector('#addTokenBtn'),
  settingsBtn: document.querySelector('#settingsBtn'),
  loginModeSelect: document.querySelector('#loginModeSelect'),
  passwordLoginPanel: document.querySelector('#passwordLoginPanel'),
  phraseLoginPanel: document.querySelector('#phraseLoginPanel'),
  keyLoginPanel: document.querySelector('#keyLoginPanel'),
};

let currentView = 'landing';
let loginMode = 'password';
let pendingRegistration = null;

function getStorage(keys) {
  return new Promise((resolve) => chrome.storage.local.get(keys, resolve));
}

function setStorage(items) {
  return new Promise((resolve) => chrome.storage.local.set(items, resolve));
}

function removeStorage(keys) {
  return new Promise((resolve) => chrome.storage.local.remove(keys, resolve));
}

function sessionStorageArea() {
  return chrome.storage.session || chrome.storage.local;
}

function getSession(keys) {
  return new Promise((resolve) => sessionStorageArea().get(keys, resolve));
}

function setSession(items) {
  return new Promise((resolve) => sessionStorageArea().set(items, resolve));
}

function removeSession(keys) {
  return new Promise((resolve) => sessionStorageArea().remove(keys, resolve));
}

function shortHash(value) {
  if (!value) return '--';
  return `${String(value).slice(0, 14)}...${String(value).slice(-8)}`;
}

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

function bytesToBase64(bytes) {
  let binary = '';
  for (let i = 0; i < bytes.length; i += 0x8000) {
    binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
  }
  return btoa(binary);
}

function base64ToBytes(base64) {
  const binary = atob(base64);
  const out = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
  return out;
}

function randomBytes(length) {
  const out = new Uint8Array(length);
  crypto.getRandomValues(out);
  return out;
}

async function passwordKey(password, salt) {
  const baseKey = await crypto.subtle.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveKey']);
  return crypto.subtle.deriveKey(
    {
      name: 'PBKDF2',
      hash: 'SHA-256',
      salt,
      iterations: KDF_ITERATIONS,
    },
    baseKey,
    { name: 'AES-GCM', length: 256 },
    false,
    ['encrypt', 'decrypt'],
  );
}

async function encryptWallet(wallet, password) {
  const salt = randomBytes(16);
  const iv = randomBytes(12);
  const key = await passwordKey(password, salt);
  const ciphertext = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    key,
    textEncoder.encode(JSON.stringify(wallet)),
  );
  return {
    kdf: 'PBKDF2-SHA256',
    cipher: 'AES-256-GCM',
    iterations: KDF_ITERATIONS,
    salt: bytesToBase64(salt),
    iv: bytesToBase64(iv),
    ciphertext: bytesToBase64(new Uint8Array(ciphertext)),
  };
}

async function decryptWallet(vault, password) {
  const encrypted = vault.encrypted_wallet;
  const key = await passwordKey(password, base64ToBytes(encrypted.salt));
  const plaintext = await crypto.subtle.decrypt(
    { name: 'AES-GCM', iv: base64ToBytes(encrypted.iv) },
    key,
    base64ToBytes(encrypted.ciphertext),
  );
  return JSON.parse(textDecoder.decode(plaintext));
}

function setStatus(target, value, type = '') {
  const node = el[target];
  if (!node) return;
  node.textContent = value;
  node.classList.toggle('error', type === 'error');
  node.classList.toggle('success', type === 'success');
}

function setBusy(isBusy) {
  for (const button of [
    el.registerNavBtn,
    el.loginNavBtn,
    el.generatePhraseBtn,
    el.continueVerifyBtn,
    el.createBtn,
    el.unlockBtn,
    el.loginPhraseBtn,
    el.loginPrivateKeyBtn,
    el.lockBtn,
    el.copyAddressBtn,
    el.copyPhraseBtn,
    el.removeAccountBtn,
    el.refreshAccountBtn,
    el.disconnectSitesBtn,
    el.addAccountBtn,
    el.addTokenBtn,
    el.settingsBtn,
  ]) {
    if (button) button.disabled = isBusy;
  }
}

function requirePassword(input, label = 'Password') {
  const value = input.value;
  input.classList.remove('input-error');
  if (!value || value.length < 8) {
    input.classList.add('input-error');
    input.focus();
    throw new Error(`${label} must be at least 8 characters.`);
  }
  return value;
}

async function readState() {
  const local = await getStorage([
    VAULTS_KEY,
    ACTIVE_ADDRESS_KEY,
    CONNECTED_ORIGINS_KEY,
    NODE_URL_KEY,
    LEGACY_WALLET_KEY,
    CUSTOM_ASSETS_KEY,
  ]);
  const session = await getSession([SESSION_WALLET_KEY]);
  const vaults = Array.isArray(local[VAULTS_KEY]) ? local[VAULTS_KEY] : [];
  const activeAddress = local[ACTIVE_ADDRESS_KEY] || vaults[0]?.address || '';
  return {
    vaults,
    activeAddress,
    activeVault: vaults.find((vault) => vault.address === activeAddress) || vaults[0] || null,
    sessionWallet: session[SESSION_WALLET_KEY] || null,
    connectedOrigins: Array.isArray(local[CONNECTED_ORIGINS_KEY]) ? local[CONNECTED_ORIGINS_KEY] : [],
    customAssets: Array.isArray(local[CUSTOM_ASSETS_KEY]) ? local[CUSTOM_ASSETS_KEY] : [],
    nodeUrl: local[NODE_URL_KEY] || 'http://localhost:3000',
    legacyWallet: local[LEGACY_WALLET_KEY] || null,
  };
}

function isUnlocked(state) {
  return Boolean(
    state.sessionWallet?.address && (!state.activeVault || state.sessionWallet.address === state.activeVault.address),
  );
}

async function writeVault(wallet, password) {
  const state = await readState();
  const vault = {
    address: wallet.address,
    public_key: wallet.public_key,
    algorithm: wallet.algorithm || 'ed25519',
    version: wallet.version || 'mazex-wallet-1.0',
    label: `Account ${state.vaults.length + 1}`,
    created_at: new Date().toISOString(),
    encrypted_wallet: await encryptWallet(wallet, password),
  };
  const vaults = [vault, ...state.vaults.filter((item) => item.address !== wallet.address)];
  await setStorage({
    [VAULTS_KEY]: vaults,
    [ACTIVE_ADDRESS_KEY]: wallet.address,
  });
  await setSession({ [SESSION_WALLET_KEY]: wallet });
  await removeStorage([LEGACY_WALLET_KEY]);
  return vault;
}

function showView(viewName) {
  currentView = viewName;
  for (const [name, node] of Object.entries(el.views)) {
    node.classList.toggle('active', name === viewName);
  }
}

function showRegisterStep(stepName) {
  const steps = {
    password: el.registerPasswordStep,
    backup: el.registerBackupStep,
    verify: el.registerVerifyStep,
  };
  for (const [name, node] of Object.entries(steps)) {
    node.classList.toggle('active', name === stepName);
  }
}

function setLoginMode(nextMode) {
  loginMode = nextMode;
  const panels = {
    password: el.passwordLoginPanel,
    phrase: el.phraseLoginPanel,
    key: el.keyLoginPanel,
  };
  el.loginModeSelect.value = nextMode;
  for (const [name, panel] of Object.entries(panels)) {
    panel.classList.toggle('active', name === nextMode);
  }
}

function resetRegistrationFlow() {
  pendingRegistration = null;
  el.registerPassword.value = '';
  el.mnemonicWords.innerHTML = '';
  el.verifyFields.innerHTML = '';
  showRegisterStep('password');
}

function chooseVerifyIndexes(wordCount, count = 3) {
  const chosen = new Set();
  while (chosen.size < Math.min(count, wordCount)) {
    chosen.add(crypto.getRandomValues(new Uint32Array(1))[0] % wordCount);
  }
  return [...chosen].sort((a, b) => a - b);
}

function renderMnemonicWords(mnemonic) {
  const words = mnemonic.split(/\s+/);
  el.mnemonicWords.innerHTML = words
    .map((word, index) => `<div class="word-pill"><span>${index + 1}</span><b>${escapeHtml(word)}</b></div>`)
    .join('');
}

function renderVerifyFields(mnemonic, indexes) {
  const words = mnemonic.split(/\s+/);
  el.verifyFields.innerHTML = indexes
    .map(
      (index) => `
        <div class="verify-row">
          <label for="verifyWord${index}">Word ${index + 1}</label>
          <input id="verifyWord${index}" data-word-index="${index}" autocomplete="off" spellcheck="false" placeholder="Enter word ${index + 1}" />
        </div>`,
    )
    .join('');
  for (const input of el.verifyFields.querySelectorAll('input')) {
    input.addEventListener('input', () => input.classList.remove('input-error'));
  }
  return words;
}

function verifyPendingMnemonic() {
  if (!pendingRegistration) throw new Error('Generate a recovery phrase first.');
  const words = pendingRegistration.wallet.mnemonic.split(/\s+/);
  let valid = true;
  for (const input of el.verifyFields.querySelectorAll('input[data-word-index]')) {
    const index = Number(input.dataset.wordIndex);
    const expected = words[index];
    const actual = input.value.trim().toLowerCase();
    input.classList.remove('input-error');
    if (actual !== expected) {
      valid = false;
      input.classList.add('input-error');
    }
  }
  if (!valid) throw new Error('Recovery phrase confirmation failed.');
}

function renderOrigins(origins) {
  if (!origins.length) {
    el.connectedOrigins.textContent = 'No connected sites.';
    return;
  }
  el.connectedOrigins.innerHTML = origins
    .map((origin) => `<span class="origin-pill">${escapeHtml(origin)}</span>`)
    .join('');
}

function renderAccountSelect(selectNode, vaults, activeAddress) {
  selectNode.innerHTML = '';
  if (!vaults.length) {
    const option = document.createElement('option');
    option.value = '';
    option.textContent = 'No wallet';
    selectNode.append(option);
    return;
  }
  for (const vault of vaults) {
    const option = document.createElement('option');
    option.value = vault.address;
    option.textContent = shortHash(vault.address);
    if (vault.address === activeAddress) option.selected = true;
    selectNode.append(option);
  }
}

function renderSecrets(sessionWallet) {
  el.backupMnemonic.value = sessionWallet?.mnemonic || '';
  el.backupPrivateKey.value = sessionWallet?.private_key || '';
}

function renderAssets(customAssets, confirmedBalance) {
  const assetList = document.querySelector('.asset-list');
  const nativeRow = `
    <div class="asset-row">
      <span class="asset-dot"></span>
      <div>
        <strong>MAZEX</strong>
        <small>Native token</small>
      </div>
      <b>${escapeHtml(confirmedBalance ?? 0)}</b>
    </div>`;
  const customRows = customAssets
    .map(
      (asset) => `
        <div class="asset-row">
          <span class="asset-dot"></span>
          <div>
            <strong>${escapeHtml(asset.symbol)}</strong>
            <small>${escapeHtml(asset.name || 'Custom asset')}</small>
          </div>
          <b>--</b>
        </div>`,
    )
    .join('');
  assetList.innerHTML = nativeRow + customRows;
}

async function refreshAccount(addressOverride = '') {
  const state = await readState();
  const address = addressOverride || state.sessionWallet?.address || state.activeVault?.address || '';
  const nodeUrl = el.nodeUrl.value.trim().replace(/\/+$/, '') || 'http://localhost:3000';
  await setStorage({ [NODE_URL_KEY]: nodeUrl });
  if (!address) {
    el.confirmed.textContent = '--';
    el.pending.textContent = '--';
    el.nonce.textContent = '--';
    el.assetMazexBalance.textContent = '0';
    return null;
  }
  const response = await fetch(`${nodeUrl}/api/base1/account?address=${encodeURIComponent(address)}`);
  if (!response.ok) throw new Error(`Node returned ${response.status}`);
  const data = await response.json();
  const account = data.account || {};
  const confirmed = account.confirmed_balance ?? 0;
  el.confirmed.textContent = confirmed;
  el.pending.textContent = account.pending_balance ?? 0;
  el.nonce.textContent = account.nonce ?? 0;
  el.assetMazexBalance.textContent = confirmed;
  return account;
}

async function render() {
  const state = await readState();
  const activeUnlocked = isUnlocked(state);
  const activeAddress = state.activeVault?.address || state.sessionWallet?.address || state.legacyWallet?.address || '';

  el.nodeUrl.value = state.nodeUrl;
  renderAccountSelect(el.accountSelect, state.vaults, state.activeVault?.address || '');
  renderAccountSelect(el.loginAccountSelect, state.vaults, state.activeVault?.address || '');
  renderOrigins(state.connectedOrigins);
  renderSecrets(activeUnlocked ? state.sessionWallet : null);

  el.accountTitle.textContent = state.activeVault?.label || 'Account';
  if (el.address) el.address.textContent = activeAddress || '--';
  el.dashboardAddressText.textContent = activeAddress ? shortHash(activeAddress) : '--';
  el.lockBadge.textContent = activeUnlocked ? 'unlocked' : state.activeVault ? 'locked' : 'no wallet';
  el.lockBadge.classList.toggle('unlocked', activeUnlocked);

  el.unlockBtn.disabled = !state.activeVault || activeUnlocked;
  el.lockBtn.disabled = !activeUnlocked;
  el.copyAddressBtn.disabled = !activeAddress;
  el.copyPhraseBtn.disabled = !activeUnlocked || !state.sessionWallet?.mnemonic;
  el.removeAccountBtn.disabled = !state.activeVault;

  if (currentView === 'dashboard' || currentView === 'settings') {
    if (!activeUnlocked) showView('landing');
  }

  if (currentView === 'login') {
    if (loginMode === 'password') {
      setStatus(
        'loginStatus',
        state.vaults.length ? '' : 'No local wallet vault exists. Use phrase login or register a new wallet.',
      );
    } else if (loginMode === 'phrase') {
      setStatus('loginStatus', '');
    } else {
      setStatus('loginStatus', '');
    }
  }

  if (activeUnlocked) {
    setStatus('dashboardStatus', shortHash(state.sessionWallet.address));
    setStatus('settingsStatus', 'Settings are local to this browser extension.');
  }

  let account = null;
  try {
    account = await refreshAccount(activeAddress);
  } catch (error) {
    if (activeUnlocked) setStatus('dashboardStatus', `Node refresh failed: ${error.message}`, 'error');
  }
  renderAssets(state.customAssets, account?.confirmed_balance ?? el.confirmed.textContent ?? 0);
}

async function setActiveAddress(address) {
  if (!address) return;
  await setStorage({ [ACTIVE_ADDRESS_KEY]: address });
  await removeSession([SESSION_WALLET_KEY]);
  showView('login');
  await render();
}

async function generateRegistrationPhrase() {
  try {
    setBusy(true);
    const password = requirePassword(el.registerPassword, 'Wallet password');
    setStatus('registerStatus', 'Generating recovery phrase locally...');
    const wallet = await createWallet({ strength: 128 });
    const verifyIndexes = chooseVerifyIndexes(wallet.mnemonic.split(/\s+/).length, 3);
    pendingRegistration = { wallet, password, verifyIndexes };
    renderMnemonicWords(wallet.mnemonic);
    showRegisterStep('backup');
    setStatus('registerStatus', 'Write down the recovery phrase in order. The wallet is not stored until confirmation passes.', 'success');
  } catch (error) {
    setStatus('registerStatus', `Recovery phrase generation failed: ${error.message}`, 'error');
  } finally {
    setBusy(false);
  }
}

function continueRegistrationVerification() {
  try {
    if (!pendingRegistration) throw new Error('Generate a recovery phrase first.');
    renderVerifyFields(pendingRegistration.wallet.mnemonic, pendingRegistration.verifyIndexes);
    showRegisterStep('verify');
    setStatus('registerStatus', 'Enter the requested words exactly as shown.', 'success');
  } catch (error) {
    setStatus('registerStatus', error.message, 'error');
  }
}

async function finalizeRegistration() {
  try {
    setBusy(true);
    verifyPendingMnemonic();
    const { wallet, password } = pendingRegistration;
    await writeVault(wallet, password);
    pendingRegistration = null;
    el.registerPassword.value = '';
    el.mnemonicWords.innerHTML = '';
    el.verifyFields.innerHTML = '';
    showRegisterStep('password');
    showView('dashboard');
    await render();
    setStatus('dashboardStatus', `Wallet registered and unlocked: ${shortHash(wallet.address)}.`, 'success');
  } catch (error) {
    setStatus('registerStatus', `Registration failed: ${error.message}`, 'error');
  } finally {
    setBusy(false);
  }
}

async function loginWithRecoveryPhrase() {
  try {
    setBusy(true);
    const password = requirePassword(el.loginPhrasePassword, 'Local password');
    const mnemonic = el.loginMnemonic.value.trim().replace(/\s+/g, ' ');
    if (!mnemonic) throw new Error('Paste a recovery phrase first.');
    setStatus('loginStatus', 'Recovering wallet and encrypting local vault...');
    const wallet = await importMnemonic(mnemonic);
    await writeVault(wallet, password);
    el.loginPhrasePassword.value = '';
    el.loginMnemonic.value = '';
    showView('dashboard');
    await render();
    setStatus('dashboardStatus', `Wallet recovered and unlocked: ${shortHash(wallet.address)}.`, 'success');
  } catch (error) {
    setStatus('loginStatus', `Recovery phrase login failed: ${error.message}`, 'error');
  } finally {
    setBusy(false);
  }
}

async function loginWithPrivateKey() {
  try {
    setBusy(true);
    const password = requirePassword(el.loginPrivatePassword, 'Local password');
    const privateKey = el.loginPrivateKey.value.trim();
    if (!privateKey) throw new Error('Paste a private key first.');
    setStatus('loginStatus', 'Importing private key and encrypting local vault...');
    const wallet = await importPrivateKey(privateKey);
    await writeVault(wallet, password);
    el.loginPrivatePassword.value = '';
    el.loginPrivateKey.value = '';
    showView('dashboard');
    await render();
    setStatus('dashboardStatus', `Private key imported and unlocked: ${shortHash(wallet.address)}.`, 'success');
  } catch (error) {
    setStatus('loginStatus', `Private key login failed: ${error.message}`, 'error');
  } finally {
    setBusy(false);
  }
}

async function unlockWallet() {
  try {
    setBusy(true);
    const state = await readState();
    if (!state.activeVault) throw new Error('No wallet vault is selected.');
    const wallet = await decryptWallet(state.activeVault, requirePassword(el.unlockPassword));
    await setSession({ [SESSION_WALLET_KEY]: wallet });
    el.unlockPassword.value = '';
    showView('dashboard');
    await render();
    setStatus('dashboardStatus', `Wallet unlocked: ${shortHash(wallet.address)}.`, 'success');
  } catch (error) {
    setStatus('loginStatus', `Unlock failed: ${error.message}`, 'error');
  } finally {
    setBusy(false);
  }
}

async function lockWallet() {
  await removeSession([SESSION_WALLET_KEY]);
  showView('landing');
  await render();
}

async function addToken() {
  const symbol = prompt('Token symbol, for example MAZEXAI:');
  if (!symbol) return;
  const normalized = symbol.trim().toUpperCase().replace(/[^A-Z0-9_-]/g, '').slice(0, 16);
  if (!normalized) {
    setStatus('dashboardStatus', 'Invalid token symbol.', 'error');
    return;
  }
  const name = prompt('Token display name:')?.trim().slice(0, 48) || 'Custom asset';
  const state = await readState();
  const nextAssets = [
    { symbol: normalized, name, added_at: new Date().toISOString() },
    ...state.customAssets.filter((asset) => asset.symbol !== normalized),
  ];
  await setStorage({ [CUSTOM_ASSETS_KEY]: nextAssets });
  setStatus('dashboardStatus', `${normalized} added to the local asset list.`, 'success');
  await render();
}

el.registerNavBtn.addEventListener('click', async () => {
  showView('register');
  resetRegistrationFlow();
  setStatus('registerStatus', 'Create a new MazeXChain vault. The wallet is stored only after recovery phrase confirmation.');
  await render();
});

el.loginNavBtn.addEventListener('click', async () => {
  showView('login');
  await render();
});

document.querySelectorAll('[data-back]').forEach((button) => {
  button.addEventListener('click', async () => {
    resetRegistrationFlow();
    showView('landing');
    await render();
  });
});

document.querySelectorAll('[data-dashboard]').forEach((button) => {
  button.addEventListener('click', async () => {
    showView('dashboard');
    await render();
  });
});

el.generatePhraseBtn.addEventListener('click', generateRegistrationPhrase);
el.continueVerifyBtn.addEventListener('click', continueRegistrationVerification);
el.createBtn.addEventListener('click', finalizeRegistration);
el.unlockBtn.addEventListener('click', unlockWallet);
el.loginPhraseBtn.addEventListener('click', loginWithRecoveryPhrase);
el.loginPrivateKeyBtn.addEventListener('click', loginWithPrivateKey);
el.lockBtn.addEventListener('click', lockWallet);
el.addTokenBtn.addEventListener('click', addToken);

el.addAccountBtn.addEventListener('click', async () => {
  showView('register');
  resetRegistrationFlow();
  el.registerPassword.value = '';
  setStatus('registerStatus', 'Create an additional account. The new account becomes active after registration.');
  await render();
});

el.settingsBtn.addEventListener('click', async () => {
  showView('settings');
  await render();
});

el.accountSelect.addEventListener('change', async () => setActiveAddress(el.accountSelect.value));
el.loginAccountSelect.addEventListener('change', async () => setActiveAddress(el.loginAccountSelect.value));
el.loginModeSelect.addEventListener('change', async () => {
  setLoginMode(el.loginModeSelect.value);
  await render();
});

el.copyAddressBtn.addEventListener('click', async () => {
  const state = await readState();
  const address = state.activeVault?.address || state.sessionWallet?.address;
  if (!address) {
    setStatus('dashboardStatus', 'No address to copy.', 'error');
    return;
  }
  await navigator.clipboard.writeText(address);
  setStatus('dashboardStatus', `Address copied: ${shortHash(address)}.`, 'success');
});

el.copyPhraseBtn.addEventListener('click', async () => {
  const state = await readState();
  if (!state.sessionWallet?.mnemonic) {
    setStatus('settingsStatus', 'No recovery phrase is available for the active session.', 'error');
    return;
  }
  await navigator.clipboard.writeText(state.sessionWallet.mnemonic);
  setStatus('settingsStatus', 'Recovery phrase copied. Keep it offline and private.', 'success');
});

el.removeAccountBtn.addEventListener('click', async () => {
  const state = await readState();
  if (!state.activeVault) return;
  if (!confirm(`Remove ${shortHash(state.activeVault.address)} from this extension? Back up the recovery phrase first.`)) return;
  const nextVaults = state.vaults.filter((vault) => vault.address !== state.activeVault.address);
  await setStorage({
    [VAULTS_KEY]: nextVaults,
    [ACTIVE_ADDRESS_KEY]: nextVaults[0]?.address || '',
  });
  await removeSession([SESSION_WALLET_KEY]);
  showView(nextVaults.length ? 'login' : 'landing');
  await render();
});

el.disconnectSitesBtn.addEventListener('click', async () => {
  await setStorage({ [CONNECTED_ORIGINS_KEY]: [] });
  setStatus('settingsStatus', 'All site connections removed. Sites must request connection again.', 'success');
  await render();
});

el.refreshAccountBtn.addEventListener('click', async () => {
  try {
    setBusy(true);
    setStatus('dashboardStatus', 'Refreshing account from node...');
    await refreshAccount();
    const state = await readState();
    setStatus('dashboardStatus', state.activeVault?.address ? `Balance refreshed: ${shortHash(state.activeVault.address)}.` : 'No wallet connected.', 'success');
  } catch (error) {
    setStatus('dashboardStatus', `Refresh failed: ${error.message}`, 'error');
  } finally {
    setBusy(false);
  }
});

el.registerPassword.addEventListener('input', () => {
  el.registerPassword.classList.remove('input-error');
});

el.unlockPassword.addEventListener('input', () => {
  el.unlockPassword.classList.remove('input-error');
});

for (const input of [el.loginPhrasePassword, el.loginPrivatePassword, el.loginMnemonic, el.loginPrivateKey]) {
  input.addEventListener('input', () => input.classList.remove('input-error'));
}

setLoginMode('password');
showView('landing');
await render();
