import { renderHeader } from '../components/header.js';
import {
  authService,
  setAuthError,
  setAuthInfo,
  state,
} from '../state.js';
import { toUserMessage } from '../services/ui-error-texts.js';
import {
  formatSol,
  getBalanceSol,
  getTopupSiteUrl,
} from '../services/solana-wallet-service.js';
import {
  formatSolanaErrorDetails,
  isUserAlreadyExistsSolanaError,
  registerUserOnSolana,
} from '../services/solana-register-service.js';

export const pageMeta = { id: 'registration-payment-view', title: 'Оплата регистрации', showAppChrome: false };
const MIN_REQUIRED_SOL = 0.01;
const SOLANA_SYNC_WAIT_SEC = 15;

function parseBalanceSol(value) {
  const parsed = Number.parseFloat(String(value || '').replace(',', '.'));
  return Number.isFinite(parsed) ? parsed : 0;
}

function getCryptoRuntimeState() {
  const hasCrypto = Boolean(globalThis.crypto);
  const hasGetRandomValues = Boolean(globalThis.crypto && typeof globalThis.crypto.getRandomValues === 'function');
  const hasSubtle = Boolean(globalThis.crypto && (globalThis.crypto.subtle || globalThis.crypto.webkitSubtle));
  const secureContext = window.isSecureContext === true;
  return { hasCrypto, hasGetRandomValues, hasSubtle, secureContext };
}

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

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

  const status = document.createElement('p');
  status.className = 'status-line is-unavailable';
  status.style.display = 'none';

  const walletValue = document.createElement('input');
  walletValue.className = 'input';
  walletValue.type = 'text';
  walletValue.value = state.registrationPayment.walletAddress || '';
  walletValue.readOnly = true;

  const walletRow = document.createElement('div');
  walletRow.className = 'inline-input-row';

  const copyButton = document.createElement('button');
  copyButton.className = 'ghost-btn';
  copyButton.type = 'button';
  copyButton.textContent = 'Скопировать номер';
  copyButton.addEventListener('click', async () => {
    try {
      await navigator.clipboard.writeText(walletValue.value);
      copyButton.textContent = 'Скопировано';
      window.setTimeout(() => {
        copyButton.textContent = 'Скопировать номер';
      }, 1500);
    } catch {
      status.className = 'status-line is-unavailable';
      status.textContent = 'Не удалось скопировать номер кошелька.';
      status.style.display = '';
    }
  });

  walletRow.append(walletValue, copyButton);

  const balanceRow = document.createElement('div');
  balanceRow.className = 'row wrap-row';

  const balanceValue = document.createElement('strong');
  balanceValue.textContent = `${formatSol(parseBalanceSol(state.registrationPayment.balanceSOL), 6)} SOL`;

  const refreshButton = document.createElement('button');
  refreshButton.className = 'square-btn';
  refreshButton.type = 'button';
  refreshButton.textContent = '↻';
  refreshButton.title = 'Обновить';

  const refreshBalance = async ({ showError = true, addressOverride = '' } = {}) => {
    const address = String(addressOverride || walletValue.value || '').trim();
    if (!address) return null;
    refreshButton.disabled = true;
    try {
      const balance = await getBalanceSol({
        endpoint: state.entrySettings.solanaServer,
        address,
      });
      state.registrationPayment.balanceSOL = String(balance.sol);
      balanceValue.textContent = `${formatSol(balance.sol, 6)} SOL`;
      return Number(balance.sol) || 0;
    } catch (error) {
      if (showError) {
        status.className = 'status-line is-unavailable';
        status.textContent = `Не удалось обновить баланс: ${error?.message || 'unknown'}`;
        status.style.display = '';
      }
      return null;
    } finally {
      refreshButton.disabled = false;
    }
  };

  const deriveUserWalletAddress = async () => {
    const keyBundle = state.registrationDraft.preGeneratedKeyBundle;
    if (!keyBundle) throw new Error('Ключи ещё не сгенерированы. Вернитесь на предыдущий шаг.');
    const { publicKeyB64 } = keyBundle.devicePair;
    const raw = atob(publicKeyB64);
    const bytes = new Uint8Array(raw.length);
    for (let i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i);
    const { PublicKey } = await import('https://esm.sh/@solana/web3.js@1.98.4');
    const address = new PublicKey(bytes).toBase58();
    state.registrationPayment.walletAddress = address;
    walletValue.value = address;
    return address;
  };

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

  balanceRow.append(balanceValue, refreshButton);

  const topupButton = document.createElement('button');
  topupButton.className = 'ghost-btn';
  topupButton.type = 'button';
  topupButton.textContent = 'Пополнить кошелёк';
  topupButton.addEventListener('click', async () => {
    try {
      const walletAddress = await deriveUserWalletAddress();
      window.open(getTopupSiteUrl(walletAddress), '_blank', 'noopener,noreferrer');
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Не удалось подготовить кошелёк: ${error?.message || 'unknown'}`;
      status.style.display = '';
    }
  });

  const showKeysButton = document.createElement('button');
  showKeysButton.className = 'ghost-btn';
  showKeysButton.type = 'button';
  showKeysButton.textContent = 'Показать сгенерированные ключи';
  showKeysButton.addEventListener('click', () => navigate('registration-draft-keys-view'));

  const submitButton = document.createElement('button');
  submitButton.className = 'primary-btn';
  submitButton.type = 'button';
  submitButton.textContent = 'Зарегистрироваться';
  submitButton.addEventListener('click', async () => {
    status.style.display = 'none';

    const cryptoState = getCryptoRuntimeState();
    if (!cryptoState.hasCrypto || !cryptoState.hasGetRandomValues || !cryptoState.hasSubtle) {
      status.className = 'status-line is-unavailable';
      status.textContent = 'Криптография браузера недоступна. Откройте приложение через HTTPS tunnel или localhost и повторите регистрацию.';
      status.style.display = '';
      return;
    }

    try {
      submitButton.disabled = true;
      submitButton.textContent = 'Регистрация...';

      const walletAddress = await deriveUserWalletAddress();
      const currentBalance = await refreshBalance({ showError: true, addressOverride: walletAddress });
      if (currentBalance == null) return;
      if (currentBalance < MIN_REQUIRED_SOL) {
        status.className = 'status-line is-unavailable';
        status.textContent = `Для регистрации нужно минимум ${MIN_REQUIRED_SOL} SOL. Сейчас на кошельке ${formatSol(currentBalance, 6)} SOL. Пополните на промо-странице или попросите перевод у знакомого с тестовыми SOL.`;
        status.style.display = '';
        const openTopup = window.confirm('Открыть страницу пополнения с вашим кошельком?');
        if (openTopup) {
          window.open(getTopupSiteUrl(walletAddress), '_blank', 'noopener,noreferrer');
        }
        return;
      }

      const keyBundle = state.registrationDraft.preGeneratedKeyBundle;
      if (!keyBundle) throw new Error('Ключи не найдены. Вернитесь на предыдущий шаг.');

      // Регистрация на Solana (смарт контракт)
      submitButton.textContent = 'Регистрация в Solana...';
      try {
        await registerUserOnSolana({
          login: state.registrationDraft.login,
          keyBundle,
          solanaEndpoint: state.entrySettings.solanaServer,
        });
      } catch (solanaError) {
        const solanaMsg = formatSolanaErrorDetails(solanaError);
        // Пользователь уже зарегистрирован в Solana — продолжаем
        if (!solanaMsg.includes('already') && !isUserAlreadyExistsSolanaError(solanaError)) {
          throw new Error(`Ошибка регистрации в Solana: ${solanaMsg}`);
        }
      }

      renderSolanaDoneStage({ navigate, status, keyBundle });
    } catch (error) {
      const message = toUserMessage(error, 'Не удалось завершить регистрацию.');
      setAuthError(message);
      status.className = 'status-line is-unavailable';
      status.textContent = message;
      status.style.display = '';
    } finally {
      submitButton.disabled = false;
      submitButton.textContent = 'Зарегистрироваться';
    }
  });

  card.innerHTML = `
    <p class="auth-copy">Для регистрации в тестовой Solana нужно минимум 0,01 SOL на вашем кошельке.</p>
    <label class="stack"><span class="field-label">Номер кошелька (wallet.key = device.key)</span></label>
    <div class="stack">
      <span class="field-label">Баланс (Solana)</span>
    </div>
  `;
  card.children[1].append(walletRow);
  card.children[2].append(balanceRow);
  card.append(topupButton, showKeysButton, submitButton, status);

  screen.append(
    renderHeader({
      title: 'Оплата регистрации',
      leftAction: { label: '←', onClick: () => navigate('register-view') },
    }),
    card,
  );

  (async () => {
    try {
      const walletAddress = await deriveUserWalletAddress();
      await refreshBalance({ addressOverride: walletAddress });
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = `Не удалось подготовить wallet.key: ${error?.message || 'unknown'}`;
      status.style.display = '';
    }
  })();

  return screen;
}

function renderSolanaDoneStage({ navigate, status, keyBundle }) {
  const screen = document.querySelector('section.stack');
  if (!screen) return;
  const card = screen.querySelector('.card.stack');
  if (!card) return;

  let remainingSec = SOLANA_SYNC_WAIT_SEC;
  let canTryLogin = false;
  let timerId = null;

  const info = document.createElement('p');
  info.className = 'auth-copy';
  info.textContent = 'Регистрация в Solana прошла успешно.';

  const hint = document.createElement('p');
  hint.className = 'meta-muted';
  hint.textContent = 'Подождите 10–15 секунд, пока запись обновится в блокчейне. После этого можно входить на сервер.';

  const timer = document.createElement('p');
  timer.className = 'meta-muted';
  timer.textContent = `До попытки входа: ${remainingSec} сек`;

  const tryLoginBtn = document.createElement('button');
  tryLoginBtn.className = 'primary-btn';
  tryLoginBtn.type = 'button';
  tryLoginBtn.textContent = `Попробовать войти (${remainingSec})`;
  tryLoginBtn.disabled = true;

  const backBtn = document.createElement('button');
  backBtn.className = 'ghost-btn';
  backBtn.type = 'button';
  backBtn.textContent = 'Назад';
  backBtn.addEventListener('click', () => navigate('register-view'));

  const stopTimer = () => {
    if (timerId) {
      window.clearInterval(timerId);
      timerId = null;
    }
  };

  const updateTimerUi = () => {
    if (remainingSec > 0) {
      timer.textContent = `До попытки входа: ${remainingSec} сек`;
      tryLoginBtn.textContent = `Попробовать войти (${remainingSec})`;
      tryLoginBtn.disabled = true;
    } else {
      canTryLogin = true;
      timer.textContent = 'Можно входить на сервер.';
      tryLoginBtn.textContent = 'Попробовать войти на сервер';
      tryLoginBtn.disabled = false;
      stopTimer();
    }
  };

  tryLoginBtn.addEventListener('click', async () => {
    if (!canTryLogin) return;
    status.style.display = 'none';
    tryLoginBtn.disabled = true;
    tryLoginBtn.textContent = 'Вход...';
    try {
      await authService.reconnect(state.entrySettings.shineServer);
      const result = await authService.createSessionForExistingUser(
        state.registrationDraft.login,
        state.registrationDraft.password,
      );
      state.registrationDraft.flowType = 'registration';
      state.registrationDraft.sessionId = result.sessionId;
      state.registrationDraft.storagePwd = result.storagePwd;
      state.registrationDraft.pendingKeyBundle = keyBundle;
      state.registrationDraft.pendingSessionMaterial = result.sessionMaterial;
      setAuthInfo(`Регистрация завершена. Вы вошли как @${result.login}. Далее откройте вкладку «Каналы».`);
      navigate('registration-keys-view');
    } catch (error) {
      status.className = 'status-line is-unavailable';
      status.textContent = toUserMessage(error, 'Пока не удалось войти. Попробуйте ещё раз через несколько секунд.');
      status.style.display = '';
      tryLoginBtn.disabled = false;
      tryLoginBtn.textContent = 'Попробовать войти на сервер';
    }
  });

  card.innerHTML = '';
  card.append(info, hint, timer, tryLoginBtn, backBtn, status);
  updateTimerUi();
  timerId = window.setInterval(() => {
    remainingSec -= 1;
    updateTimerUi();
  }, 1000);
}
