import { renderHeader } from '../components/header.js';
import { authService, state } from '../state.js';
import {
  createRandomSolanaWallet,
  createSolanaWalletFromPrivateBase58,
  formatSol,
  getBalanceSol,
  getTopupSiteUrl,
  getWalletFromStoredDeviceKey,
  transferSol,
} from '../services/solana-wallet-service.js';
import {
  formatAr,
  getArweaveBalance,
  getArweaveTopupSiteUrl,
  getArweaveWalletFromStoredDeviceKey,
  transferAr,
} from '../services/arweave-wallet-service.js';
import { loadEncryptedUserSecrets } from '../services/key-vault.js';
import {
  calcLimitTopupPriceLamports,
  getLimitStepBytes,
  getShineBlockchainUsage,
  getShineUsersEconomyConfig,
  updateShineUserPdaOnSolana,
} from '../services/shine-blockchain-wallet-service.js?v=202605300007';

export const pageMeta = { id: 'wallet-view', title: 'Кошелёк' };
const SOLANA_PRIVATE_BASE58_MAX_LEN = 44;

function nowRu() {
  return new Date().toLocaleString('ru-RU');
}

function formatKbFromBytes(rawBytes) {
  const bytes = typeof rawBytes === 'bigint'
    ? Number(rawBytes)
    : Number(rawBytes || 0);
  if (!Number.isFinite(bytes) || bytes <= 0) return '0 KB';
  const kb = bytes / 1024;
  return `${kb.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} KB`;
}

function lamportsToSolText(lamportsBigInt) {
  const value = Number(lamportsBigInt || 0n) / 1_000_000_000;
  return value.toLocaleString('ru-RU', { minimumFractionDigits: 0, maximumFractionDigits: 9 });
}

function createModeBackButton(renderWalletChoice) {
  const backBtn = document.createElement('button');
  backBtn.className = 'text-btn';
  backBtn.textContent = '← К выбору кошелька';
  backBtn.addEventListener('click', () => {
    renderWalletChoice();
  });
  return backBtn;
}

function sessionArgsOrThrow() {
  const login = String(state.session.login || '').trim();
  const storagePwd = String(state.session.storagePwdInMemory || '').trim();
  if (!login || !storagePwd) {
    throw new Error('Нет активной сессии. Выполните вход заново.');
  }
  return { login, storagePwd };
}

export function render({ navigate }) {
  const screen = document.createElement('section');
  screen.className = 'stack';

  const status = document.createElement('p');
  status.className = 'meta-muted';
  const setStatus = (text) => {
    status.textContent = String(text || '');
  };

  const content = document.createElement('div');
  content.className = 'stack';

  screen.append(
    renderHeader({
      title: 'Кошелёк',
      leftAction: { label: '←', onClick: () => navigate('profile-view') },
    }),
    content,
    status,
  );

  let activeModeToken = 0;
  let arweaveWalletCtx = null;

  function clearArweaveSecretsInMemory() {
    if (!arweaveWalletCtx?.jwk) return;
    Object.keys(arweaveWalletCtx.jwk).forEach((key) => {
      arweaveWalletCtx.jwk[key] = '';
    });
    arweaveWalletCtx.jwk = null;
    arweaveWalletCtx = null;
  }

  function renderWalletChoice() {
    activeModeToken += 1;
    clearArweaveSecretsInMemory();
    content.innerHTML = '';

    const card = document.createElement('div');
    card.className = 'card stack';
    card.innerHTML = `
      <h2 style="margin:0 0 6px;">Кошелёк</h2>
      <p class="meta-muted">Выберите режим кошелька.</p>
    `;

    const solanaBtn = document.createElement('button');
    solanaBtn.className = 'primary-btn';
    solanaBtn.style.width = '100%';
    solanaBtn.textContent = 'Solana кошелёк';
    solanaBtn.addEventListener('click', () => {
      void renderSolanaWallet();
    });

    const arweaveBtn = document.createElement('button');
    arweaveBtn.className = 'primary-btn';
    arweaveBtn.style.width = '100%';
    arweaveBtn.textContent = 'Arweave кошелёк';
    arweaveBtn.addEventListener('click', () => {
      void renderArweaveWallet();
    });

    const shineBchBtn = document.createElement('button');
    shineBchBtn.className = 'primary-btn';
    shineBchBtn.style.width = '100%';
    shineBchBtn.textContent = 'Блокчейн Сияния';
    shineBchBtn.addEventListener('click', () => {
      void renderShineBlockchainWallet();
    });

    card.append(solanaBtn, arweaveBtn, shineBchBtn);
    content.append(card);
    setStatus('Выберите тип кошелька.');
  }

  async function renderShineBlockchainWallet() {
    const modeToken = ++activeModeToken;
    clearArweaveSecretsInMemory();
    content.innerHTML = '';

    const backBtn = createModeBackButton(renderWalletChoice);
    const card = document.createElement('div');
    card.className = 'card stack';

    const limitLabel = document.createElement('p');
    limitLabel.className = 'meta-muted';
    limitLabel.textContent = 'Лимит блокчейна';
    const limitValue = document.createElement('h2');
    limitValue.style.fontSize = '26px';
    limitValue.textContent = '— KB';

    const usedLabel = document.createElement('p');
    usedLabel.className = 'meta-muted';
    usedLabel.textContent = 'Израсходовано (фактически на сервере)';
    const usedValue = document.createElement('h2');
    usedValue.style.fontSize = '26px';
    usedValue.textContent = '— KB';

    const leftLabel = document.createElement('p');
    leftLabel.className = 'meta-muted';
    leftLabel.textContent = 'Осталось';
    const leftValue = document.createElement('h2');
    leftValue.style.fontSize = '30px';
    leftValue.textContent = '— KB';

    const pdaLabel = document.createElement('p');
    pdaLabel.className = 'meta-muted';
    pdaLabel.style.wordBreak = 'break-all';
    pdaLabel.textContent = 'PDA: —';

    const endpointLabel = document.createElement('p');
    endpointLabel.className = 'meta-muted';
    endpointLabel.textContent = `RPC: ${state.entrySettings.solanaServer}`;

    const updatedLabel = document.createElement('p');
    updatedLabel.className = 'meta-muted';
    updatedLabel.textContent = 'Обновлено: —';

    const serverTitle = document.createElement('h3');
    serverTitle.style.margin = '14px 0 0';
    serverTitle.textContent = 'Фактическое состояние на сервере';
    const serverSizeLabel = document.createElement('p');
    serverSizeLabel.className = 'meta-muted';
    serverSizeLabel.textContent = 'Размер цепочки: —';
    const serverLastLabel = document.createElement('p');
    serverLastLabel.className = 'meta-muted';
    serverLastLabel.textContent = 'Крайний блок: —';
    const serverLastHashLabel = document.createElement('p');
    serverLastHashLabel.className = 'meta-muted';
    serverLastHashLabel.style.wordBreak = 'break-all';
    serverLastHashLabel.style.fontSize = '11px';
    serverLastHashLabel.textContent = 'Hash: —';

    const solanaTitle = document.createElement('h3');
    solanaTitle.style.margin = '14px 0 0';
    solanaTitle.textContent = 'Закреплено в Solana';
    const solanaLastLabel = document.createElement('p');
    solanaLastLabel.className = 'meta-muted';
    solanaLastLabel.textContent = 'Крайний блок: —';
    const solanaLastHashLabel = document.createElement('p');
    solanaLastHashLabel.className = 'meta-muted';
    solanaLastHashLabel.style.wordBreak = 'break-all';
    solanaLastHashLabel.style.fontSize = '11px';
    solanaLastHashLabel.textContent = 'Hash: —';

    card.append(
      limitLabel,
      limitValue,
      usedLabel,
      usedValue,
      leftLabel,
      leftValue,
      pdaLabel,
      endpointLabel,
      updatedLabel,
      serverTitle,
      serverSizeLabel,
      serverLastLabel,
      serverLastHashLabel,
      solanaTitle,
      solanaLastLabel,
      solanaLastHashLabel,
    );

    const actions = document.createElement('div');
    actions.className = 'stack';
    actions.innerHTML = `
      <button class="ghost-btn" id="refresh-shine-bch" style="width:100%;">Обновить</button>
      <button class="primary-btn" id="sync-shine-solana" style="width:100%;">Закрепить в Solana</button>
      <button class="primary-btn" id="topup-shine-limit" style="width:100%;">Увеличить лимит</button>
    `;
    const refreshBtn = actions.querySelector('#refresh-shine-bch');
    const syncBtn = actions.querySelector('#sync-shine-solana');
    const topupBtn = actions.querySelector('#topup-shine-limit');

    const fetchServerState = async () => {
      const user = await authService.getUser(String(state.session.login || '').trim());
      if (!user?.exists) throw new Error('Пользователь не найден на сервере');
      const lastNumber = Number(user.serverLastGlobalNumber ?? -1);
      return {
        sizeBytes: Number(user.serverBlockchainSizeBytes || 0),
        sizeLimitBytes: Number(user.serverBlockchainSizeLimitBytes || 0),
        lastNumber,
        lastHash: String(user.serverLastGlobalHash || ''),
      };
    };

    const resolveWalletSigningMaterial = async () => {
      const { login, storagePwd } = sessionArgsOrThrow();
      let saved;
      try {
        saved = await loadEncryptedUserSecrets(login, storagePwd);
      } catch {
        saved = null;
      }
      let rootKey = String(saved?.rootKey || '').trim();
      let blockchainKey = String(saved?.blockchainKey || '').trim();
      const deviceKey = String(saved?.deviceKey || '').trim();
      if (!deviceKey) throw new Error('На устройстве нет device.key. Выполните вход заново.');
      if (rootKey && blockchainKey) {
        return { rootPrivatePkcs8B64: rootKey, blockchainPrivatePkcs8B64: blockchainKey, devicePrivatePkcs8B64: deviceKey };
      }

      const password = window.prompt(
        'Для операции нужен root key (и blockchain key), но они не сохранены на устройстве.\nВведите пароль аккаунта для временного восстановления ключей:',
        '',
      );
      if (password == null) throw new Error('Операция отменена пользователем');
      const keyBundle = await authService.derivePasswordKeyBundle(login, password);
      rootKey = keyBundle?.rootPair?.privatePkcs8B64 || '';
      blockchainKey = keyBundle?.blockchainPair?.privatePkcs8B64 || '';
      if (!rootKey || !blockchainKey) throw new Error('Не удалось восстановить root/blockchain key из пароля');

      const shouldSave = window.confirm(
        'Сохранить root key и blockchain key в зашифрованном контейнере этого устройства?\nВнимание: хранить ключи на телефоне менее безопасно.',
      );
      if (shouldSave) {
        await authService.persistSelectedKeys(login, storagePwd, keyBundle, { saveRoot: true, saveBlockchain: true });
      }
      return { rootPrivatePkcs8B64: rootKey, blockchainPrivatePkcs8B64: blockchainKey, devicePrivatePkcs8B64: deviceKey };
    };

    const setButtonsDisabled = (disabled) => {
      refreshBtn.disabled = disabled;
      syncBtn.disabled = disabled;
      topupBtn.disabled = disabled;
    };

    const refreshUsage = async () => {
      setButtonsDisabled(true);
      try {
        const [usage, serverState] = await Promise.all([
          getShineBlockchainUsage({
            login: String(state.session.login || '').trim(),
            solanaEndpoint: state.entrySettings.solanaServer,
          }),
          fetchServerState(),
        ]);
        if (modeToken !== activeModeToken) return;
        limitValue.textContent = formatKbFromBytes(usage.paidLimitBytes);
        const usedServerBytes = BigInt(Math.max(0, Number(serverState.sizeBytes || 0)));
        const leftServerBytes = usage.paidLimitBytes > usedServerBytes ? (usage.paidLimitBytes - usedServerBytes) : 0n;
        usedValue.textContent = formatKbFromBytes(usedServerBytes);
        leftValue.textContent = formatKbFromBytes(leftServerBytes);
        pdaLabel.textContent = `PDA: ${usage.userPda}`;
        endpointLabel.textContent = `RPC: ${usage.endpoint}`;
        updatedLabel.textContent = `Обновлено: ${nowRu()}`;

        serverSizeLabel.textContent = `Размер цепочки: ${formatKbFromBytes(serverState.sizeBytes)}`;
        serverLastLabel.textContent = `Крайний блок: ${serverState.lastNumber}`;
        serverLastHashLabel.textContent = `Hash: ${serverState.lastHash || '—'}`;

        solanaLastLabel.textContent = `Крайний блок: ${usage.lastBlockNumber}`;
        solanaLastHashLabel.textContent = `Hash: ${usage.lastBlockHashHex || '—'}`;

        setStatus('Данные лимита и состояния блокчейна обновлены.');
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Не удалось обновить состояние блокчейна: ${error?.message || 'unknown'}`);
      } finally {
        setButtonsDisabled(false);
      }
    };

    syncBtn.addEventListener('click', async () => {
      setButtonsDisabled(true);
      try {
        const [serverState, signing] = await Promise.all([
          fetchServerState(),
          resolveWalletSigningMaterial(),
        ]);
        const result = await updateShineUserPdaOnSolana({
          login: String(state.session.login || '').trim(),
          solanaEndpoint: state.entrySettings.solanaServer,
          rootPrivatePkcs8B64: signing.rootPrivatePkcs8B64,
          blockchainPrivatePkcs8B64: signing.blockchainPrivatePkcs8B64,
          devicePrivatePkcs8B64: signing.devicePrivatePkcs8B64,
          additionalLimitBytes: 0n,
          nextUsedBytes: BigInt(Math.max(0, serverState.sizeBytes)),
          nextLastBlockNumber: serverState.lastNumber,
          nextLastBlockHashHex: serverState.lastHash,
        });
        if (modeToken !== activeModeToken) return;
        setStatus(`Состояние закреплено в Solana. Tx: ${result.signature}`);
        await refreshUsage();
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Не удалось закрепить состояние в Solana: ${error?.message || 'unknown'}`);
      } finally {
        setButtonsDisabled(false);
      }
    });

    topupBtn.addEventListener('click', async () => {
      setButtonsDisabled(true);
      try {
        const economy = await getShineUsersEconomyConfig({ solanaEndpoint: state.entrySettings.solanaServer });
        const step = getLimitStepBytes();
        const input = window.prompt(
          `Введите, на сколько увеличить лимит (в байтах, шаг ${step.toString()}).\nЦена за шаг: ${lamportsToSolText(economy.lamportsPerLimitStep)} SOL`,
          step.toString(),
        );
        if (!input) {
          setStatus('Увеличение лимита отменено.');
          return;
        }
        const addBytes = BigInt(String(input).trim());
        const priceLamports = calcLimitTopupPriceLamports(addBytes, economy.lamportsPerLimitStep);
        const confirm = window.confirm(
          `Будет увеличено на ${formatKbFromBytes(addBytes)}.\n` +
          `С вашего Solana-счёта будет списано ~${lamportsToSolText(priceLamports)} SOL.\n` +
          `Продолжить?`,
        );
        if (!confirm) {
          setStatus('Увеличение лимита отменено.');
          return;
        }
        const signing = await resolveWalletSigningMaterial();
        const result = await updateShineUserPdaOnSolana({
          login: String(state.session.login || '').trim(),
          solanaEndpoint: state.entrySettings.solanaServer,
          rootPrivatePkcs8B64: signing.rootPrivatePkcs8B64,
          blockchainPrivatePkcs8B64: signing.blockchainPrivatePkcs8B64,
          devicePrivatePkcs8B64: signing.devicePrivatePkcs8B64,
          additionalLimitBytes: addBytes,
        });
        if (modeToken !== activeModeToken) return;
        setStatus(`Лимит увеличен. Tx: ${result.signature}`);
        await refreshUsage();
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Не удалось увеличить лимит: ${error?.message || 'unknown'}`);
      } finally {
        setButtonsDisabled(false);
      }
    });

    refreshBtn.addEventListener('click', () => {
      void refreshUsage();
    });

    content.append(backBtn, card, actions);
    setStatus('Загрузка данных блокчейна Сияния...');
    await refreshUsage();
  }

  async function renderSolanaWallet() {
    const modeToken = ++activeModeToken;
    clearArweaveSecretsInMemory();
    content.innerHTML = '';

    let walletCtx = null;
    let walletAddress = '';

    const backBtn = createModeBackButton(renderWalletChoice);

    const card = document.createElement('div');
    card.className = 'card stack';

    const balanceWrap = document.createElement('div');
    const balanceLabel = document.createElement('p');
    balanceLabel.className = 'meta-muted';
    balanceLabel.textContent = 'Баланс (Solana)';
    const balanceValue = document.createElement('h2');
    balanceValue.style.fontSize = '30px';
    balanceValue.textContent = '— SOL';
    const updatedLabel = document.createElement('p');
    updatedLabel.className = 'meta-muted';
    updatedLabel.textContent = 'Обновлено: —';
    const endpointLabel = document.createElement('p');
    endpointLabel.className = 'meta-muted';
    endpointLabel.textContent = `RPC: ${state.entrySettings.solanaServer}`;
    balanceWrap.append(balanceLabel, balanceValue, updatedLabel, endpointLabel);

    const addressCard = document.createElement('div');
    addressCard.className = 'card';
    addressCard.style.padding = '10px';
    addressCard.innerHTML = `
      <p class="meta-muted" style="margin-bottom:6px;">Публичный адрес (wallet.key = device.key)</p>
      <p style="font-size:13px; line-height:1.4; word-break:break-all;" id="wallet-address-value">—</p>
    `;
    const addressEl = addressCard.querySelector('#wallet-address-value');

    card.append(balanceWrap, addressCard);

    const actions = document.createElement('div');
    actions.className = 'stack';
    actions.innerHTML = `
      <div class="row">
        <button class="text-btn" id="copy-address">Копировать адрес</button>
        <button class="ghost-btn" id="refresh-balance">Обновить баланс</button>
      </div>
      <div class="row">
        <button class="primary-btn" id="send-sol" style="width:100%;">Перевести</button>
        <button class="primary-btn" id="topup-sol" style="width:100%;">Пополнить</button>
      </div>
    `;

    const copyBtn = actions.querySelector('#copy-address');
    const refreshBtn = actions.querySelector('#refresh-balance');
    const sendBtn = actions.querySelector('#send-sol');
    const topupBtn = actions.querySelector('#topup-sol');

    const generatedCard = document.createElement('div');
    generatedCard.className = 'card stack';
    generatedCard.innerHTML = `
      <h3 style="margin:0;">Создание нового кошелька Solana</h3>
      <p class="meta-muted" style="margin:0;">Введите приватный ключ Base58 (32 байта) или сгенерируйте случайный.</p>
    `;

    const privateLabel = document.createElement('label');
    privateLabel.className = 'meta-muted';
    privateLabel.textContent = 'Приватный ключ (Base58, 32 байта)';
    privateLabel.setAttribute('for', 'solana-private-base58-input');

    const privateInput = document.createElement('input');
    privateInput.id = 'solana-private-base58-input';
    privateInput.type = 'text';
    privateInput.placeholder = 'Введите приватный ключ Base58';
    privateInput.maxLength = SOLANA_PRIVATE_BASE58_MAX_LEN;
    privateInput.autocomplete = 'off';
    privateInput.spellcheck = false;

    const privateState = document.createElement('p');
    privateState.className = 'meta-muted';
    privateState.textContent = 'Ожидается Base58-строка приватного ключа.';

    const generatedPublicLabel = document.createElement('label');
    generatedPublicLabel.className = 'meta-muted';
    generatedPublicLabel.textContent = 'Публичный ключ (Base58)';
    generatedPublicLabel.setAttribute('for', 'solana-generated-public-key');

    const generatedPublicInput = document.createElement('input');
    generatedPublicInput.id = 'solana-generated-public-key';
    generatedPublicInput.type = 'text';
    generatedPublicInput.readOnly = true;
    generatedPublicInput.placeholder = 'Будет сгенерирован после нажатия кнопки';

    const generatedPrivateLabel = document.createElement('label');
    generatedPrivateLabel.className = 'meta-muted';
    generatedPrivateLabel.textContent = 'Сгенерированный приватный ключ (Base58)';
    generatedPrivateLabel.setAttribute('for', 'solana-generated-private-key');

    const generatedPrivateInput = document.createElement('input');
    generatedPrivateInput.id = 'solana-generated-private-key';
    generatedPrivateInput.type = 'text';
    generatedPrivateInput.readOnly = true;
    generatedPrivateInput.placeholder = 'Появится после генерации';

    const generationActions = document.createElement('div');
    generationActions.className = 'row';
    generationActions.innerHTML = `
      <button class="primary-btn" id="generate-random-solana" style="width:100%;">Сгенерировать случайный кошелёк</button>
      <button class="primary-btn" id="generate-from-private-solana" style="width:100%;">Сгенерировать из приватного ключа</button>
    `;

    const copyGeneratedActions = document.createElement('div');
    copyGeneratedActions.className = 'row';
    copyGeneratedActions.innerHTML = `
      <button class="text-btn" id="copy-generated-private-solana" style="width:100%;">Копировать приватный</button>
      <button class="text-btn" id="copy-generated-public-solana" style="width:100%;">Копировать публичный</button>
    `;

    generatedCard.append(
      privateLabel,
      privateInput,
      privateState,
      generationActions,
      generatedPrivateLabel,
      generatedPrivateInput,
      generatedPublicLabel,
      generatedPublicInput,
      copyGeneratedActions,
    );

    const randomGenerateBtn = generationActions.querySelector('#generate-random-solana');
    const fromPrivateGenerateBtn = generationActions.querySelector('#generate-from-private-solana');
    const copyGeneratedPrivateBtn = copyGeneratedActions.querySelector('#copy-generated-private-solana');
    const copyGeneratedPublicBtn = copyGeneratedActions.querySelector('#copy-generated-public-solana');

    const BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]+$/;
    const validatePrivateInput = () => {
      const value = String(privateInput.value || '').trim();
      if (!value) {
        privateState.textContent = 'Ожидается Base58-строка приватного ключа.';
        return false;
      }
      if (!BASE58_RE.test(value)) {
        privateState.textContent = 'Недопустимый формат: используйте только Base58.';
        return false;
      }
      if (value.length > SOLANA_PRIVATE_BASE58_MAX_LEN) {
        privateState.textContent = 'Слишком длинное значение.';
        return false;
      }
      try {
        const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
        let num = 0n;
        for (const c of value) {
          num = num * 58n + BigInt(alphabet.indexOf(c));
        }
        let hex = num.toString(16);
        if (hex.length % 2) hex = `0${hex}`;
        const decoded = hex ? hex.match(/.{1,2}/g)?.map((h) => parseInt(h, 16)) || [] : [];
        let leadingZeros = 0;
        while (leadingZeros < value.length && value[leadingZeros] === '1') leadingZeros += 1;
        const byteLen = leadingZeros + decoded.length;
        if (byteLen < 32) {
          privateState.textContent = 'Слишком короткое значение: нужно 32 байта.';
          return false;
        }
        if (byteLen > 32) {
          privateState.textContent = 'Слишком длинное значение: нужно ровно 32 байта.';
          return false;
        }
      } catch {
        privateState.textContent = 'Ошибка декодирования Base58.';
        return false;
      }
      privateState.textContent = 'Подходит';
      return true;
    };

    privateInput.addEventListener('input', () => {
      validatePrivateInput();
    });

    const setGenerationDisabled = (disabled) => {
      randomGenerateBtn.disabled = disabled;
      fromPrivateGenerateBtn.disabled = disabled;
      copyGeneratedPrivateBtn.disabled = disabled;
      copyGeneratedPublicBtn.disabled = disabled;
    };

    randomGenerateBtn.addEventListener('click', async () => {
      setGenerationDisabled(true);
      try {
        const generated = await createRandomSolanaWallet();
        if (modeToken !== activeModeToken) return;
        generatedPrivateInput.value = generated.privateKey32Base58;
        generatedPublicInput.value = generated.address;
        privateState.textContent = 'Случайный кошелёк создан.';
        setStatus('Случайный кошелёк Solana успешно сгенерирован.');
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Ошибка генерации случайного кошелька: ${error?.message || 'unknown'}`);
      } finally {
        setGenerationDisabled(false);
      }
    });

    fromPrivateGenerateBtn.addEventListener('click', async () => {
      if (!validatePrivateInput()) {
        setStatus('Исправьте приватный ключ перед генерацией.');
        return;
      }
      setGenerationDisabled(true);
      try {
        const generated = await createSolanaWalletFromPrivateBase58(privateInput.value);
        if (modeToken !== activeModeToken) return;
        generatedPrivateInput.value = generated.privateKey32Base58;
        generatedPublicInput.value = generated.address;
        privateState.textContent = 'Подходит';
        setStatus('Публичный ключ сгенерирован из введённого приватного ключа.');
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Ошибка генерации из приватного ключа: ${error?.message || 'unknown'}`);
      } finally {
        setGenerationDisabled(false);
      }
    });

    copyGeneratedPrivateBtn.addEventListener('click', async () => {
      const value = String(generatedPrivateInput.value || '').trim();
      if (!value) {
        setStatus('Сначала сгенерируйте приватный ключ.');
        return;
      }
      try {
        await navigator.clipboard.writeText(value);
        setStatus('Приватный ключ скопирован.');
      } catch {
        setStatus('Не удалось скопировать приватный ключ в этом браузере.');
      }
    });

    copyGeneratedPublicBtn.addEventListener('click', async () => {
      const value = String(generatedPublicInput.value || '').trim();
      if (!value) {
        setStatus('Сначала сгенерируйте публичный ключ.');
        return;
      }
      try {
        await navigator.clipboard.writeText(value);
        setStatus('Публичный ключ скопирован.');
      } catch {
        setStatus('Не удалось скопировать публичный ключ в этом браузере.');
      }
    });

    const refreshBalance = async () => {
      if (!walletAddress) {
        setStatus('Кошелёк не инициализирован.');
        return;
      }
      refreshBtn.disabled = true;
      try {
        const balance = await getBalanceSol({
          endpoint: state.entrySettings.solanaServer,
          address: walletAddress,
        });
        if (modeToken !== activeModeToken) return;
        balanceValue.textContent = `${formatSol(balance.sol, 6)} SOL`;
        updatedLabel.textContent = `Обновлено: ${nowRu()}`;
        endpointLabel.textContent = `RPC: ${balance.endpoint}`;
        setStatus('Баланс обновлён.');
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Не удалось получить баланс: ${error?.message || 'unknown'}`);
      } finally {
        refreshBtn.disabled = false;
      }
    };

    copyBtn.addEventListener('click', async () => {
      if (!walletAddress) return;
      try {
        await navigator.clipboard.writeText(walletAddress);
        setStatus('Адрес скопирован в буфер обмена');
      } catch {
        setStatus('Не удалось скопировать адрес в этом браузере');
      }
    });

    refreshBtn.addEventListener('click', () => {
      void refreshBalance();
    });

    sendBtn.addEventListener('click', async () => {
      if (!walletCtx?.keypair) {
        setStatus('Перевод недоступен: wallet.key не загружен.');
        return;
      }
      const toAddress = window.prompt('Введите адрес получателя (Solana):', '');
      if (!toAddress) return;
      const amountRaw = window.prompt('Введите сумму SOL для перевода:', '0.01');
      if (!amountRaw) return;

      sendBtn.disabled = true;
      try {
        const tx = await transferSol({
          endpoint: state.entrySettings.solanaServer,
          fromKeypair: walletCtx.keypair,
          toAddress,
          amountSol: Number(String(amountRaw || '').replace(',', '.')),
        });
        if (modeToken !== activeModeToken) return;
        setStatus(`Перевод отправлен. Signature: ${tx.signature}`);
        await refreshBalance();
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Ошибка перевода: ${error?.message || 'unknown'}`);
      } finally {
        sendBtn.disabled = false;
      }
    });

    topupBtn.addEventListener('click', async () => {
      if (!walletAddress) {
        setStatus('Кошелёк не инициализирован.');
        return;
      }
      window.location.assign(getTopupSiteUrl(walletAddress));
    });

    content.append(backBtn, card, actions, generatedCard);
    setStatus('Инициализация wallet.key...');

    try {
      walletCtx = await getWalletFromStoredDeviceKey(sessionArgsOrThrow());
      if (modeToken !== activeModeToken) return;
      walletAddress = walletCtx.address;
      addressEl.textContent = walletAddress;
      await refreshBalance();
    } catch (error) {
      if (modeToken !== activeModeToken) return;
      addressEl.textContent = 'wallet.key недоступен';
      setStatus(`Не удалось инициализировать кошелёк: ${error?.message || 'unknown'}`);
    }
  }

  async function renderArweaveWallet() {
    const modeToken = ++activeModeToken;
    content.innerHTML = '';

    let walletAddress = '';

    const backBtn = createModeBackButton(renderWalletChoice);

    const card = document.createElement('div');
    card.className = 'card stack';

    const balanceWrap = document.createElement('div');
    const balanceLabel = document.createElement('p');
    balanceLabel.className = 'meta-muted';
    balanceLabel.textContent = 'Баланс (Arweave)';
    const balanceValue = document.createElement('h2');
    balanceValue.style.fontSize = '30px';
    balanceValue.textContent = '— AR';
    const updatedLabel = document.createElement('p');
    updatedLabel.className = 'meta-muted';
    updatedLabel.textContent = 'Обновлено: —';
    const gatewayLabel = document.createElement('p');
    gatewayLabel.className = 'meta-muted';
    gatewayLabel.textContent = `Gateway: ${state.entrySettings.arweaveServer}`;
    balanceWrap.append(balanceLabel, balanceValue, updatedLabel, gatewayLabel);

    const addressCard = document.createElement('div');
    addressCard.className = 'card';
    addressCard.style.padding = '10px';
    addressCard.innerHTML = `
      <p class="meta-muted" style="margin-bottom:6px;">Публичный адрес Arweave (SAWD-v1)</p>
      <p style="font-size:13px; line-height:1.4; word-break:break-all;" id="wallet-address-value">—</p>
    `;
    const addressEl = addressCard.querySelector('#wallet-address-value');

    const helpCard = document.createElement('details');
    helpCard.className = 'card';
    helpCard.style.padding = '10px';
    helpCard.innerHTML = `
      <summary style="cursor:pointer; font-weight:600;">Как получен этот адрес?</summary>
      <p class="meta-muted" style="margin-top:8px;">
        SHiNE берёт ваш локальный device.key и по стандарту SAWD-v1 получает из него нативный Arweave-кошелёк.
        Приватный ключ не отправляется на сервер. После первого расчёта он хранится только в зашифрованном контейнере этого устройства.
      </p>
    `;

    card.append(balanceWrap, addressCard, helpCard);

    const actions = document.createElement('div');
    actions.className = 'stack';
    actions.innerHTML = `
      <div class="row">
        <button class="text-btn" id="copy-address">Копировать адрес</button>
        <button class="ghost-btn" id="refresh-balance">Обновить баланс</button>
      </div>
      <div class="row">
        <button class="primary-btn" id="send-ar" style="width:100%;">Перевести</button>
        <button class="primary-btn" id="topup-ar" style="width:100%;">Пополнить</button>
      </div>
    `;

    const copyBtn = actions.querySelector('#copy-address');
    const refreshBtn = actions.querySelector('#refresh-balance');
    const sendBtn = actions.querySelector('#send-ar');
    const topupBtn = actions.querySelector('#topup-ar');

    const refreshBalance = async () => {
      if (!walletAddress) {
        setStatus('Arweave-кошелёк не инициализирован.');
        return;
      }
      refreshBtn.disabled = true;
      try {
        const balance = await getArweaveBalance({
          gateway: state.entrySettings.arweaveServer,
          address: walletAddress,
        });
        if (modeToken !== activeModeToken) return;
        balanceValue.textContent = `${formatAr(balance.ar, 6)} AR`;
        updatedLabel.textContent = `Обновлено: ${nowRu()}`;
        gatewayLabel.textContent = `Gateway: ${balance.gateway}`;
        setStatus('Баланс обновлён.');
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Не удалось получить баланс: ${error?.message || 'unknown'}`);
      } finally {
        refreshBtn.disabled = false;
      }
    };

    copyBtn.addEventListener('click', async () => {
      if (!walletAddress) return;
      try {
        await navigator.clipboard.writeText(walletAddress);
        setStatus('Адрес скопирован');
      } catch {
        setStatus('Не удалось скопировать адрес в этом браузере');
      }
    });

    refreshBtn.addEventListener('click', () => {
      void refreshBalance();
    });

    sendBtn.addEventListener('click', async () => {
      if (!arweaveWalletCtx?.jwk) {
        setStatus('Перевод недоступен: Arweave-кошелёк не инициализирован.');
        return;
      }
      const toAddress = window.prompt('Введите адрес получателя (Arweave):', '');
      if (!toAddress) return;
      const amountRaw = window.prompt('Введите сумму AR для перевода:', '0.01');
      if (!amountRaw) return;

      sendBtn.disabled = true;
      try {
        const tx = await transferAr({
          gateway: state.entrySettings.arweaveServer,
          jwk: arweaveWalletCtx.jwk,
          toAddress,
          amountAr: amountRaw,
        });
        if (modeToken !== activeModeToken) return;
        setStatus(`Перевод отправлен. Transaction ID: ${tx.id}`);
        await refreshBalance();
      } catch (error) {
        if (modeToken !== activeModeToken) return;
        setStatus(`Ошибка перевода: ${error?.message || 'unknown'}`);
      } finally {
        sendBtn.disabled = false;
      }
    });

    topupBtn.addEventListener('click', () => {
      window.open(getArweaveTopupSiteUrl(), '_blank', 'noopener,noreferrer');
      setStatus('Открыта страница пополнения.');
    });

    content.append(backBtn, card, actions);
    setStatus('Генерация Arweave-кошелька...');

    try {
      let wasFirstTimeGeneration = false;
      arweaveWalletCtx = await getArweaveWalletFromStoredDeviceKey({
        ...sessionArgsOrThrow(),
        onStatus: (message) => {
          const text = String(message || '').trim();
          if (!text) return;
          if (text.includes('впервые получаем Arweave-кошелёк')) {
            wasFirstTimeGeneration = true;
            setStatus('Подождите — ваш Arweave-ключ вычисляется из device key. Это происходит только один раз, потом будет мгновенно.');
            return;
          }
          setStatus(text);
        },
      });
      if (modeToken !== activeModeToken) return;
      if (wasFirstTimeGeneration) setStatus('');
      walletAddress = arweaveWalletCtx.address;
      addressEl.textContent = walletAddress;
      await refreshBalance();
    } catch (error) {
      if (modeToken !== activeModeToken) return;
      addressEl.textContent = 'wallet.key недоступен';
      clearArweaveSecretsInMemory();
      setStatus(`Не удалось инициализировать Arweave-кошелёк: ${error?.message || 'unknown'}`);
    }
  }

  renderWalletChoice();
  return screen;
}
