import { renderHeader } from '../components/header.js';
import { authService, clearAuthMessages, state } from '../state.js';
import { toUserMessage } from '../services/ui-error-texts.js';
import {
  checkLoginExistsOnSolana,
  formatSolanaErrorDetails,
  precheckLoginClassOnSolana,
} from '../services/solana-register-service.js';
import {
  composePasswordFromWords,
  emptyPasswordWords,
  normalizePasswordWords,
  PASSWORD_MAX_LENGTH,
  PASSWORD_WORDS_COUNT,
} from '../services/password-words.js';
import { openRegistrationFaq } from './registration-faq-view.js';

export const pageMeta = { id: 'register-view', title: 'Зарегистрироваться', showAppChrome: false };

function createWordsLayout({ words, onInput }) {
  const section = document.createElement('div');
  section.className = 'registration-words-block';

  const grid = document.createElement('div');
  grid.className = 'registration-words-grid';

  const inputs = Array.from({ length: PASSWORD_WORDS_COUNT }, (_, index) => {
    const row = document.createElement('label');
    row.className = 'registration-word-row';

    const number = document.createElement('span');
    number.className = 'registration-word-number';
    number.textContent = `${index + 1}.`;

    const input = document.createElement('input');
    input.className = 'input registration-word-input';
    input.type = 'text';
    input.autocomplete = 'off';
    input.autocapitalize = 'off';
    input.spellcheck = false;
    input.maxLength = 32;
    input.value = words[index];
    input.addEventListener('input', () => onInput(index, input.value));

    row.append(number, input);
    grid.append(row);
    return input;
  });

  const hint = document.createElement('p');
  hint.className = 'meta-muted';
  hint.textContent =
    'Здесь можно ввести любые слова на любых языках. Мы не проверяем орфографию. Можно заполнить все 12 полей или только часть. В конце всё склеивается в один пароль длиной до 256 символов.';

  section.append(grid, hint);
  return { section, inputs };
}

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

  clearAuthMessages();

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

  let passwordMode = String(state.registrationDraft.passwordMode || 'single') === 'words' ? 'words' : 'single';
  let passwordWords = normalizePasswordWords(state.registrationDraft.passwordWords);

  const loginInput = document.createElement('input');
  loginInput.className = 'input';
  loginInput.type = 'text';
  loginInput.autocomplete = 'off';
  loginInput.autocapitalize = 'off';
  loginInput.spellcheck = false;
  loginInput.value = state.registrationDraft.login;
  loginInput.placeholder = 'Введите логин';

  const passwordInput = document.createElement('input');
  passwordInput.className = 'input';
  passwordInput.type = 'password';
  passwordInput.name = 'shine-register-password';
  passwordInput.autocomplete = 'new-password';
  passwordInput.autocapitalize = 'off';
  passwordInput.spellcheck = false;
  passwordInput.maxLength = PASSWORD_MAX_LENGTH;
  passwordInput.value = passwordMode === 'single' ? state.registrationDraft.password : '';
  passwordInput.placeholder = 'Введите пароль';

  const {
    section: wordsSection,
    inputs: wordInputs,
  } = createWordsLayout({
    words: passwordWords,
    onInput: (index, value) => {
      passwordWords[index] = value;
      syncDraftState();
      updateWordsPreview();
    },
  });

  const passwordModeToggle = document.createElement('label');
  passwordModeToggle.className = 'registration-toggle';

  const passwordModeCheckbox = document.createElement('input');
  passwordModeCheckbox.type = 'checkbox';
  passwordModeCheckbox.checked = passwordMode === 'words';

  const passwordModeLabel = document.createElement('span');
  passwordModeLabel.textContent = 'Представить пароль в виде 12 слов';

  passwordModeToggle.append(passwordModeCheckbox, passwordModeLabel);

  const statusText = document.createElement('p');
  statusText.className = 'status-line registration-login-status';
  statusText.style.display = 'none';

  const faqButton = document.createElement('button');
  faqButton.className = 'registration-faq-link';
  faqButton.type = 'button';
  faqButton.textContent = 'Вопросы о регистрации';
  faqButton.addEventListener('click', () => openRegistrationFaq(navigate, 'key-derivation'));

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

  const actions = document.createElement('div');
  actions.className = 'auth-footer-actions';

  const nextButton = document.createElement('button');
  nextButton.className = 'primary-btn';
  nextButton.type = 'button';
  nextButton.textContent = 'Далее';

  let passwordField = null;
  const passwordLengthText = document.createElement('p');
  passwordLengthText.className = 'password-length-hint';
  let lastCheckedLogin = '';
  let lastCheckedFree = false;
  let lastCheckedClassName = '';
  let loginCheckTimer = null;
  let loginCheckRunId = 0;
  let generationRunId = 0;

  function getCurrentPassword() {
    return passwordMode === 'words' ? composePasswordFromWords(passwordWords) : String(passwordInput.value || '');
  }

  function updateWordsPreview() {
    const password = getCurrentPassword();
    const text = `Итоговая длина пароля: ${password.length} символов.`;
    passwordLengthText.textContent = text;
  }

  function updatePasswordModeVisibility() {
    const wordsMode = passwordMode === 'words';
    wordsSection.style.display = wordsMode ? 'grid' : 'none';
    if (passwordField) passwordField.style.display = wordsMode ? 'none' : 'grid';
    passwordInput.style.display = wordsMode ? 'none' : '';
    updateWordsPreview();
  }

  function syncDraftState() {
    state.registrationDraft.login = String(loginInput.value.trim());
    state.registrationDraft.passwordMode = passwordMode;
    state.registrationDraft.passwordWords = normalizePasswordWords(passwordWords);
    state.registrationDraft.password = getCurrentPassword();
  }

  async function runAvailabilityCheck() {
    const login = loginInput.value.trim();
    if (!login) {
      statusText.textContent = '';
      statusText.style.display = 'none';
      formError.style.display = 'none';
      return false;
    }

    if (login === lastCheckedLogin) {
      if (!lastCheckedFree) {
        statusText.textContent = 'Логин уже занят ❌';
        statusText.className = 'status-line is-unavailable';
      } else if (lastCheckedClassName === 'free') {
        statusText.textContent = 'Логин свободен ✅';
        statusText.className = 'status-line is-available';
      } else if (lastCheckedClassName === 'premium') {
        statusText.textContent = 'Логин свободен, но это премиум-логин (покупка через DAO) ❌';
        statusText.className = 'status-line is-unavailable';
      } else if (lastCheckedClassName === 'company') {
        statusText.textContent = 'Логин свободен, но относится к компании/бренду (отдельное согласование) ❌';
        statusText.className = 'status-line is-unavailable';
      } else {
        statusText.textContent = 'Логин нельзя использовать для обычной регистрации ❌';
        statusText.className = 'status-line is-unavailable';
      }
      statusText.style.display = '';
      formError.style.display = 'none';
      return lastCheckedFree && lastCheckedClassName === 'free';
    }

    const runId = ++loginCheckRunId;
    statusText.className = 'status-line registration-login-status';
    statusText.textContent = 'Проверяем логин...';
    statusText.style.display = '';
    try {
      const check = await checkLoginExistsOnSolana({
        login,
        solanaEndpoint: state.entrySettings.solanaServer,
      });
      const isFree = !check.exists;
      let className = '';
      let precheckWarning = '';
      if (isFree) {
        try {
          const precheck = await precheckLoginClassOnSolana({
            login,
            solanaEndpoint: state.entrySettings.solanaServer,
          });
          className = precheck.className;
        } catch (precheckError) {
          className = 'free';
          precheckWarning = formatSolanaErrorDetails(precheckError);
        }
      }
      if (runId !== loginCheckRunId) return false;
      lastCheckedLogin = login;
      lastCheckedFree = isFree;
      lastCheckedClassName = className;
      if (!isFree) {
        statusText.textContent = 'Логин уже занят ❌';
        statusText.className = 'status-line is-unavailable';
      } else if (className === 'free') {
        statusText.textContent = precheckWarning
          ? `Логин свободен ✅ (предпроверка Solana недоступна: ${precheckWarning})`
          : 'Логин свободен ✅';
        statusText.className = 'status-line is-available';
      } else if (className === 'premium') {
        statusText.textContent = 'Логин свободен, но это премиум-логин (покупка через DAO) ❌';
        statusText.className = 'status-line is-unavailable';
      } else if (className === 'company') {
        statusText.textContent = 'Логин свободен, но относится к компании/бренду (отдельное согласование) ❌';
        statusText.className = 'status-line is-unavailable';
      } else {
        statusText.textContent = 'Логин нельзя использовать для обычной регистрации ❌';
        statusText.className = 'status-line is-unavailable';
      }
      statusText.style.display = '';
      formError.style.display = 'none';
      return isFree && className === 'free';
    } catch (error) {
      if (runId !== loginCheckRunId) return false;
      const base = toUserMessage(error, 'Не удалось проверить логин');
      const details = formatSolanaErrorDetails(error);
      statusText.textContent = `${base}. Детали: ${details}`;
      statusText.className = 'status-line is-unavailable';
      statusText.style.display = '';
      return false;
    }
  }

  loginInput.addEventListener('input', () => {
    syncDraftState();
    lastCheckedLogin = '';
    loginCheckRunId += 1;
    if (loginCheckTimer) window.clearTimeout(loginCheckTimer);
    statusText.textContent = '';
    statusText.style.display = 'none';
    if (!loginInput.value.trim()) return;
    loginCheckTimer = window.setTimeout(() => {
      runAvailabilityCheck();
    }, 450);
  });

  passwordInput.addEventListener('input', () => {
    syncDraftState();
    updateWordsPreview();
  });

  passwordModeCheckbox.addEventListener('change', () => {
    const nextMode = passwordModeCheckbox.checked ? 'words' : 'single';
    if (nextMode === passwordMode) return;
    if (nextMode === 'words') {
      passwordWords = emptyPasswordWords();
      wordInputs.forEach((input) => {
        input.value = '';
      });
      passwordInput.value = '';
    } else {
      passwordInput.value = composePasswordFromWords(passwordWords);
    }
    passwordMode = nextMode;
    updatePasswordModeVisibility();
    updateWordsPreview();
    syncDraftState();
  });

  nextButton.addEventListener('click', async () => {
    formError.style.display = 'none';
    const isFree = await runAvailabilityCheck();
    if (!isFree) return;

    const prevLogin = String(state.registrationDraft.login || '');
    const prevPassword = String(state.registrationDraft.password || '');
    const nextLogin = String(loginInput.value.trim());
    const nextPassword = getCurrentPassword();
    if (nextPassword.length === 0) {
      formError.textContent = 'Пустой пароль запрещён. Введите непустой пароль для регистрации.';
      formError.style.display = '';
      return;
    }
    if (nextPassword.length > PASSWORD_MAX_LENGTH) {
      formError.textContent = `Пароль получился слишком длинным. Максимальная длина: ${PASSWORD_MAX_LENGTH} символов.`;
      formError.style.display = '';
      return;
    }
    const credsChanged = prevLogin !== nextLogin || prevPassword !== nextPassword;

    state.registrationDraft.login = nextLogin;
    state.registrationDraft.password = nextPassword;
    state.registrationDraft.passwordMode = passwordMode;
    state.registrationDraft.passwordWords = normalizePasswordWords(passwordWords);
    if (credsChanged) {
      state.registrationDraft.preGeneratedKeyBundle = null;
    }

    startGenerationStage();
  });

  function renderInputStage() {
    form.innerHTML = `
      <label class="stack"><span class="field-label">Логин</span></label>
      <label class="stack registration-password-single"><span class="field-label">Пароль</span></label>
    `;
    const loginField = form.children[0];
    passwordField = form.children[1];
    loginField.append(loginInput);
    passwordField.append(passwordInput, passwordLengthText);
    form.append(passwordModeToggle, wordsSection, statusText, formError);
    actions.innerHTML = '';
    actions.append(nextButton);
    updatePasswordModeVisibility();
    syncDraftState();
  }

  async function startGenerationStage() {
    const runId = ++generationRunId;
    form.innerHTML = '';

    const title = document.createElement('p');
    title.className = 'auth-copy';
    title.textContent = 'Для повышения безопасности мы генерируем секрет из вашего логина и пароля с помощью Argon2id.';

    const subtitle = document.createElement('p');
    subtitle.className = 'meta-muted';
    subtitle.textContent = 'Процесс запускается сразу: из этого секрета будут вычислены recovery key, root key, blockchain key и client key.';

    const details = document.createElement('p');
    details.className = 'meta-muted';
    details.textContent = 'Параметры: t=2, m=65536 KiB (64 MB), p=1, dkLen=32.';

    const details2 = document.createElement('p');
    details2.className = 'meta-muted';
    details2.textContent = 'Замедление нужно специально: оно усложняет подбор пароля и повышает цену атак на видеокартах и GPU.';

    const details3 = document.createElement('p');
    details3.className = 'meta-muted';
    details3.textContent = `Длина вашего текущего пароля: ${getCurrentPassword().length} символов.`;

    const progressWrap = document.createElement('div');
    progressWrap.className = 'registration-progress';

    const progressBar = document.createElement('div');
    progressBar.className = 'registration-progress-bar';
    progressWrap.append(progressBar);

    const progressText = document.createElement('p');
    progressText.className = 'meta-muted';
    progressText.textContent = 'Подготовка...';

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

    form.append(title, subtitle, details, details2, details3, progressWrap, progressText, genError);

    const cancelBtn = document.createElement('button');
    cancelBtn.className = 'ghost-btn';
    cancelBtn.type = 'button';
    cancelBtn.textContent = 'Отмена';
    cancelBtn.addEventListener('click', () => {
      generationRunId += 1;
      renderInputStage();
    });
    actions.innerHTML = '';
    actions.append(cancelBtn);

    try {
      if (!state.registrationDraft.preGeneratedKeyBundle) {
        const keyBundle = await authService.derivePasswordKeyBundle(
          state.registrationDraft.login,
          state.registrationDraft.password,
          {
            onProgress: ({ percent, message }) => {
              if (runId !== generationRunId) return;
              const safePercent = Math.max(0, Math.min(100, Number(percent) || 0));
              progressBar.style.width = `${safePercent}%`;
              progressText.textContent = `${safePercent}% · ${String(message || '').trim()}`;
            },
            isCancelled: () => runId !== generationRunId,
          },
        );
        if (runId !== generationRunId) return;
        state.registrationDraft.preGeneratedKeyBundle = keyBundle;
      }
      if (runId !== generationRunId) return;
      progressBar.style.width = '100%';
      progressText.textContent = '100%';
      title.textContent = 'Ключи сгенерированы';
      window.setTimeout(() => navigate('registration-payment-view'), 350);
    } catch (error) {
      if (runId !== generationRunId) return;
      if (String(error?.message || '') === 'DERIVE_CANCELLED') {
        renderInputStage();
        return;
      }
      genError.textContent = `Ошибка генерации ключей: ${error?.message || 'неизвестная ошибка'}`;
      genError.style.display = '';
      const retry = document.createElement('button');
      retry.className = 'primary-btn';
      retry.type = 'button';
      retry.textContent = 'Повторить';
      retry.addEventListener('click', startGenerationStage);
      const goBack = document.createElement('button');
      goBack.className = 'ghost-btn';
      goBack.type = 'button';
      goBack.textContent = 'Назад';
      goBack.addEventListener('click', renderInputStage);
      actions.innerHTML = '';
      actions.append(goBack, retry);
    }
  }

  renderInputStage();

  screen.append(
    renderHeader({
      title: 'Зарегистрироваться',
      leftAction: { label: '←', onClick: () => navigate('start-view') },
    }),
    form,
    faqButton,
    actions,
  );

  return screen;
}
