import { readShineUserPdaByRef } from '../../js/services/shine-user-pda-service.js';
import { bytesToBase58 } from '../../js/services/crypto-utils.js';
import { $, clearStatus, formatBigInt, formatTimestamp, setStatus } from './server-ui-shared.js';

function hex(bytes) {
  const data = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes || []);
  return Array.from(data).map((x) => x.toString(16).padStart(2, '0')).join('');
}

function base58(bytes) {
  const data = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes || []);
  return bytesToBase58(data);
}

function renderRows(rows) {
  const container = $('summaryRows');
  container.innerHTML = '';
  for (const row of rows) {
    const el = document.createElement('div');
    el.className = 'field-row';
    const label = document.createElement('div');
    label.className = 'field-label';
    label.textContent = row.label;
    const value = document.createElement('div');
    value.className = `field-value${row.muted ? ' muted' : ''}`;
    value.textContent = row.value;
    el.append(label, value);
    container.appendChild(el);
  }
}

function renderMiniGrid(items) {
  const wrap = document.createElement('div');
  wrap.className = 'mini-grid';
  for (const item of items) {
    const node = document.createElement('div');
    node.className = 'mini-item';
    const label = document.createElement('div');
    label.className = 'mini-label';
    label.textContent = item.label;
    const value = document.createElement('div');
    value.className = 'mini-value';
    value.textContent = item.value;
    node.append(label, value);
    wrap.appendChild(node);
  }
  return wrap;
}

function renderBlock(title, subtitle, items) {
  const card = document.createElement('div');
  card.className = 'block-card';
  const ttl = document.createElement('div');
  ttl.className = 'block-title';
  ttl.textContent = title;
  card.appendChild(ttl);
  if (subtitle) {
    const sub = document.createElement('div');
    sub.className = 'block-subtitle';
    sub.textContent = subtitle;
    card.appendChild(sub);
  }
  card.appendChild(renderMiniGrid(items));
  return card;
}

function renderArrayLine(values, emptyLabel = '—') {
  const arr = Array.isArray(values) ? values : [];
  return arr.length ? arr.join(', ') : emptyLabel;
}

function renderSessionList(sessions) {
  const list = document.createElement('div');
  list.className = 'details-wrap';
  const details = document.createElement('details');
  details.open = true;
  const summary = document.createElement('summary');
  summary.textContent = `Сессии (${Array.isArray(sessions) ? sessions.length : 0})`;
  const body = document.createElement('div');
  body.className = 'details-body';
  if (!Array.isArray(sessions) || sessions.length === 0) {
    body.innerHTML = '<div class="field-value muted">Сессий нет.</div>';
  } else {
    const grid = document.createElement('div');
    grid.className = 'block-list';
    sessions.forEach((session, idx) => {
      grid.appendChild(renderBlock(
        `Session #${idx + 1}`,
        `type=${session.sessionType}, version=${session.sessionVersion}`,
        [
          { label: 'Имя', value: session.sessionName || '—' },
          { label: 'PubKey', value: base58(session.sessionPubKey32) },
        ],
      ));
    });
    body.appendChild(grid);
  }
  details.append(summary, body);
  list.appendChild(details);
  return list;
}

function renderParsed(parsed) {
  $('summaryCard').style.display = 'block';
  $('blocksCard').style.display = 'block';
  $('rawCard').style.display = 'block';

  renderRows([
    { label: 'PDA адрес', value: parsed.pdaAddress },
    { label: 'Логин', value: parsed.login },
    { label: 'Статус', value: parsed.isServer ? 'server' : 'not server' },
    { label: 'recordNumber', value: String(parsed.recordNumber) },
    { label: 'createdAtMs', value: `${parsed.createdAtMs} · ${formatTimestamp(parsed.createdAtMs)}` },
    { label: 'updatedAtMs', value: `${parsed.updatedAtMs} · ${formatTimestamp(parsed.updatedAtMs)}` },
    { label: 'recordLen', value: String(parsed.recordLen) },
    { label: 'prevRecordHash32', value: hex(parsed.prevRecordHash) },
    { label: 'signature64', value: base58(parsed.signature) },
    { label: 'unsignedBytesLen', value: String(parsed.unsignedBytes?.length || 0) },
  ]);

  const badgeLine = $('badgeLine');
  badgeLine.innerHTML = '';
  const badges = [
    { label: `server=${parsed.isServer ? '1' : '0'}`, kind: parsed.isServer ? 'ok' : 'warn' },
    { label: `trusted=${Number(parsed.trustedCount || 0)}`, kind: Number(parsed.trustedCount || 0) > 0 ? 'ok' : 'warn' },
    { label: `sessions=${Array.isArray(parsed.sessions) ? parsed.sessions.length : 0}`, kind: 'info' },
    { label: `access=${Array.isArray(parsed.accessServers) ? parsed.accessServers.length : 0}`, kind: 'info' },
    { label: `sync=${Array.isArray(parsed.syncServers) ? parsed.syncServers.length : 0}`, kind: 'info' },
  ];
  badges.forEach((item) => {
    const badge = document.createElement('span');
    badge.className = `badge ${item.kind}`;
    badge.textContent = item.label;
    badgeLine.appendChild(badge);
  });

  const blocks = $('blocksList');
  blocks.innerHTML = '';
  blocks.appendChild(renderBlock('RecoveryKeyBlock', 'block_type=0', [
    { label: 'recoveryKey32', value: base58(parsed.recoveryKey) },
  ]));
  blocks.appendChild(renderBlock('RootKeyBlock', 'block_type=1', [
    { label: 'rootKey32', value: base58(parsed.rootKey) },
  ]));
  blocks.appendChild(renderBlock('ClientKeyBlock', 'block_type=2', [
    { label: 'clientKey32', value: base58(parsed.clientKey) },
  ]));
  blocks.appendChild(renderBlock('BlockchainRegistryBlock', 'block_type=3', [
    { label: 'blockchainType', value: String(parsed.blockchain?.blockchainType ?? 0) },
    { label: 'blockchainName', value: parsed.blockchain?.blockchainName || '—' },
    { label: 'blockchainPublicKey32', value: base58(parsed.blockchain?.blockchainPublicKey) },
    { label: 'paidLimitBytes', value: formatBigInt(parsed.blockchain?.paidLimitBytes || 0n) },
    { label: 'usedBytes', value: formatBigInt(parsed.blockchain?.usedBytes || 0n) },
    { label: 'lastBlockNumber', value: String(parsed.blockchain?.lastBlockNumber ?? 0) },
    { label: 'lastBlockHash32', value: hex(parsed.blockchain?.lastBlockHash) },
    { label: 'lastBlockSignature64', value: base58(parsed.blockchain?.lastBlockSignature) },
    { label: 'arweaveTxId', value: parsed.blockchain?.arweaveTxId || '—' },
  ]));
  blocks.appendChild(renderBlock('ServerProfileBlock', 'block_type=30', [
    { label: 'isServer', value: parsed.isServer ? '1' : '0' },
    { label: 'addressFormatType', value: String(parsed.addressFormatType ?? 0) },
    { label: 'addressFormatVersion', value: String(parsed.addressFormatVersion ?? 0) },
    { label: 'serverAddress', value: parsed.serverAddress || '—' },
    { label: 'syncServersCount', value: String(parsed.syncServers?.length || 0) },
    { label: 'syncServers', value: renderArrayLine(parsed.syncServers) },
  ]));
  blocks.appendChild(renderBlock('AccessServersBlock', 'block_type=40', [
    { label: 'accessServersCount', value: String(parsed.accessServers?.length || 0) },
    { label: 'accessServers', value: renderArrayLine(parsed.accessServers) },
  ]));
  blocks.appendChild(renderBlock('SessionsBlock', 'block_type=50', [
    { label: 'sessionsMode', value: String(parsed.sessionsMode ?? 0) },
    { label: 'sessionsCount', value: String(parsed.sessions?.length || 0) },
    { label: 'sessions', value: parsed.sessions?.length ? 'ниже' : '—' },
  ]));
  blocks.appendChild(renderBlock('TrustedStateBlock', 'block_type=70', [
    { label: 'trustedCount', value: String(parsed.trustedCount ?? 0) },
  ]));
  blocks.appendChild(renderSessionList(parsed.sessions));

  $('rawJson').textContent = JSON.stringify({
    pdaAddress: parsed.pdaAddress,
    login: parsed.login,
    isServer: parsed.isServer,
    recordNumber: parsed.recordNumber,
    createdAtMs: parsed.createdAtMs.toString(),
    updatedAtMs: parsed.updatedAtMs.toString(),
    recordLen: parsed.recordLen,
    trustedCount: parsed.trustedCount,
    addressFormatType: parsed.addressFormatType,
    addressFormatVersion: parsed.addressFormatVersion,
    serverAddress: parsed.serverAddress,
    syncServers: parsed.syncServers,
    accessServers: parsed.accessServers,
    sessionsMode: parsed.sessionsMode,
    sessions: parsed.sessions.map((s) => ({
      sessionType: s.sessionType,
      sessionVersion: s.sessionVersion,
      sessionName: s.sessionName,
      sessionPubKey32: base58(s.sessionPubKey32),
    })),
    recoveryKey: base58(parsed.recoveryKey),
    rootKey: base58(parsed.rootKey),
    clientKey: base58(parsed.clientKey),
    blockchain: {
      blockchainType: parsed.blockchain.blockchainType,
      blockchainName: parsed.blockchain.blockchainName,
      blockchainPublicKey: base58(parsed.blockchain.blockchainPublicKey),
      paidLimitBytes: parsed.blockchain.paidLimitBytes.toString(),
      usedBytes: parsed.blockchain.usedBytes.toString(),
      lastBlockNumber: parsed.blockchain.lastBlockNumber,
      lastBlockHash: hex(parsed.blockchain.lastBlockHash),
      lastBlockSignature: base58(parsed.blockchain.lastBlockSignature),
      arweaveTxId: parsed.blockchain.arweaveTxId || '',
    },
  }, null, 2);
}

$('btnLoad').addEventListener('click', async () => {
  clearStatus($('status'));
  $('btnLoad').disabled = true;
  $('summaryCard').style.display = 'none';
  $('blocksCard').style.display = 'none';
  $('rawCard').style.display = 'none';
  try {
    const endpoint = String($('endpoint').value || '').trim();
    const ref = String($('ref').value || '').trim();
    if (!endpoint) throw new Error('Укажите Solana endpoint');
    if (!ref) throw new Error('Укажите логин или адрес PDA');

    setStatus($('status'), 'Чтение PDA...', 'info');
    const parsed = await readShineUserPdaByRef({ value: ref, solanaEndpoint: endpoint });
    renderParsed(parsed);
    setStatus($('status'), 'PDA загружена.', 'success');
  } catch (error) {
    setStatus($('status'), error?.message || String(error), 'error');
  } finally {
    $('btnLoad').disabled = false;
  }
});

document.body.dataset.ready = '1';
