'use strict';

let allClients = [];
let searchQuery = '';
let editingClient = null;

async function loadClients() {
  try {
    const res = await fetch('/api/clients');
    const json = await res.json();
    if (!res.ok || !json.success) throw new Error(json.error || `HTTP ${res.status}`);
    allClients = json.data || [];
    render();
  } catch (e) {
    showToast('Ошибка загрузки: ' + e.message, 'error');
  }
}

const ONLINE_WINDOW_MS = 5 * 60 * 1000;

function isOnline(c) {
  if (c.last_active) {
    return (Date.now() - c.last_active * 1000) < ONLINE_WINDOW_MS;
  }
  return c.online;
}

function fmtBytes(n) {
  if (!n) return '—';
  const units = ['Б', 'КБ', 'МБ', 'ГБ', 'ТБ'];
  let i = 0, v = n;
  while (v >= 1024 && i < units.length - 1) { v /= 1024; i++; }
  return `${v.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
}

function fmtLease(expiresUnix) {
  if (!expiresUnix) return null;
  const secs = expiresUnix - Math.floor(Date.now() / 1000);
  if (secs <= 0) return { text: 'истекла', cls: 'lease-expired' };
  if (secs < 3600)  return { text: `${Math.floor(secs / 60)} мин`, cls: 'lease-soon' };
  if (secs < 86400) return { text: `${Math.floor(secs / 3600)} ч`, cls: '' };
  return { text: `${Math.floor(secs / 86400)} д ${Math.floor((secs % 86400) / 3600)} ч`, cls: '' };
}

function fmtLastActive(c) {
  const nowSec = Math.floor(Date.now() / 1000);

  if (c.last_active) {
    const ago = nowSec - c.last_active;
    if (ago < 10)    return { text: 'только что', cls: 'active-now' };
    if (ago < 60)    return { text: `${ago} с назад`, cls: 'active-now' };
    if (ago < 3600)  return { text: `${Math.floor(ago / 60)} мин назад`, cls: ago < ONLINE_WINDOW_MS / 1000 ? 'active-now' : '' };
    if (ago < 86400) return { text: `${Math.floor(ago / 3600)} ч назад`, cls: '' };
    return { text: `${Math.floor(ago / 86400)} д назад`, cls: '' };
  }

  if (c.is_dhcp && c.lease_expires) {
    const lease = fmtLease(c.lease_expires);
    return lease
      ? { text: `аренда: ${lease.text}`, cls: lease.cls }
      : { text: '—', cls: '' };
  }

  return { text: '—', cls: '' };
}

function matchesSearch(c, q) {
  if (!q) return true;
  const l = q.toLowerCase();
  return (
    (c.hostname  || '').toLowerCase().includes(l) ||
    (c.ip        || '').includes(l) ||
    (c.mac       || '').toLowerCase().includes(l) ||
    (c.interface || '').toLowerCase().includes(l)
  );
}

function render() {
  const loading = document.getElementById('loading');
  const wrap    = document.getElementById('clientsTableWrap');
  const empty   = document.getElementById('emptyState');
  const body    = document.getElementById('clientsBody');
  const summary = document.getElementById('clientsSummary');

  loading.classList.add('hidden');

  const onlineCount = allClients.filter(c => isOnline(c)).length;
  const dhcpCount   = allClients.filter(c => c.is_dhcp).length;
  const blockedCount = allClients.filter(c => c.blocked).length;

  summary.innerHTML =
    `<span class="cl-stat"><span class="state-dot up"></span>${onlineCount} онлайн</span>` +
    `<span class="cl-stat cl-stat--muted">${allClients.length} всего</span>` +
    `<span class="cl-stat cl-stat--muted">${dhcpCount} по DHCP</span>` +
    (blockedCount > 0 ? `<span class="cl-stat cl-stat--blocked">${blockedCount} заблокировано</span>` : '');

  const filtered = allClients.filter(c => matchesSearch(c, searchQuery));

  if (filtered.length === 0) {
    wrap.classList.add('hidden');
    empty.classList.remove('hidden');
    empty.textContent = allClients.length === 0
      ? 'Нет подключённых устройств'
      : `Ничего не найдено по запросу «${searchQuery}»`;
    return;
  }

  empty.classList.add('hidden');
  wrap.classList.remove('hidden');

  const sorted = [...filtered].sort((a, b) => {
    const ao = isOnline(a), bo = isOnline(b);
    if (ao !== bo) return ao ? -1 : 1;
    return ipToNum(a.ip) - ipToNum(b.ip);
  });

  body.innerHTML = '';
  sorted.forEach(c => body.appendChild(buildRow(c)));
}

function buildRow(c) {
  const online   = isOnline(c);
  const tr       = document.createElement('tr');
  tr.className   = 'client-row';
  if (!online) tr.classList.add('row-offline');
  if (c.blocked) tr.classList.add('row-blocked');

  const activity = fmtLastActive(c);

  const typeCell = c.is_dhcp
    ? '<span class="client-badge dhcp">DHCP</span>'
    : '<span class="client-badge arp">ARP</span>';

  const hostname = c.hostname
    ? `<span class="client-host">${escHtml(c.hostname)}</span>`
    : '<span class="none">—</span>';

  const txHtml = c.tx_bytes
    ? `<span class="traffic-num">${fmtBytes(c.tx_bytes)}</span>`
    : '<span class="none">—</span>';

  const rxHtml = c.rx_bytes
    ? `<span class="traffic-num">${fmtBytes(c.rx_bytes)}</span>`
    : '<span class="none">—</span>';

  const actHtml = activity.text !== '—'
    ? `<span class="activity-val ${activity.cls}">${activity.text}</span>`
    : '<span class="none">—</span>';

  const ipDisplay = c.static_ip
    ? `<span class="mono">${escHtml(c.static_ip)}</span> <span class="client-badge static-badge">фикс.</span>`
    : `<span class="mono">${escHtml(c.ip)}</span>`;

  const blockedBadge = c.blocked
    ? ' <span class="client-badge blocked-badge">ЗАБЛОКИРОВАН</span>'
    : '';

  tr.innerHTML = `
    <td class="col-status">
      <span class="state-dot ${online ? 'up' : 'down'}"
            title="${online ? 'онлайн' : 'офлайн'}"></span>
    </td>
    <td class="col-host">${hostname}${blockedBadge}</td>
    <td class="col-ip">${ipDisplay}</td>
    <td class="col-mac"><span class="mono muted">${escHtml(c.mac || '—')}</span></td>
    <td class="col-iface">${escHtml(c.interface || '—')}</td>
    <td class="col-type">${typeCell}</td>
    <td class="col-tx">${txHtml}</td>
    <td class="col-rx">${rxHtml}</td>
    <td class="col-activity">${actHtml}</td>
  `;

  tr.addEventListener('click', () => openModal(c));
  return tr;
}

function openModal(c) {
  editingClient = { ...c };
  const modal = document.getElementById('clientModal');

  document.getElementById('modalTitle').textContent = c.hostname || c.ip || 'Устройство';
  document.getElementById('modalHostname').value = c.hostname || '';
  document.getElementById('modalHostname').placeholder = c.hostname ? '' : (c.mac || c.ip);

  const currentIP = c.static_ip || c.ip || '—';
  document.getElementById('modalIP').textContent = currentIP;
  const currentLabel = document.getElementById('modalIPCurrent');
  if (c.static_ip) {
    currentLabel.textContent = '(фиксированный)';
    currentLabel.style.display = '';
  } else if (c.ip) {
    currentLabel.textContent = '(DHCP: ' + c.ip + ')';
    currentLabel.style.display = '';
  } else {
    currentLabel.textContent = '';
    currentLabel.style.display = 'none';
  }

  document.getElementById('modalStaticIP').value = c.static_ip || '';
  document.getElementById('modalMAC').textContent = c.mac || '—';
  document.getElementById('modalIface').textContent = c.interface || '—';

  const blocked = document.getElementById('modalBlocked');
  blocked.checked = !c.blocked;
  updateBlockedToggle(c.blocked);

  modal.classList.remove('hidden');
  document.getElementById('modalHostname').focus();
}

function updateBlockedToggle(isBlocked) {
  const hint = document.getElementById('modalBlockHint');
  const toggle = document.getElementById('modalBlockToggle');
  const toggleContainer = document.getElementById('modalBlocked');

  if (isBlocked) {
    hint.textContent = 'Доступ в интернет заблокирован';
    hint.style.color = 'var(--danger)';
    toggleContainer.checked = false;
    toggle.classList.add('toggle-blocked');
  } else {
    hint.textContent = 'Отключите, чтобы запретить устройству выход в интернет';
    hint.style.color = '';
    toggleContainer.checked = true;
    toggle.classList.remove('toggle-blocked');
  }
}

function closeModal() {
  document.getElementById('clientModal').classList.add('hidden');
  editingClient = null;
}

async function saveClient() {
  if (!editingClient) return;

  const mac = editingClient.mac;
  if (!mac) {
    showToast('У устройства нет MAC-адреса', 'error');
    return;
  }

  const hostname = document.getElementById('modalHostname').value.trim();
  const isBlocked = !document.getElementById('modalBlocked').checked;
  const staticIP = document.getElementById('modalStaticIP').value.trim();

  const btn = document.getElementById('modalSave');
  btn.disabled = true;

  try {
    const res = await fetch('/api/clients/update/' + encodeURIComponent(mac), {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ hostname, blocked: isBlocked, static_ip: staticIP })
    });
    const json = await res.json();
    if (!res.ok || !json.success) throw new Error(json.error || `HTTP ${res.status}`);
    showToast('Настройки сохранены', 'success');
    closeModal();
    loadClients();
  } catch (e) {
    showToast('Ошибка: ' + e.message, 'error');
  } finally {
    btn.disabled = false;
  }
}

function ipToNum(ip) {
  return (ip || '').split('.').reduce((acc, o) => acc * 256 + (+o || 0), 0);
}

function escHtml(s) {
  return String(s)
    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

let toastTimer;
function showToast(msg, type = 'info') {
  const t = document.getElementById('toast');
  t.textContent = msg;
  t.className = `toast ${type}`;
  t.classList.remove('hidden');
  clearTimeout(toastTimer);
  toastTimer = setTimeout(() => t.classList.add('hidden'), 3500);
}

document.getElementById('refreshBtn').addEventListener('click', loadClients);

document.getElementById('clientsSearch').addEventListener('input', e => {
  searchQuery = e.target.value.trim();
  render();
});

document.getElementById('modalBackdrop').addEventListener('click', closeModal);
document.getElementById('modalClose').addEventListener('click', closeModal);
document.getElementById('modalCancel').addEventListener('click', closeModal);
document.getElementById('clientForm').addEventListener('submit', e => {
  e.preventDefault();
  saveClient();
});

document.getElementById('modalBlocked').addEventListener('change', () => {
  if (!editingClient) return;
  const isBlocked = !document.getElementById('modalBlocked').checked;
  updateBlockedToggle(isBlocked);
});

document.addEventListener('keydown', e => {
  if (e.key === 'Escape') closeModal();
});

setInterval(loadClients, 10000);

loadClients();