import { formatPairingShortCode } from './js/lib/device-pairing.js';

const els = {
  serverLoginInfo: document.querySelector('#server-login-info'),
  loginInput: document.querySelector('#login-input'),
  usePassword: document.querySelector('#use-password'),
  passwordField: document.querySelector('#password-field'),
  passwordInput: document.querySelector('#password-input'),
  startBtn: document.querySelector('#start-btn'),
  connectCard: document.querySelector('#connect-card'),
  pairingCard: document.querySelector('#pairing-card'),
  shortCode: document.querySelector('#short-code'),
  pairingHint: document.querySelector('#pairing-hint'),
  pairingExpire: document.querySelector('#pairing-expire'),
  cancelBtn: document.querySelector('#cancel-btn'),
  status: document.querySelector('#status'),
  sessionCard: document.querySelector('#session-card'),
  sessionLogin: document.querySelector('#session-login'),
  resumeBtn: document.querySelector('#resume-btn'),
  refreshDevicesBtn: document.querySelector('#refresh-devices-btn'),
  disconnectBtn: document.querySelector('#disconnect-btn'),
  walletCard: document.querySelector('#wallet-card'),
  deviceSelect: document.querySelector('#device-select'),
  homeserverList: document.querySelector('#homeserver-list'),
  requestWalletBtn: document.querySelector('#request-wallet-btn'),
  pendingApprovalCard: document.querySelector('#pending-approval-card'),
  pendingApprovalSubtitle: document.querySelector('#pending-approval-subtitle'),
  pendingApprovalDetails: document.querySelector('#pending-approval-details'),
  cancelPendingApprovalBtn: document.querySelector('#cancel-pending-approval-btn'),
  walletResultCard: document.querySelector('#wallet-result-card'),
  walletType: document.querySelector('#wallet-type'),
  walletPubkey: document.querySelector('#wallet-pubkey'),
  walletVerify: document.querySelector('#wallet-verify'),
  copyWalletBtn: document.querySelector('#copy-wallet-btn'),
  connectionPill: document.querySelector('#connection-pill'),
};

let state = {
  settings: {
    serverLogin: 'shineupme',
    serverHttp: 'https://shineup.me',
    login: '',
  },
  pairing: {
    active: false,
    expiresAtMs: 0,
    shortCode: '',
  },
  session: null,
  walletProfile: null,
  signing: {
    selectedDeviceName: '',
  },
  currentWallet: null,
  pendingApproval: null,
  status: {
    text: '',
    kind: 'info',
  },
};

let refreshTimer = 0;
let saveSettingsTimer = 0;

function setStatus(message, kind = 'info') {
  els.status.textContent = String(message || '');
  els.status.className = `status ${kind === 'error' ? 'error' : 'info'}`;
  els.status.classList.toggle('hidden', !message);
}

function setConnectedPill(connected) {
  els.connectionPill.textContent = connected ? 'подключено' : 'не подключено';
  els.connectionPill.className = connected ? 'pill pill-online' : 'pill pill-offline';
}

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 shortKey(value, size = 10) {
  const raw = String(value || '').trim();
  return raw ? `${raw.slice(0, size)}...` : '—';
}

function renderHomeserverList(items = []) {
  els.homeserverList.innerHTML = '';
  if (!items.length) {
    const empty = document.createElement('p');
    empty.className = 'muted small';
    empty.textContent = 'В PDA пока нет опубликованных homeserver-сессий.';
    els.homeserverList.append(empty);
    return;
  }
  items.forEach((item) => {
    const row = document.createElement('div');
    row.className = 'summary-row device-row';
    const label = document.createElement('span');
    label.textContent = `${item.sessionName} (${shortKey(item.sessionPubKeyBase58, 8)})`;
    const badge = document.createElement('strong');
    const stateValue = String(item.onlineState || 'unknown');
    badge.textContent = stateValue;
    badge.className = `device-state device-state-${stateValue}`;
    row.append(label, badge);
    els.homeserverList.append(row);
  });
}

function renderPendingApproval(pendingApproval) {
  els.pendingApprovalDetails.innerHTML = '';
  if (!pendingApproval) return;
  const summary = pendingApproval.transactionSummary || {};
  const programs = Array.isArray(summary.programs) && summary.programs.length
    ? summary.programs.join(', ')
    : 'не определены';
  const details = [
    { label: 'Сайт', value: pendingApproval.origin || '—', mono: true },
    { label: 'Кошелёк', value: pendingApproval.publicKeyBase58 || '—', mono: true },
    { label: 'Очередь', value: `${pendingApproval.queuePosition || 1} из ${pendingApproval.queueLength || 1}` },
    { label: 'Комментарий', value: pendingApproval.comment || 'Транзакция запрошена сайтом' },
    { label: 'Тип', value: summary.kind || 'legacy' },
    { label: 'Инструкций', value: String(summary.instructionCount ?? 0) },
    { label: 'Программы', value: programs, mono: true },
  ];
  if (summary.feePayer) {
    details.push({ label: 'Fee payer', value: summary.feePayer, mono: true });
  }
  if (summary.recentBlockhash) {
    details.push({ label: 'Blockhash', value: summary.recentBlockhash, mono: true });
  }
  for (const item of details) {
    const row = document.createElement('div');
    row.className = 'detail-row';
    const label = document.createElement('div');
    label.className = 'detail-label';
    label.textContent = item.label;
    const value = document.createElement('div');
    value.className = `detail-value${item.mono ? ' mono' : ''}`;
    value.textContent = item.value;
    row.append(label, value);
    els.pendingApprovalDetails.append(row);
  }
}

function applyState(nextState) {
  state = nextState || state;
  const loginValue = String(state?.settings?.login || '');
  const resolvedServerLogin = String(state?.settings?.serverLogin || '').trim();
  const resolvedServerAddress = String(state?.settings?.serverHttp || '').trim();
  els.serverLoginInfo.textContent = resolvedServerLogin && resolvedServerAddress
    ? `Сервер SHiNE: ${resolvedServerLogin} (${resolvedServerAddress})`
    : 'Сервер SHiNE: —';
  if (document.activeElement !== els.loginInput) {
    els.loginInput.value = loginValue;
  }

  setConnectedPill(!!state?.session);
  setStatus(state?.status?.text || '', state?.status?.kind || 'info');

  const session = state?.session;
  const walletProfile = state?.walletProfile;
  const signing = state?.signing || {};
  const currentWallet = state?.currentWallet || null;
  const pendingApproval = state?.pendingApproval || null;

  els.connectCard.classList.toggle('hidden', !!session);
  els.sessionCard.classList.toggle('hidden', !session);
  els.walletCard.classList.toggle('hidden', !session);
  els.pendingApprovalCard.classList.toggle('hidden', !pendingApproval);

  if (session) {
    els.sessionLogin.textContent = session.login || '—';
  }

  const homeservers = Array.isArray(walletProfile?.homeserverSessions) ? walletProfile.homeserverSessions : [];
  els.deviceSelect.innerHTML = '';
  homeservers.forEach((item) => {
    const option = document.createElement('option');
    option.value = item.sessionName;
    option.textContent = `${item.sessionName} [${item.onlineState || 'offline'}]`;
    option.selected = item.sessionName === signing.selectedDeviceName;
    els.deviceSelect.append(option);
  });
  renderHomeserverList(homeservers);
  els.requestWalletBtn.disabled = !session || !signing.selectedDeviceName;

  if (pendingApproval) {
    const queueSuffix = (pendingApproval.queueLength || 1) > 1
      ? ` В очереди ${pendingApproval.queueLength} транзакции.`
      : '';
    els.pendingApprovalSubtitle.textContent = pendingApproval.origin
      ? `Сайт ${pendingApproval.origin} запросил подписание транзакции.${queueSuffix}`
      : `Сайт запросил подписание транзакции.${queueSuffix}`;
    renderPendingApproval(pendingApproval);
  } else {
    els.pendingApprovalSubtitle.textContent = 'Сайт запросил подписание транзакции.';
    els.pendingApprovalDetails.innerHTML = '';
  }

  if (currentWallet?.publicKeyBase58) {
    els.walletResultCard.classList.remove('hidden');
    els.walletType.textContent = currentWallet.type || '—';
    els.walletPubkey.textContent = currentWallet.publicKeyBase58 || '—';
    els.walletVerify.textContent = currentWallet.verificationText || '—';
  } else {
    els.walletResultCard.classList.add('hidden');
    els.walletType.textContent = '—';
    els.walletPubkey.textContent = '—';
    els.walletVerify.textContent = '—';
  }

  const pairing = state?.pairing || {};
  if (pairing.active) {
    els.pairingCard.classList.remove('hidden');
    els.shortCode.textContent = formatPairingShortCode(String(pairing.shortCode || ''));
    const leftMs = Number(pairing.expiresAtMs || 0) - Date.now();
    els.pairingExpire.textContent = leftMs > 0 ? `Код действителен ещё ${formatRemaining(leftMs)}.` : 'Время ожидания истекло.';
    els.startBtn.disabled = true;
  } else {
    els.pairingCard.classList.add('hidden');
    els.shortCode.textContent = formatPairingShortCode('');
    els.pairingExpire.textContent = '';
    els.startBtn.disabled = false;
  }
}

function normalizeError(response, fallback) {
  return response?.error || fallback || 'Unknown error';
}

function sendMessage(type, payload = {}) {
  return new Promise((resolve, reject) => {
    chrome.runtime.sendMessage({ type, payload }, (response) => {
      if (chrome.runtime.lastError) {
        reject(new Error(chrome.runtime.lastError.message || 'Runtime message failed'));
        return;
      }
      if (!response?.ok) {
        reject(new Error(normalizeError(response, 'Wallet operation failed')));
        return;
      }
      if (response?.state) applyState(response.state);
      resolve(response);
    });
  });
}

async function refreshState() {
  const response = await sendMessage('wallet:getState');
  applyState(response.state);
}

async function saveSettings() {
  await sendMessage('wallet:saveSettings', {
    login: String(els.loginInput.value || '').trim(),
  });
}

async function resolveServerInfo() {
  const login = String(els.loginInput.value || '').trim();
  if (!login) {
    await sendMessage('wallet:saveSettings', { login: '' });
    return;
  }
  try {
    await sendMessage('wallet:resolveServerInfo', { login });
  } catch (error) {
    setStatus(error.message || 'Не удалось определить сервер SHiNE по PDA.', 'error');
  }
}

function scheduleSaveSettings() {
  if (saveSettingsTimer) {
    window.clearTimeout(saveSettingsTimer);
  }
  saveSettingsTimer = window.setTimeout(() => {
    saveSettingsTimer = 0;
    void saveSettings();
  }, 250);
}

async function startPairing() {
  const login = String(els.loginInput.value || '').trim();
  if (!login) {
    setStatus('Введите логин.', 'error');
    return;
  }
  setStatus('Создаём wallet-session заявку...', 'info');
  try {
    await sendMessage('wallet:startPairing', {
      login,
      usePassword: !!els.usePassword.checked,
      password: String(els.passwordInput.value || ''),
    });
  } catch (error) {
    setStatus(error.message || 'Не удалось начать pairing.', 'error');
  }
}

async function cancelPairing() {
  try {
    await sendMessage('wallet:cancelPairing');
  } catch (error) {
    setStatus(error.message || 'Не удалось отменить pairing.', 'error');
  }
}

async function resumeSession() {
  setStatus('Проверяем сохранённую wallet-session...', 'info');
  try {
    await sendMessage('wallet:resumeSession');
  } catch (error) {
    setStatus(error.message || 'Не удалось восстановить session.', 'error');
  }
}

async function disconnectSession() {
  try {
    await sendMessage('wallet:disconnectSession');
  } catch (error) {
    setStatus(error.message || 'Не удалось удалить session.', 'error');
  }
}

async function refreshDevices() {
  setStatus('Обновляем trusted homeserver-устройства...', 'info');
  try {
    await sendMessage('wallet:refreshWalletDevices');
  } catch (error) {
    setStatus(error.message || 'Не удалось обновить список устройств.', 'error');
  }
}

async function updateDeviceSelection() {
  try {
    await sendMessage('wallet:updateSigningSelection', {
      selectedDeviceName: String(els.deviceSelect.value || '').trim(),
    });
  } catch (error) {
    setStatus(error.message || 'Не удалось обновить выбор homeserver.', 'error');
  }
}

async function requestCurrentWallet() {
  setStatus('Запрашиваем текущий кошелёк с ESP32...', 'info');
  try {
    await sendMessage('wallet:requestCurrentWallet');
  } catch (error) {
    setStatus(error.message || 'Не удалось получить кошелёк с ESP32.', 'error');
  }
}

async function copyWalletKey() {
  const value = String(els.walletPubkey.textContent || '').trim();
  if (!value || value === '—') return;
  try {
    await navigator.clipboard.writeText(value);
    setStatus('Публичный ключ скопирован.', 'info');
  } catch (error) {
    setStatus(error.message || 'Не удалось скопировать ключ.', 'error');
  }
}

async function cancelPendingApproval() {
  try {
    await sendMessage('wallet:cancelPendingSiteApproval');
  } catch (error) {
    setStatus(error.message || 'Не удалось отменить ожидание подписи.', 'error');
  }
}

function startUiRefreshLoop() {
  stopUiRefreshLoop();
  refreshTimer = window.setInterval(() => {
    void refreshState();
  }, 1000);
}

function stopUiRefreshLoop() {
  if (refreshTimer) {
    window.clearInterval(refreshTimer);
    refreshTimer = 0;
  }
}

function bindUi() {
  els.usePassword.addEventListener('change', () => {
    els.passwordField.classList.toggle('hidden', !els.usePassword.checked);
    if (!els.usePassword.checked) {
      els.passwordInput.value = '';
    }
  });
  els.loginInput.addEventListener('input', () => { scheduleSaveSettings(); });
  els.loginInput.addEventListener('change', () => {
    void saveSettings();
    void resolveServerInfo();
  });
  els.startBtn.addEventListener('click', () => { void startPairing(); });
  els.cancelBtn.addEventListener('click', () => { void cancelPairing(); });
  els.resumeBtn.addEventListener('click', () => { void resumeSession(); });
  els.refreshDevicesBtn.addEventListener('click', () => { void refreshDevices(); });
  els.disconnectBtn.addEventListener('click', () => { void disconnectSession(); });
  els.deviceSelect.addEventListener('change', () => { void updateDeviceSelection(); });
  els.requestWalletBtn.addEventListener('click', () => { void requestCurrentWallet(); });
  els.copyWalletBtn.addEventListener('click', () => { void copyWalletKey(); });
  els.cancelPendingApprovalBtn.addEventListener('click', () => { void cancelPendingApproval(); });
}

async function init() {
  bindUi();
  await refreshState();
  startUiRefreshLoop();
}

window.addEventListener('beforeunload', () => {
  stopUiRefreshLoop();
  if (saveSettingsTimer) {
    window.clearTimeout(saveSettingsTimer);
    saveSettingsTimer = 0;
  }
});

void init();
