(async () => {
  // ── 1. Verificar sesión de usuario ────────────────────────────────────────
  const savedToken   = sessionStorage.getItem('arkhon_token');
  const savedRol     = sessionStorage.getItem('arkhon_rol');
  const savedNombre  = sessionStorage.getItem('arkhon_nombre');
  const savedPerms   = sessionStorage.getItem('arkhon_permissions') || sessionStorage.getItem('arkhon_permisos');

  // Si no hay token en sesión → redirigir a /login
  // Excepción: si el sistema no tiene usuarios configurados (primera vez)
  if (!savedToken) {
    try {
      const chk = await fetch('/api/login-config');
      const cfg  = await chk.json();
      const users = Object.values(cfg.usuarios || {}).filter(u => u && u.tienePin);
      if (!users.length) {
        window.location.href = '/admin-setup?tab=seguridad';
        return;
      }
      if (users.length) {
        window.location.href = '/login';
        return;
      }
      // Sin usuarios → cargar LOCAL_API_KEY y continuar como admin
    } catch(_) {}
  }

  // ── 2. Obtener LOCAL_API_KEY del servidor (con reintentos) ───────────────
  // BUG-FIX: si el servidor aún no está listo al cargar la página, el fetch
  // falla silenciosamente y LOCAL_API_KEY queda vacío → todas las APIs devuelven
  // 401 → el dashboard muestra "—" en todos los campos.
  // Solución: reintentar hasta 5 veces con 800ms de espera entre intentos.
  const fetchLocalToken = async (intentos = 5, espera = 800) => {
    for (let i = 0; i < intentos; i++) {
      try {
        const r = await fetch('/api/local-token');
        if (r.ok) {
          const d = await r.json();
          if (d.ok && d.token) return d.token;
        }
      } catch (_) {}
      if (i < intentos - 1) await new Promise(res => setTimeout(res, espera));
    }
    return null;
  };

  // Si tenemos token de sesión de usuario, no necesitamos el LOCAL_API_KEY
  if (savedToken) {
    LOCAL_API_KEY = savedToken;
  } else {
    const tok = await fetchLocalToken();
    if (tok) {
      LOCAL_API_KEY = tok;
      sessionStorage.removeItem('arkhon_reload_count'); // Reset counter on success
    } else {
      // Sin token no podemos cargar datos — mostrar aviso y reintentar en 3s
      // P2-C FIX: Limitar reloads con contador en sessionStorage para evitar loop infinito
      const reloadCount = parseInt(sessionStorage.getItem('arkhon_reload_count') || '0');
      console.warn(`[ARKHON] No se pudo obtener el token de autenticación. Intento ${reloadCount + 1}/8`);
      if (reloadCount >= 8) {
        // Mostrar pantalla de error en lugar de seguir recargando indefinidamente
        document.body.innerHTML = `
          <div style="display:flex;align-items:center;justify-content:center;min-height:100vh;background:#0a0a0f;font-family:system-ui,sans-serif;">
            <div style="text-align:center;padding:40px;background:#111118;border:1px solid #1f2937;border-radius:16px;max-width:420px;">
              <div style="width:42px;height:42px;margin:0 auto 16px;border-radius:12px;border:1px solid #7f1d1d;display:grid;place-items:center;color:#f87171;"><svg viewBox="0 0 24 24" style="width:24px;height:24px;stroke:currentColor;fill:none;stroke-width:2"><path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12" y2="17"/></svg></div>
              <h2 style="color:#f87171;font-size:18px;margin:0 0 12px">Servidor ARKHON no responde</h2>
              <p style="color:#9ca3af;font-size:13px;line-height:1.6;margin:0 0 20px">
                No se pudo conectar al servidor en el puerto 3001 después de varios intentos.<br><br>
                Verifica que ARKHON Monitor esté en ejecución y vuelve a intentarlo.
              </p>
              <button onclick="sessionStorage.removeItem('arkhon_reload_count');location.reload()" 
                style="background:#6366f1;color:#fff;border:none;border-radius:8px;padding:10px 24px;font-size:13px;font-weight:700;cursor:pointer;">
                Reintentar
              </button>
            </div>
          </div>`;
        return;
      }
      sessionStorage.setItem('arkhon_reload_count', String(reloadCount + 1));
      setTimeout(() => window.location.reload(), 3000);
      return;
    }
  }

  // ── 3. Aplicar info de usuario en topbar ──────────────────────────────────
  if (savedNombre && savedRol) {
    const ROL_COLORS = { dueno:'#f97316', gerente:'#3b82f6', aux:'#a855f7' };
    const ROL_LABELS = { dueno:'Dueño', gerente:'Gerente', aux:'Aux. Contable' };
    const color = ROL_COLORS[savedRol] || '#6b7280';
    const label = ROL_LABELS[savedRol] || savedRol;

    // Inyectar chip de usuario en topbar
    const topRight = document.querySelector('.topbar-right');
    if (topRight) {
      if (!document.getElementById('profile-open-btn')) {
        const profileBtn = document.createElement('button');
        profileBtn.id = 'profile-open-btn';
        profileBtn.className = 'profile-topbar-btn';
        profileBtn.type = 'button';
        profileBtn.title = 'Editar mi perfil';
        profileBtn.innerHTML = `
          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
          <span>Mi perfil</span>
        `;
        profileBtn.onclick = openProfileModal;
        topRight.insertBefore(profileBtn, topRight.firstChild);
      }
      const chip = document.createElement('div');
      chip.id = 'user-chip';
      chip.style.cssText = `display:flex;align-items:center;gap:6px;padding:5px 10px;background:${color}18;border:1px solid ${color}40;border-radius:8px;cursor:pointer;font-size:11px;font-weight:700;color:${color};position:relative;`;
      chip.innerHTML = `
        <svg viewBox="0 0 24 24" style="width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2.2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
        <span>${savedNombre}</span>
        <span style="opacity:.6;font-weight:500">· ${label}</span>
      `;
      chip.title = 'Abrir perfil';
      chip.onclick = openProfileModal;
      topRight.insertBefore(chip, topRight.firstChild);
    }

    // ── 4. Aplicar restricciones de permisos ─────────────────────────────────
    let permisos = {};
    try { permisos = JSON.parse(savedPerms || '{}'); } catch(_) {}
    const hasEngineeringAccess = Array.isArray(permisos)
      ? permisos.includes('engineering.access')
      : permisos && permisos['engineering.access'] === true;
    const engineeringBtn = document.querySelector('[data-tab="arkhon-engineering"]');
    if (engineeringBtn) engineeringBtn.hidden = !hasEngineeringAccess;

    // Si el rol es dueño → acceso total, sin restricciones
    if (savedRol !== 'dueno') {
      aplicarPermisos(permisos, savedRol);
    }
  }

  const hoy = new Date();
  const p2  = n => String(n).padStart(2, '0');
  fechaDesde = fechaHasta = `${hoy.getFullYear()}-${p2(hoy.getMonth() + 1)}-${p2(hoy.getDate())}`;
  fecha = fechaHasta;

  cargarDatos();
  checkRuntimeUpdateNotification();
})();

// ── Cerrar sesión ─────────────────────────────────────────────────────────────
async function cerrarSesion() {
  if (!confirm('¿Cerrar sesión?')) return;
  try {
    await fetch('/api/auth/logout', { method: 'POST', headers: { 'X-Api-Token': LOCAL_API_KEY } });
  } catch(_) {}
  sessionStorage.clear();
  window.location.href = '/login';
}

// ── Aplicar restricciones de permisos al UI ───────────────────────────────────
function aplicarPermisos(permisos, rol) {
  // Mapa de permiso → tabs/botones a ocultar si el permiso es false
  const PERM_MAP = {
    // Si no tiene permiso de admin → quitar acceso a panel de Administración
    admin:        () => {
      ['configuracion'].forEach(tab => {
        const btn = document.querySelector('[data-tab="' + tab + '"]');
        if(btn) btn.style.display='none';
      });
    },
    // Si no tiene permiso de reportes → quitar acceso a Reportes
    reportes:     () => { const btn = document.querySelector('[data-tab="reportes"]'); if(btn) btn.style.display='none'; },
    // Si no tiene permiso de análisis → quitar tab
    analisis:     () => { const btn = document.querySelector('[data-tab="graficas"]'); if(btn) btn.style.display='none'; },
    // Sin permiso de meseros → quitar tab
    meseros:      () => { const btn = document.querySelector('[data-tab="meseros"]'); if(btn) btn.style.display='none'; },
    // Sin permiso de turnos → quitar tab
    turnos:       () => { const btn = document.querySelector('[data-tab="turnos"]'); if(btn) btn.style.display='none'; },
    // Sin permiso de cancelaciones → sin acceso al módulo
    cancelaciones:() => {
      // Ocultarlo del menú de reportes dinámicamente cuando se abra
      window._perm_cancelaciones = false;
    },
    // Sin permiso de corte Z
    corte_z:      () => { window._perm_corte_z = false; },
    // Sin permiso de movimientos de caja
    caja:         () => { window._perm_caja = false; },
  };

  for (const [perm, fn] of Object.entries(PERM_MAP)) {
    if (permisos[perm] === false) {
      try { fn(); } catch(_) {}
    }
  }

  // P3-D FIX: Usar defineProperty con getter en lugar de envolver en el momento de ejecución.
  // Antes: si openReporteModule no existía aún cuando se llamaba aplicarPermisos(), el wrapper
  // nunca se instalaba. Ahora: el getter intercepta SIEMPRE la llamada, sin importar cuándo
  // se defina la función original.
  const _existingOpenReporteModule = typeof window.openReporteModule === 'function'
    ? window.openReporteModule
    : null;
  const _wrapOpenReporteModule = fn => function(key) {
    const BLOCKED = [];
    if (window._perm_cancelaciones === false) BLOCKED.push('cancelaciones');
    if (window._perm_corte_z       === false) BLOCKED.push('corte-z');
    if (window._perm_caja          === false) BLOCKED.push('depositos-efectivo');
    if (BLOCKED.includes(key)) {
      alert('No tienes permiso para acceder a este módulo.');
      return;
    }
    return fn(key);
  };
  let _origOpen = _existingOpenReporteModule ? _wrapOpenReporteModule(_existingOpenReporteModule) : null;
  Object.defineProperty(window, 'openReporteModule', {
    configurable: true,
    get() { return _origOpen; },
    set(fn) {
      // Cada vez que alguien asigne openReporteModule, envolvemos la nueva función
      _origOpen = typeof fn === 'function' ? _wrapOpenReporteModule(fn) : fn;

    },
  });
}

function profileStatus(message, type = '') {
  const el = document.getElementById('profile-status');
  if (!el) return;
  el.className = 'profile-status ' + type;
  el.textContent = message || '';
}

function openProfileModal() {
  const modal = document.getElementById('profile-modal');
  if (!modal) return;
  const nameInput = document.getElementById('profile-name');
  const sub = document.getElementById('profile-modal-sub');
  if (nameInput) nameInput.value = sessionStorage.getItem('arkhon_nombre') || '';
  if (sub) {
    const user = sessionStorage.getItem('arkhon_rol') || '';
    sub.textContent = user ? `Cuenta ${user}` : 'Cuenta de usuario';
  }
  ['profile-current-password', 'profile-new-password', 'profile-confirm-password'].forEach(id => {
    const el = document.getElementById(id);
    if (el) el.value = '';
  });
  profileStatus('');
  modal.classList.add('open');
}

function closeProfileModal() {
  const modal = document.getElementById('profile-modal');
  if (modal) modal.classList.remove('open');
}

async function saveProfile() {
  const name = document.getElementById('profile-name')?.value.trim() || '';
  const currentPassword = document.getElementById('profile-current-password')?.value || '';
  const newPassword = document.getElementById('profile-new-password')?.value || '';
  const confirmPassword = document.getElementById('profile-confirm-password')?.value || '';
  if (!name) return profileStatus('El nombre no puede quedar vacio.', 'err');
  if (newPassword || confirmPassword) {
    if (newPassword !== confirmPassword) return profileStatus('La confirmacion no coincide.', 'err');
    if (!currentPassword) return profileStatus('Ingresa tu contrasena actual para cambiarla.', 'err');
  }
  profileStatus('Guardando...');
  try {
    const response = await fetch('/api/security/me', {
      method: 'PUT',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'X-Api-Token': LOCAL_API_KEY,
      },
      body: JSON.stringify({ nombre: name, current_password: currentPassword, password: newPassword }),
    });
    const data = await response.json();
    if (!response.ok || !data.ok) throw new Error(data.error || 'No se pudo guardar el perfil.');
    sessionStorage.setItem('arkhon_nombre', data.user?.nombre || name);
    const chip = document.getElementById('user-chip');
    const label = chip?.querySelector('span');
    if (label) label.textContent = data.user?.nombre || name;
    profileStatus('Perfil actualizado.', 'ok');
    document.getElementById('profile-current-password').value = '';
    document.getElementById('profile-new-password').value = '';
    document.getElementById('profile-confirm-password').value = '';
  } catch (error) {
    profileStatus(error.message, 'err');
  }
}

function notifyRuntimeUpdateAvailable(info) {
  const version = info?.version_disponible || info?.manifest?.version || '';
  if (!version || !info?.hay_actualizacion || info?.manifest?.type !== 'runtime-zip') return;
  const key = `arkhon_update_available_notified_${version}`;
  try {
    if (localStorage.getItem(key) === '1') return;
    localStorage.setItem(key, '1');
  } catch (_) {}
  const notification = {
    id: `runtime-update-${version}`,
    eventId: `runtime-update-${version}`,
    type: 'actualizacion_disponible',
    title: 'Nueva version disponible',
    body: `ARKHON Monitor ${version} esta listo para instalarse.`,
    url: '/admin?tab=actualizaciones',
    priority: 'alta',
    createdAt: new Date().toISOString(),
    data: {
      version,
      installedVersion: info.version_actual || '',
      manifest: info.manifest || {},
    },
  };
  if (window.arkhonNotify && typeof window.arkhonNotify.handleServerEvent === 'function') {
    window.arkhonNotify.handleServerEvent(notification);
  } else if (typeof window.arkhonToast === 'function') {
    window.arkhonToast(notification.title, notification.body, 'info');
  }
}

async function checkRuntimeUpdateNotification() {
  try {
    const lastCheck = Number(localStorage.getItem('arkhon_update_available_last_check') || 0);
    if (lastCheck && Date.now() - lastCheck < 30 * 60 * 1000) return;
    localStorage.setItem('arkhon_update_available_last_check', String(Date.now()));
    const res = await fetch('/api/actualizador/estado', {
      headers: { 'X-Api-Token': LOCAL_API_KEY },
      credentials: 'include',
    });
    if (!res.ok) return;
    const info = await res.json();
    notifyRuntimeUpdateAvailable(info);
  } catch (_) {}
}
