import { renderHeader } from '../components/header.js';
import {
  authService,
  authorizeSession,
  clearAuthMessages,
  clearBrowserClientData,
  refreshSessions,
  setAuthBusy,
  setAuthError,
  setAuthInfo,
  state,
  terminateCurrentSession,
} from '../state.js';
import { showToast } from '../services/channels-ux.js';
import {
  decryptPairingPayloadFromEnvelope,
  deriveEspPairingPasswordHash,
  createRequesterPairingMaterial,
  formatPairingShortCode,
} from '../services/device-pairing-service.js';
import { clearClientAuthData, saveEncryptedUserSecrets } from '../services/key-vault.js';
import { clearStoredMessages } from '../services/message-store.js';
import { toUserMessage } from '../services/ui-error-texts.js';

export const pageMeta = { id: 'login-other-device-view', title: 'Войти через другое устройство', showAppChrome: false };

function setStatus(statusEl, message, kind = 'info') {
  statusEl.classList.toggle('is-unavailable', kind === 'error');
  statusEl.classList.toggle('is-available', kind !== 'error');
  statusEl.textContent = message;
  statusEl.style.display = message ? '' : 'none';
}

function codeCardHtml() {
  return `
    <div class="card stack">
      <p class="field-label">Код подключения</p>
      <div id="pairing-short-code" style="font-size:34px; font-weight:700; letter-spacing:0.12em;">00 00 00 00 00</div>
      <p class="meta-muted" id="pairing-status-hint">Покажите этот код на уже подключённом устройстве в разделе «Подключить по коду».</p>
      <p class="meta-muted" id="pairing-online-hint"></p>
      <p class="meta-muted" id="pairing-expire-hint"></p>
    </div>
  `;
}

function formatRemaining(ms) {
  const safe = Math.max(0, Math.floor(Number(ms || 0) / 1000));
  const minutes = Math.floor(safe / 60);
  const seconds = safe % 60;
  return `${minutes} мин ${seconds} сек`;
}

function resetCodeCard(resultWrap, shortCodeEl, statusHintEl, onlineHintEl, expireHintEl) {
  resultWrap.style.display = 'none';
  shortCodeEl.textContent = formatPairingShortCode('');
  statusHintEl.textContent = 'Покажите этот код на уже подключённом устройстве в разделе «Подключить по коду».';
  onlineHintEl.textContent = '';
  expireHintEl.textContent = '';
}

export function render({ navigate }) {
  const screen = document.createElement('section');
  screen.className = 'stack auth-screen auth-screen--lower';
  let pollTimer = 0;
  let countdownTimer = 0;
  let activePairingId = '';
  let requesterMaterial = null;
  let activeExpiresAtMs = 0;
  let isDisposed = false;

  clearAuthMessages();

  screen.append(
    renderHeader({
      title: 'Войти через другое устройство',
      leftAction: { label: '←', onClick: () => navigate('login-view') },
    }),
  );

  const panel = document.createElement('section');
  panel.className = 'login-panel login-panel--wide stack';
  panel.innerHTML = '<h1 class="login-panel-title">Войти через другое устройство</h1>';

  const formCard = document.createElement('div');
  formCard.className = 'card stack';
  formCard.innerHTML = `
    <label class="stack">
      <span class="field-label">Введите логин</span>
      <input class="input" id="pair-login" type="text" autocomplete="username" placeholder="" value="" />
    </label>
    <label class="checkbox-row">
      <input type="checkbox" id="pair-use-password" />
      использовать доп. пароль
    </label>
    <label class="stack">
      <span class="field-label">Пароль подключения</span>
      <input class="input" id="pair-password" type="password" autocomplete="current-password" placeholder="Пароль, заданный на другом устройстве" />
    </label>
    <button class="primary-btn" type="button" id="pair-start-btn">Получить код</button>
    <p class="meta-muted" id="pair-mode-hint">Получить код для входа можно только если сейчас есть хотя бы одно другое активное устройство этого пользователя в сети.</p>
  `;

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

  const resultWrap = document.createElement('div');
  resultWrap.className = 'stack';
  resultWrap.style.display = 'none';
  resultWrap.innerHTML = codeCardHtml();

  const loginInput = formCard.querySelector('#pair-login');
  const usePasswordInput = formCard.querySelector('#pair-use-password');
  const passwordInput = formCard.querySelector('#pair-password');
  const startBtn = formCard.querySelector('#pair-start-btn');
  const modeHintEl = formCard.querySelector('#pair-mode-hint');
  const shortCodeEl = resultWrap.querySelector('#pairing-short-code');
  const statusHintEl = resultWrap.querySelector('#pairing-status-hint');
  const onlineHintEl = resultWrap.querySelector('#pairing-online-hint');
  const expireHintEl = resultWrap.querySelector('#pairing-expire-hint');
  const cancelBtn = document.createElement('button');
  cancelBtn.className = 'ghost-btn';
  cancelBtn.type = 'button';
  cancelBtn.textContent = 'Отмена';
  cancelBtn.style.display = 'none';

  const syncPasswordUi = () => {
    const usePassword = !!usePasswordInput.checked;
    passwordInput.parentElement.style.display = usePassword ? '' : 'none';
    modeHintEl.textContent = usePassword
      ? 'Получить код для входа можно только если сейчас есть хотя бы одно другое активное устройство этого пользователя в сети. Если на доверённом устройстве включён доп. пароль, введите его.'
      : 'Получить код для входа можно только если сейчас есть хотя бы одно другое активное устройство этого пользователя в сети.';
    if (!usePassword) {
      passwordInput.value = '';
    }
  };

  const stopPolling = () => {
    if (pollTimer) {
      window.clearTimeout(pollTimer);
      pollTimer = 0;
    }
  };

  const stopCountdown = () => {
    if (countdownTimer) {
      window.clearInterval(countdownTimer);
      countdownTimer = 0;
    }
  };

  const updateCountdown = () => {
    const leftMs = activeExpiresAtMs - Date.now();
    if (leftMs <= 0) {
      stopPolling();
      stopCountdown();
      activePairingId = '';
      activeExpiresAtMs = 0;
      startBtn.disabled = false;
      cancelBtn.style.display = 'none';
      resetCodeCard(resultWrap, shortCodeEl, statusHintEl, onlineHintEl, expireHintEl);
      setStatus(status, 'Время ожидания истекло. Получите новый код.', 'error');
      return;
    }
    expireHintEl.textContent = `Код действителен ещё ${formatRemaining(leftMs)}.`;
  };

  const startCountdown = (expiresAtMs) => {
    activeExpiresAtMs = Number(expiresAtMs || 0);
    stopCountdown();
    updateCountdown();
    countdownTimer = window.setInterval(updateCountdown, 1000);
  };

  const clearActivePairing = () => {
    stopPolling();
    stopCountdown();
    activePairingId = '';
    activeExpiresAtMs = 0;
    cancelBtn.style.display = 'none';
    resetCodeCard(resultWrap, shortCodeEl, statusHintEl, onlineHintEl, expireHintEl);
  };

  const finalizeAuthorizedLogin = async (keys, login) => {
    const session = await authService.createSessionFromImportedSecrets(login, keys);
    await terminateCurrentSession({ closeServerSession: true });
    await clearStoredMessages().catch(() => {});
    clearBrowserClientData();
    await clearClientAuthData().catch(() => {});
    await saveEncryptedUserSecrets(session.login, session.storagePwd, keys);
    await authService.persistSessionMaterial(session.login, session.sessionMaterial);
    const resumed = await authService.resumeSession(session.login, session.sessionId);
    authorizeSession({
      login: resumed.login || session.login,
      sessionId: resumed.sessionId || session.sessionId,
      storagePwd: resumed.storagePwd || session.storagePwd,
    });
    state.loginDraft.login = resumed.login || session.login;
    state.loginDraft.password = '';
    await refreshSessions();
    setAuthInfo(`Вход через другое устройство выполнен для @${resumed.login || session.login}.`);
    showToast(`Устройство подключено для @${resumed.login || session.login}`);
    navigate('profile-view');
  };

  const finalizeAuthorizedSessionAttach = async (payloadSession, login, requesterKeys) => {
    const sessionId = String(payloadSession?.sessionId || '').trim();
    const storagePwd = String(payloadSession?.storagePwd || '').trim();
    if (!sessionId || !storagePwd) {
      throw new Error('В session-only payload нет sessionId или storagePwd');
    }
    const sessionMaterial = {
      sessionId,
      sessionKey: requesterKeys.sessionKey,
      sessionPrivPkcs8: requesterKeys.sessionPrivPkcs8,
      sessionType: Number(payloadSession?.sessionType || 50) || 50,
    };

    await terminateCurrentSession({ closeServerSession: true });
    await clearStoredMessages().catch(() => {});
    clearBrowserClientData();
    await clearClientAuthData().catch(() => {});
    await authService.persistSessionMaterial(login, sessionMaterial);
    const resumed = await authService.resumeSession(login, sessionId);
    authorizeSession({
      login: resumed.login || login,
      sessionId: resumed.sessionId || sessionId,
      storagePwd: resumed.storagePwd || storagePwd,
    });
    state.loginDraft.login = resumed.login || login;
    state.loginDraft.password = '';
    await refreshSessions();
    setAuthInfo(`Session-only вход выполнен для @${resumed.login || login}.`);
    showToast(`Wallet-session подключена для @${resumed.login || login}`);
    navigate('profile-view');
  };

  const schedulePoll = () => {
    stopPolling();
    if (!activePairingId || isDisposed) return;
    pollTimer = window.setTimeout(async () => {
      try {
        const payload = await authService.getTrustedDeviceLoginStatus(activePairingId);
        const stateValue = String(payload?.state || '');
        if (stateValue === 'created') {
          schedulePoll();
          return;
        }
        if (stateValue === 'approved') {
          stopCountdown();
          setStatus(status, 'Заявка подтверждена. Подключаем устройство...', 'info');
          const decoded = await decryptPairingPayloadFromEnvelope(payload?.encryptedPayload, requesterMaterial);
          const decodedType = String(decoded?.type || '');
          if (decodedType === 'shine-esp-session-attach') {
            await finalizeAuthorizedSessionAttach(decoded.session, decoded.login || loginInput.value, requesterMaterial);
            return;
          }
          if (decodedType !== 'shine-esp-pairing-transfer') {
            throw new Error('Получен неподдерживаемый pairing payload');
          }
          await finalizeAuthorizedLogin(decoded.keys, decoded.login || loginInput.value);
          return;
        }
        if (stateValue === 'rejected') {
          clearActivePairing();
          startBtn.disabled = false;
          setStatus(status, 'Подключение отклонено на доверенном устройстве.', 'error');
          return;
        }
        if (stateValue === 'canceled') {
          clearActivePairing();
          startBtn.disabled = false;
          setStatus(status, 'Ожидание подключения отменено.', 'error');
          return;
        }
        if (stateValue === 'expired') {
          clearActivePairing();
          startBtn.disabled = false;
          setStatus(status, 'Время ожидания истекло. Получите новый код.', 'error');
          return;
        }
        schedulePoll();
      } catch (error) {
        stopPolling();
        startBtn.disabled = false;
        const message = toUserMessage(error, 'Не удалось проверить статус pairing.');
        setAuthError(message);
        setStatus(status, message, 'error');
      }
    }, 2200);
  };

  usePasswordInput.addEventListener('change', syncPasswordUi);
  syncPasswordUi();

  startBtn.addEventListener('click', async () => {
    const login = String(loginInput.value || '').trim();
    const usePassword = !!usePasswordInput.checked;
    const password = String(passwordInput.value || '');
    if (!login) {
      setStatus(status, 'Введите логин.', 'error');
      return;
    }
    if (usePassword && !password) {
      setStatus(status, 'Введите пароль подключения.', 'error');
      return;
    }

    startBtn.disabled = true;
    setAuthBusy(true);
    setAuthError('');
    setAuthInfo('');
    setStatus(status, 'Проверяем пользователя и создаём pairing-заявку...', 'info');
    clearActivePairing();

    try {
      await authService.reconnect(state.entrySettings.shineServer);
      const user = await authService.getUser(login);
      if (!user?.exists) {
        throw new Error('Пользователь не найден.');
      }

      requesterMaterial = await createRequesterPairingMaterial();
      const passwordHash = usePassword
        ? await deriveEspPairingPasswordHash(login, password)
        : '';
      const payload = await authService.startTrustedDeviceLogin({
        login,
        passwordHash,
        requesterSessionKey: requesterMaterial.sessionKey,
        payloadType: 3,
      });

      activePairingId = String(payload?.pairingId || '');
      if (!activePairingId) {
        throw new Error('Сервер не вернул pairingId.');
      }

      shortCodeEl.textContent = formatPairingShortCode(payload?.shortCode || '');
      statusHintEl.textContent = 'Откройте на доверенном устройстве: Настройки -> Устройства -> Подключить устройство -> Подключить по коду.';
      onlineHintEl.textContent = payload?.trustedSessionOnline
        ? 'Сейчас есть хотя бы одна онлайн доверенная сессия, которая может принять заявку.'
        : 'Сейчас нет онлайн доверенной сессии. Заявка будет ждать, пока пользователь откроет уже подключённое устройство.';
      resultWrap.style.display = '';
      cancelBtn.style.display = '';
      startCountdown(payload?.expiresAtMs);
      state.loginDraft.login = login;
      setStatus(status, 'Код создан. Ожидаем подтверждение на другом устройстве...', 'info');
      schedulePoll();
    } catch (error) {
      startBtn.disabled = false;
      const message = toUserMessage(error, 'Не удалось начать вход через другое устройство.');
      setAuthError(message);
      setStatus(status, message, 'error');
    } finally {
      setAuthBusy(false);
    }
  });

  cancelBtn.addEventListener('click', async () => {
    if (!activePairingId || !requesterMaterial?.sessionKey) {
      clearActivePairing();
      startBtn.disabled = false;
      cancelBtn.style.display = 'none';
      return;
    }
    cancelBtn.disabled = true;
    try {
      await authService.cancelTrustedDeviceLogin(activePairingId, requesterMaterial.sessionKey);
      clearActivePairing();
      startBtn.disabled = false;
      setStatus(status, 'Ожидание подключения отменено.', 'info');
    } catch (error) {
      const message = toUserMessage(error, 'Не удалось отменить ожидание подключения.');
      setAuthError(message);
      setStatus(status, message, 'error');
    } finally {
      cancelBtn.disabled = false;
      cancelBtn.style.display = activePairingId ? '' : 'none';
    }
  });

  screen.cleanup = () => {
    isDisposed = true;
    stopPolling();
    stopCountdown();
  };

  const resultActions = document.createElement('div');
  resultActions.className = 'row';
  resultActions.append(cancelBtn);
  resultWrap.append(resultActions);

  panel.append(formCard, status, resultWrap);
  screen.append(panel);
  return screen;
}
