// ===================== Navegación por hash  =====================
const routes = ["panel","tickets","logs","comandos","config"];
const navLinks = document.querySelectorAll('.nav a');
function setRoute(hash){
  const target = (hash||'').replace('#','') || 'panel';
  routes.forEach(id=>{
    const sec = document.getElementById(id);
    if(!sec) return;
    if(id === target) sec.removeAttribute('hidden'); else sec.setAttribute('hidden','');
  });
  navLinks.forEach(a=>{
    if((a.getAttribute('href')||'').includes('#'+target)) a.classList.add('active'); else a.classList.remove('active');
  });
  if (target === 'panel') {
    loadKpis().catch(()=>{});
    // Carga inicial de últimos eventos en el panel
    loadLogs('', '#panel #latest-events .table tbody').catch(()=>{});
    loadStatus().catch(()=>{});
  }
  if (target === 'logs')  loadLogs().catch(()=>{});
  if (target === 'tickets') loadTickets().catch(()=>{});
}
window.addEventListener('hashchange', ()=> setRoute(location.hash));
setRoute(location.hash);

// =============================== Tabs  ===============================
const tabButtons = document.querySelectorAll('.tab');
tabButtons.forEach(btn=>{
  btn.addEventListener('click',()=>{
    tabButtons.forEach(b=>b.classList.remove('active'));
    btn.classList.add('active');
    const k = btn.dataset.tab;
    ["metrics","servicios","webhooks"].forEach(t=>{
      const el = document.getElementById('panel-'+t);
      if(el) el.hidden = t!==k;
    });
  })
});

// ========================= Buscador Ctrl+K  =========================
const q = document.getElementById('q');
window.addEventListener('keydown', (e)=>{
  if((e.ctrlKey || e.metaKey) && e.key.toLowerCase()==='k'){
    e.preventDefault(); q?.focus();
  }
});

// ============================= Modal tickets  =============================
const modal = document.getElementById('modal-ticket');
document.querySelectorAll('[data-open-modal="ticket"]').forEach(btn=>{
  btn.addEventListener('click', ()=> modal?.showModal());
});
modal?.querySelector('[data-close]')?.addEventListener('click', ()=> modal?.close());

// =============================== Toast helper  ===============================
function toast(msg, kind){
  const host = document.getElementById('toast');
  if(!host) return;
  const el = document.createElement('div');
  el.className = 'item' + (kind ? ` ${kind}` : '');
  el.textContent = msg;
  host.appendChild(el);
  setTimeout(()=>{ el.style.opacity=.0; el.style.transform='translateY(6px)'; }, 2600);
  setTimeout(()=>{ host.removeChild(el); }, 3200);
}

// ================================ Acciones demo (tu código) ================================
document.getElementById('btnSync')?.addEventListener('click', ()=> toast('Sincronización iniciada…'));
document.getElementById('btnDeploy')?.addEventListener('click', ()=> toast('Desplegando…'));

// =============================== Tema (tu código) ===============================
const toggle = document.getElementById('toggleTheme');
let light = window.matchMedia('(prefers-color-scheme: light)').matches;
toggle?.addEventListener('click', ()=>{
  light = !light;
  document.documentElement.style.colorScheme = light ? 'light' : 'dark';
  toast('Tema: ' + (light ? 'claro' : 'oscuro'));
});

// ---- Theme selector (modal + persist) ----
const THEME_KEY = 'panel:theme';
function applyTheme(theme, opts={persist:true}){
  const t = (theme||'').toLowerCase();
  const allowed = ['light','dark','fire'];
  const final = allowed.includes(t) ? t : 'dark';
  document.documentElement.setAttribute('data-theme', final);
  document.documentElement.style.colorScheme = (final === 'light') ? 'light' : 'dark';
  if (opts.persist) try { localStorage.setItem(THEME_KEY, final); } catch {}
  updateActiveThemeInModal(final);
}
function getStoredTheme(){ try { return localStorage.getItem(THEME_KEY) || ''; } catch { return ''; } }
function getPreferredTheme(){
  const stored = getStoredTheme();
  if (stored) return stored;
  const prefersLight = window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches;
  return prefersLight ? 'light' : 'dark';
}
function updateActiveThemeInModal(current){
  document.querySelectorAll('[data-theme-option]')?.forEach(card=>{
    const v = card.getAttribute('data-theme-option');
    if (v === current) card.classList.add('active'); else card.classList.remove('active');
  });
  const adminBtn = document.getElementById('btn-admin');
  if (adminBtn) {
    const isAdmin = ['admin','superadmin'].includes(rank);
    if (!isAdmin) adminBtn.setAttribute('hidden',''); else adminBtn.removeAttribute('hidden');
  }
}
function initThemeUI(){
  const old = document.getElementById('toggleTheme');
  let toggleButton = old;
  // Replace node to remove earlier click listeners
  if (old) { const clone = old.cloneNode(true); old.replaceWith(clone); toggleButton = clone; }
  const dlg = document.getElementById('modal-theme');
  const btnClose = document.getElementById('theme-close');
  const btnApply = document.getElementById('theme-apply');
  let pending = getPreferredTheme();
  toggleButton?.addEventListener('click', ()=>{
    updateActiveThemeInModal(getPreferredTheme());
    try { dlg?.showModal(); } catch { if (dlg) dlg.open = true; }
  });
  btnClose?.addEventListener('click', ()=>{ try { dlg?.close(); } catch { if (dlg) dlg.open = false; } });
  document.querySelectorAll('[data-theme-option]')?.forEach(card=>{
    card.addEventListener('click', ()=>{
      pending = card.getAttribute('data-theme-option') || 'dark';
      applyTheme(pending);
      try { dlg?.close(); } catch { if (dlg) dlg.open = false; }
      toast('Tema: ' + (pending==='light'?'claro': pending==='dark'?'oscuro':'fuego'));
    });
  });
  btnApply?.addEventListener('click', ()=>{
    applyTheme(pending);
    try { dlg?.close(); } catch { if (dlg) dlg.open = false; }
  });
}

// =========================================
// Acciones demo
// =========================================
document.querySelectorAll('[data-action]')?.forEach(b=>{
  b.addEventListener('click', ()=> toast('Acción: '+b.dataset.action));
});

// =====================================================
// ===== A PARTIR DE AQUÍ: CONEXIÓN CON EL PANEL API ====
// =====================================================

// ==================================== Helpers REST ====================================
function computeApiBase() {
  if (typeof window.API_BASE !== 'undefined' && window.API_BASE) return window.API_BASE.replace(/\/+$/, '');
  const meta = document.querySelector('meta[name="base-path"]');
  const basePath = (meta?.content || '').replace(/\/+$/, '').replace(/^\/+/, '');
  if (basePath) return window.location.origin + '/' + basePath;
  // Heurística: tomar el primer segmento del path si existe (p.ej. /panel)
  const seg = (window.location.pathname || '/').split('/').filter(Boolean)[0];
  return window.location.origin + (seg ? '/' + seg : '');
}
let API_BASE = computeApiBase();
// Debug banner eliminado

async function fetchJSON(path, opts = {}) {
  const res = await fetch(API_BASE + path, {
    credentials: 'include',
    headers: { 'Content-Type': 'application/json', ...(opts.headers||{}) },
    method: opts.method || 'GET',
    body: opts.body ? JSON.stringify(opts.body) : undefined
  });
  if (!res.ok) {
    let text = ''; try { text = await res.text(); } catch {}
    throw new Error(`HTTP ${res.status} ${path}${text ? ` - ${text}` : ''}`);
  }
  return res.json();
}

// ========================= Login UI =========================
async function refreshAuthUI() {
  const loginBtn = document.getElementById('btn-login');
  const userPill = document.getElementById('user-pill');
  const postLoginCard = document.getElementById('post-login-card'); // NUEVO

  try {
    const { user } = await fetchJSON('/api/me');
    if (loginBtn) loginBtn.hidden = true;
    if (userPill) {
      userPill.hidden = false;
      const roleDisplay = user.rank ? ` (${user.rank.charAt(0).toUpperCase() + user.rank.slice(1)})` : '';
      const nameEl = userPill.querySelector('.user-name');
      const roleEl = userPill.querySelector('.user-role');
      if (nameEl) nameEl.textContent = user.username;
      if (roleEl) roleEl.textContent = roleDisplay;
    }
    if (postLoginCard) postLoginCard.hidden = false; // ← mostrar SOLO ese cuadro al loguear
    return user;
  } catch {
    if (loginBtn) loginBtn.hidden = false;
    if (userPill) userPill.hidden = true;
    if (postLoginCard) postLoginCard.hidden = true; // ← oculto si no hay sesión
    return null;
  }
}

// Re-define refreshAuthUI with avatar support and robust hidden toggling
async function refreshAuthUI() {
  const loginBtn = document.getElementById('btn-login');
  const userPill = document.getElementById('user-pill');
  const postLoginCard = document.getElementById('post-login-card');
  try {
    const { user } = await fetchJSON('/api/me');
    // expone el usuario actual para acciones del menú
    window.CURRENT_USER = user;
    if (loginBtn) loginBtn.setAttribute('hidden', '');
    if (userPill) {
      userPill.removeAttribute('hidden');
      const nameEl = userPill.querySelector('.user-name');
      const roleEl = userPill.querySelector('.user-role');
      const avatarEl = userPill.querySelector('.user-avatar');
      const roleDisplay = user.rank ? ` (${user.rank.charAt(0).toUpperCase() + user.rank.slice(1)})` : '';
      if (nameEl) nameEl.textContent = user.username || '';
      if (roleEl) roleEl.textContent = roleDisplay;
      if (avatarEl) {
        const url = user?.avatar
          ? `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png?size=64`
          : 'https://cdn.discordapp.com/embed/avatars/0.png';
        avatarEl.src = url;
        avatarEl.alt = user.username || 'user';
      }
    }
    if (postLoginCard) postLoginCard.removeAttribute('hidden');
    return user;
  } catch (_e) {
    if (loginBtn) loginBtn.removeAttribute('hidden');
    if (userPill) userPill.setAttribute('hidden', '');
    if (postLoginCard) postLoginCard.setAttribute('hidden', '');
    return null;
  }
}

// ========================================= KPIs =========================================
async function loadKpis() {
  const d = await fetchJSON('/api/kpis');

  // Eventos últimas 24h
  setText('kpi-members', d.events24h ?? '-');
  setText('kpi-members-delta', '');

  // Resto
  setText('kpi-users',   (d.users ?? 0).toLocaleString());
  setText('kpi-tickets', d.ticketsOpen ?? '-');
  setText('kpi-errors',  d.errors24h ?? '-');
}
function setText(id, value){ const el = document.getElementById(id); if (el) el.textContent = value; }

// ======================================== Status ========================================
async function loadStatus(){
  const s = await fetchJSON('/api/status');
  const m = s?.metrics || {};
  if (m.wsPing != null) {
    setText('st-latency', `${m.wsPing} ms`);
    setBadgeState('st-latency', m.wsPing, { ok: v=>v<100, warn: v=>v<250 });
  }
  if (m.memMB != null) {
    setText('st-mem', `${m.memMB} MB`);
    setBadgeState('st-mem', m.memMB, { ok: v=>v<400, warn: v=>v<800 });
  }
  if (m.cpuPct != null) {
    setText('st-cpu', `${m.cpuPct}`);
    setTextState('st-cpu', m.cpuPct, { ok: v=>v<30, warn: v=>v<70 });
  }
  if (m.guilds != null) setText('st-guilds', `${m.guilds}`);
  if (m.usersCached != null) setText('st-users', `${m.usersCached}`);
  if (m.uptimeSec != null) setText('st-uptime', formatUptime(m.uptimeSec));
}
function formatUptime(sec){ const d=Math.floor(sec/86400),h=Math.floor((sec%86400)/3600),m=Math.floor((sec%3600)/60); return [d?d+'d':null,h?h+'h':null,(sec%60)+'s'].filter(Boolean).join(' '); }

// Aplica clases de color a un chip .badge-pill que contiene el elemento con id dado
function setBadgeState(valueElId, value, rules){
  const el = document.getElementById(valueElId);
  if (!el) return;
  const chip = el.closest('.badge-pill');
  if (!chip) return;
  chip.classList.remove('pill-ok','pill-warn','pill-err');
  let cls = 'pill-err';
  try {
    if (rules?.ok && rules.ok(value)) cls = 'pill-ok';
    else if (rules?.warn && rules.warn(value)) cls = 'pill-warn';
  } catch {}
  chip.classList.add(cls);
}

// Aplica clases de color a un <b id="..."> dentro de listas
function setTextState(valueElId, value, rules){
  const el = document.getElementById(valueElId);
  if (!el) return;
  el.classList.remove('text-ok','text-warn','text-err');
  let cls = 'text-err';
  try {
    if (rules?.ok && rules.ok(value)) cls = 'text-ok';
    else if (rules?.warn && rules.warn(value)) cls = 'text-warn';
  } catch {}
  el.classList.add(cls);
}

// Oculta/ muestra secciones según permisos
function applyPermissions(user){
  const rank = (user?.rank || '').toLowerCase();
  const isStaff = ['staff','mod','admin','superadmin'].includes(rank);
  const nav = document.querySelector('.nav');
  const hideIfNoStaff = ['tickets','logs'];
  hideIfNoStaff.forEach(r=>{
    const link = nav?.querySelector(`[data-route="${r}"]`);
    if (!link) return;
    if (!isStaff) link.setAttribute('hidden',''); else link.removeAttribute('hidden');
  });
}

// ======================================== Logs ========================================
const LOG_MAX_ROWS = 20;
function trimTableBodyRows(tbody, max = LOG_MAX_ROWS){
  if (!tbody) return;
  const rows = tbody.querySelectorAll('tr');
  for (let i = max; i < rows.length; i++) {
    rows[i].remove();
  }
}
async function loadLogs(guildId = '', containerSelector) {
  const rows = await fetchJSON('/api/logs?limit=20');
  const tbody = (containerSelector ? document.querySelector(containerSelector) : null)
            || document.querySelector('#logs .table tbody')
            || document.getElementById('tbl-logs')
            || document.querySelector('#logs tbody');
  if (!tbody) return;
  tbody.innerHTML = '';
  rows.forEach(l=>{
    const tr = document.createElement('tr');
    const sev = (l.severity || 'info').toLowerCase();
    const className = sev === 'error' ? 'err' : (sev === 'warn' ? 'warn' : 'ok');
    const sevText = sev.charAt(0).toUpperCase() + sev.slice(1);
    tr.innerHTML = `
      <td>${new Date(l.ts).toLocaleString()}</td>
      <td>${l.origin||'-'}</td>
      <td>${l.event||'-'}</td>
      <td><span class="status"><span class="dot ${className}"></span>${sevText}</span></td>`;
    tbody.appendChild(tr);
  });
  trimTableBodyRows(tbody, LOG_MAX_ROWS);
}

// ======================================= Tickets =======================================
async function loadTickets() {
  const rows = await fetchJSON('/api/tickets');
  const tbody = document.querySelector('#tickets .table tbody')
             || document.getElementById('tbl-tickets')
             || document.querySelector('#tickets tbody');
  if (!tbody) return;
  tbody.innerHTML = '';
  rows.forEach(t => {
    const tr = document.createElement('tr');
    tr.innerHTML = `
      <td>#${t.id}</td>
      <td><code>${t.userId || '-'}</code></td>
      <td>${t.assignedId ? `<code>${t.assignedId}</code>` : '-'}</td>
      <td>${t.category || '-'}</td>
      <td>${t.status || '-'}</td>
    `;
    tbody.appendChild(tr);
  });
}

// =================================== Live (opcional) ===================================
function initLive() {
  if (typeof io !== 'function') { console.warn('[live] Socket.IO client no está cargado'); return; }
  const basePath = (new URL(API_BASE)).pathname.replace(/\/+$/, '');
  const socket = io(`${API_BASE}/live`, { withCredentials: true, path: `${basePath || ''}/socket.io` });
  socket.on('connect', () => console.log('[live] conectado:', socket.id));
  socket.on('disconnect', () => console.log('[live] desconectado'));
  socket.on('event', (e) => {
    const tbody = document.querySelector('#panel .table tbody')
               || document.getElementById('tbl-events')
               || document.querySelector('#panel tbody');
    if (!tbody) return;
    const tr = document.createElement('tr');
    tr.innerHTML = `
      <td>${new Date(e.ts || Date.now()).toLocaleString()}</td>
      <td>${e.origin || '-'}</td>
      <td>${e.event || e.command || '-'}</td>
      <td><span class="status"><span class="dot ok"></span>OK</span></td>`;
    tbody.prepend(tr);
    trimTableBodyRows(tbody, LOG_MAX_ROWS);
  });
}

// ================================== Arranque Frontend ==================================
document.addEventListener('DOMContentLoaded', async ()=>{
  // Tema inicial y UI del selector
  applyTheme(getPreferredTheme(), { persist:false });
  initThemeUI();
  const basePath = (new URL(API_BASE)).pathname.replace(/\/+$/, '');
  // Debug banner eliminado

  // Probar si el backend responde en API_BASE; si no, caer a puerto 3001
  try {
    const res = await fetch(API_BASE + '/api/health', { credentials: 'include' });
    if (!res.ok) throw new Error('health not ok');
  } catch {
    API_BASE = `${window.location.protocol}//${window.location.hostname}:3001`;
    // fallback silencioso
  }

  // Reescribe hrefs de navegación para mantener la subruta (ej. /panel/#logs)
  document.querySelectorAll('.nav a[data-route]')?.forEach(a => {
    const route = a.getAttribute('data-route') || '';
    a.setAttribute('href', `${basePath}/#${route || 'panel'}`);
  });

  // Botón de login: fija href según API_BASE detectado (sin interceptar click)
  const loginBtn = document.getElementById('btn-login');
  if (loginBtn) {
    const loginUrl = `${API_BASE}/auth/discord/login`;
    loginBtn.setAttribute('href', loginUrl);
  }
  // Toggle menú usuario
  const pill = document.getElementById('user-pill');
  const menu = document.getElementById('user-menu');
  pill?.addEventListener('click', (e)=>{
    e.preventDefault();
    if (!menu) return;
    const visible = menu.style.display === 'block';
    menu.style.display = visible ? 'none' : 'block';
  });
  document.addEventListener('click', (e)=>{
    if (!menu || !pill) return;
    if (!pill.contains(e.target)) menu.style.display='none';
  });
  // Logout
  const logoutMenu = document.getElementById('menu-logout');
  const profileMenu = document.getElementById('menu-profile');
  if (logoutMenu) {
    logoutMenu.addEventListener('click', async (e)=>{
      e.preventDefault();
      try { await fetch(`${API_BASE}/auth/logout`, { credentials:'include' }); } catch {}
      const basePath = (new URL(API_BASE)).pathname.replace(/\/+$/, '');
      window.location.assign(basePath || '/');
    });
  }
  if (profileMenu) {
    profileMenu.addEventListener('click', (e)=>{
      e.preventDefault();
      const dlg = document.getElementById('modal-profile');
      if (!dlg) return;
      populateProfileModal(window.CURRENT_USER);
      try { dlg.showModal(); } catch { dlg.open = true; }
    });
  }
  // Admin modal open
  const adminBtn = document.getElementById('btn-admin');
  const adminDlg = document.getElementById('modal-admin');
  adminBtn?.addEventListener('click', (e)=>{
    e.preventDefault();
    try { adminDlg?.showModal(); } catch { if (adminDlg) adminDlg.open = true; }
    // Cargar datos de admin (ranks)
    loadRanks().catch(()=>{});
    loadAdminUsers().catch(()=>{});
  });
  document.getElementById('admin-close')?.addEventListener('click', ()=>{ try { adminDlg?.close(); } catch { if (adminDlg) adminDlg.open = false; } });
  document.getElementById('admin-ok')?.addEventListener('click', ()=>{ try { adminDlg?.close(); } catch { if (adminDlg) adminDlg.open = false; } });
  document.getElementById('btn-ranks-refresh')?.addEventListener('click', ()=> loadRanks().catch(()=>{}));
  document.getElementById('btn-rank-save')?.addEventListener('click', async ()=>{
    const sel = document.getElementById('rank-user-select');
    const uid = sel?.value?.trim(); // discordId
    const rank = document.getElementById('rank-select')?.value;
    if (!uid || !rank) return toast('Faltan datos', 'error');
    try {
      await fetch(API_BASE + '/api/ranks/' + encodeURIComponent(uid), {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ rank })
      });
      toast('Rango actualizado');
      await loadRanks();
    } catch { toast('No se pudo actualizar', 'error'); }
  });
  document.getElementById('btn-restart')?.addEventListener('click', async ()=>{
    const code = document.getElementById('sudo-code')?.value?.trim();
    if (!code) return toast('Introduce SUDO code', 'error');
    try {
      const res = await fetch(API_BASE + '/api/actions/restart', {
        method: 'POST', credentials: 'include',
        headers: { 'Content-Type': 'application/json', 'x-sudo-code': code, 'x-sudo-ok': '1' },
      }).then(r=>r.json());
      if (res?.ok) toast('Solicitud de reinicio enviada'); else toast('No se pudo reiniciar', 'error');
    } catch { toast('Error al reiniciar', 'error'); }
  });
  document.getElementById('btn-cleanup-logs')?.addEventListener('click', async ()=>{
    const code = document.getElementById('sudo-code')?.value?.trim();
    const days = parseInt(document.getElementById('cleanup-days')?.value || '30', 10);
    if (!code) return toast('Introduce SUDO code', 'error');
    try {
      const res = await fetch(API_BASE + '/api/actions/cleanup-logs', {
        method: 'POST', credentials: 'include',
        headers: { 'Content-Type': 'application/json', 'x-sudo-code': code, 'x-sudo-ok': '1' },
        body: JSON.stringify({ olderThanDays: days })
      }).then(r=>r.json());
      if (res?.ok) { toast(`Logs limpiados: ${res.deleted||0}`); await loadLogs().catch(()=>{}); }
      else toast('No se pudo limpiar', 'error');
    } catch { toast('Error al limpiar', 'error'); }
  });
  // (Eliminado) opción de copiar ID desde el menú de la pill
  const me = await refreshAuthUI();
  if (me) {
    // Aplicar permisos de visibilidad
    try { applyPermissions(me); } catch {}
    try {
      await Promise.all([ loadKpis(), loadLogs(), loadStatus() ]);
    } catch (err) {
      console.error(err);
      toast('No se pudieron cargar los datos iniciales', 'error');
    }
    initLive(); // activa eventos en tiempo real si el servidor está disponible
    setInterval(() => { loadKpis().catch(()=>{}); loadStatus().catch(()=>{}); }, 30_000);
    // Auto refresco de tickets y sincronización con el bot
    setInterval(async () => {
      try { await fetchJSON('/api/tickets/sync', { method: 'POST' }); } catch {}
      try { await loadTickets(); } catch {}
    }, 60_000);
  }
});

// ===================== Perfil: rellenar modal + cierres =====================
function populateProfileModal(u){
  if (!u) u = window.CURRENT_USER || {};
  const avatarEl = document.getElementById('profile-avatar');
  const userEl = document.getElementById('profile-username');
  const didEl = document.getElementById('profile-discord-id');
  const pidEl = document.getElementById('profile-panel-id');
  const prankEl = document.getElementById('profile-panel-rank');
  const drankEl = document.getElementById('profile-discord-rank');
  const loginAtEl = document.getElementById('profile-login-at');
  const loginAgoEl = document.getElementById('profile-login-ago');
  if (avatarEl) {
    const url = u?.avatar
      ? `https://cdn.discordapp.com/avatars/${u.id}/${u.avatar}.png?size=128`
      : 'https://cdn.discordapp.com/embed/avatars/0.png';
    avatarEl.src = url; avatarEl.alt = u?.username || 'user';
  }
  if (userEl) userEl.textContent = u?.username || '-';
  if (didEl) didEl.textContent = u?.id || '-';
  if (pidEl) pidEl.textContent = (u?.panelId != null) ? String(u.panelId) : '-';
  if (prankEl) prankEl.textContent = (u?.rank || '').toString() || '-';
  if (drankEl) drankEl.textContent = 'N/D';
  // Login time from JWT iat (seconds since epoch)
  if (typeof u?.iat === 'number'){
    const loginDate = new Date(u.iat * 1000);
    if (loginAtEl) loginAtEl.textContent = loginDate.toLocaleString();
    if (loginAgoEl) loginAgoEl.textContent = timeSince(loginDate);
  } else {
    if (loginAtEl) loginAtEl.textContent = '-';
    if (loginAgoEl) loginAgoEl.textContent = '-';
  }
}

function timeSince(date){
  const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
  const units = [
    ['año', 365*24*3600],
    ['mes', 30*24*3600],
    ['día', 24*3600],
    ['hora', 3600],
    ['minuto', 60],
    ['segundo', 1],
  ];
  for (const [name, s] of units){
    const v = Math.floor(seconds / s);
    if (v >= 1) return `${v} ${name}${v>1?'s':''}`;
  }
  return 'instantes';
}

// Cerrar modal perfil
document.getElementById('profile-close')?.addEventListener('click', ()=>{
  const dlg = document.getElementById('modal-profile');
  try { dlg?.close(); } catch { if (dlg) dlg.open = false; }
});
document.getElementById('profile-close-2')?.addEventListener('click', ()=>{
  const dlg = document.getElementById('modal-profile');
  try { dlg?.close(); } catch { if (dlg) dlg.open = false; }
});

// Copiar Panel ID desde el modal de perfil
document.getElementById('profile-copy-id')?.addEventListener('click', async ()=>{
  try {
    const id = (window.CURRENT_USER?.panelId != null) ? String(window.CURRENT_USER.panelId) : '';
    if (!id) return toast('Sin Panel ID', 'error');
    await navigator.clipboard.writeText(id);
    toast('Panel ID copiado');
  } catch {
    toast('No se pudo copiar', 'error');
  }
});

// ================== Tickets: botón de sincronización manual ==================
document.getElementById('btnTicketsSync')?.addEventListener('click', async ()=>{
  try {
    await fetchJSON('/api/tickets/sync', { method: 'POST' });
    toast('Sincronización de tickets solicitada');
    await loadTickets();
  } catch {
    toast('No se pudo sincronizar tickets', 'error');
  }
});

// ================== Admin: cargar lista de rangos ==================
async function loadRanks(){
  const rows = await fetchJSON('/api/ranks');
  const tbody = document.getElementById('tbl-ranks');
  if (!tbody) return;
  tbody.innerHTML = '';
  rows.forEach(r=>{
    const tr = document.createElement('tr');
    tr.innerHTML = `<td><code>${r.userId}</code></td><td>${r.guildId || '-'}</td><td>${r.rank}</td>`;
    tbody.appendChild(tr);
  });
}

async function loadAdminUsers(){
  const rows = await fetchJSON('/api/ranks/users');
  const sel = document.getElementById('rank-user-select');
  if (!sel) return;
  sel.innerHTML = '';
  rows.forEach(u => {
    const opt = document.createElement('option');
    const labelName = u.username || 'Usuario';
    opt.value = u.discordId;
    opt.textContent = `${labelName} (${u.panelId ?? '-'})`;
    sel.appendChild(opt);
  });
}


