<?php
$title = 'Dashboard - ESP Admin';
ob_start();
?>

<!-- Header -->
<div class="mb-6">
  <div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
    <div>
      <h1 class="text-3xl font-bold text-slate-900 flex items-center gap-2">
        <svg class="w-8 h-8 text-emerald-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
        </svg>
        Dashboard
      </h1>
      <p id="device-title" class="text-slate-600 mt-1">Cargando información del dispositivo...</p>
    </div>
    <a href="/" class="inline-flex items-center gap-2 px-4 py-2.5 text-sm font-semibold rounded-lg bg-white text-slate-700 hover:bg-slate-50 border-2 border-slate-200 shadow-sm transition-all">
      <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
      </svg>
      Volver
    </a>
  </div>
</div>

<!-- Contenedor principal -->
<div class="space-y-6">
  <!-- Cards de Estado -->
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
    <!-- Estado de Conexión -->
    <div class="bg-white rounded-xl border-2 border-slate-200 p-6 shadow-sm hover:shadow-md transition-all">
      <div class="flex items-center justify-between mb-4">
        <h3 class="text-lg font-semibold text-slate-900">Estado</h3>
        <svg class="w-6 h-6 text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
        </svg>
      </div>
      <div class="flex items-center gap-3">
        <span id="connection-status" class="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-semibold rounded-full bg-slate-100 text-slate-700">
          <span class="w-2 h-2 rounded-full bg-slate-400"></span>
          Verificando...
        </span>
      </div>
      <div class="mt-4 text-sm text-slate-600">
        <span class="font-medium">IP:</span> <span id="device-ip" class="font-mono">Cargando...</span>
      </div>
    </div>

    <!-- Última Actividad -->
    <div class="bg-white rounded-xl border-2 border-slate-200 p-6 shadow-sm hover:shadow-md transition-all">
      <div class="flex items-center justify-between mb-4">
        <h3 class="text-lg font-semibold text-slate-900">Actividad</h3>
        <svg class="w-6 h-6 text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
        </svg>
      </div>
      <div class="text-2xl font-bold text-slate-900" id="last-activity">-</div>
      <div class="mt-2 text-sm text-slate-600">Última actualización</div>
    </div>

    <!-- Acciones Rápidas -->
    <div class="bg-white rounded-xl border-2 border-slate-200 p-6 shadow-sm hover:shadow-md transition-all">
      <div class="flex items-center justify-between mb-4">
        <h3 class="text-lg font-semibold text-slate-900">Acciones</h3>
        <svg class="w-6 h-6 text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
        </svg>
      </div>
      <div class="space-y-2">
        <button id="btn-refresh" class="w-full inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-lg bg-emerald-600 text-white hover:bg-emerald-700 transition-all">
          <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
          </svg>
          Actualizar
        </button>
        <button id="btn-reboot" class="w-full inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-lg bg-white text-red-600 hover:bg-red-50 border-2 border-red-200 transition-all">
          <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
          </svg>
          Reiniciar
        </button>
      </div>
    </div>
  </div>

  <!-- Estados de Pines -->
  <div class="bg-white rounded-xl border-2 border-slate-200 shadow-sm overflow-hidden">
    <div class="px-6 py-4 border-b border-slate-200 bg-gradient-to-r from-emerald-50 to-emerald-100">
      <h2 class="text-lg font-bold text-slate-900 flex items-center gap-2">
        <svg class="w-5 h-5 text-emerald-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
        </svg>
        Estados de Pines
      </h2>
      <p class="text-xs text-slate-600 mt-1">Actualización en tiempo real</p>
    </div>
    <div class="p-6">
      <div id="pins-status" class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 gap-3">
        <div class="text-center text-slate-500 col-span-full py-4">Cargando estados de pines...</div>
      </div>
    </div>
  </div>

  <!-- Controles Rapidos -->
  <div class="bg-white rounded-xl border-2 border-slate-200 shadow-sm overflow-hidden">
    <div class="px-6 py-4 border-b border-slate-200 bg-gradient-to-r from-blue-50 to-blue-100">
      <h2 class="text-lg font-bold text-slate-900 flex items-center gap-2">
        <svg class="w-5 h-5 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
        </svg>
        Controles Rapidos
      </h2>
      <p class="text-xs text-slate-600 mt-1">Control manual de salidas</p>
    </div>
    <div class="p-6">
      <div id="quick-controls" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
        <div class="text-center text-slate-500 col-span-full py-4">Cargando controles...</div>
      </div>
    </div>
  </div>

  <!-- Botones de Acción Adicionales -->
  <div class="flex flex-wrap gap-3">
    <button id="btn-config-ports" class="inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium rounded-lg bg-white text-blue-600 hover:bg-blue-50 border-2 border-blue-200 transition-all">
      <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
      </svg>
      Configurar Puertos
    </button>

    <button id="btn-mqtt" class="inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium rounded-lg bg-white text-purple-600 hover:bg-purple-50 border-2 border-purple-200 transition-all">
      <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
      </svg>
      Ver Info MQTT
    </button>
  </div>
</div>

<!-- Modal MQTT -->
<div id="mqttModal" class="fixed inset-0 z-50 hidden" aria-hidden="true">
  <div id="mqttModalOverlay" class="absolute inset-0 bg-black/40"></div>
  <div class="relative mx-auto mt-24 w-11/12 max-w-2xl">
    <div class="bg-white rounded-lg shadow-lg overflow-hidden">
      <div class="flex items-center justify-between px-4 py-2 border-b border-gray-200">
        <h3 class="text-lg font-semibold">Información MQTT</h3>
        <button id="mqttModalClose" class="inline-flex items-center justify-center w-8 h-8 rounded hover:bg-gray-100" aria-label="Cerrar">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
        </button>
      </div>
      <div class="p-4">
        <pre id="mqttJson" class="text-sm bg-gray-50 p-3 rounded border border-gray-200 overflow-auto max-h-96">{}</pre>
      </div>
      <div class="flex justify-end gap-2 px-4 py-3 border-t border-gray-200">
        <button id="mqttModalClose2" class="inline-flex items-center px-3 py-1.5 text-sm font-medium rounded border border-gray-300 text-gray-700 hover:bg-gray-50">Cerrar</button>
      </div>
    </div>
  </div>
  </div>

<script>
const urlParams = new URLSearchParams(window.location.search);
let chipid = urlParams.get('chipid');
if (chipid) chipid = String(chipid).trim().toUpperCase();

if (!chipid) {
  document.getElementById('device-info').innerHTML = '<div class="alert alert-danger">Error: No se especificó un ChipID en la URL.</div>';
  throw new Error('Falta el parámetro chipid');
}

let deviceData = {};
let pinsData = {};
let lastUpdateTime = null;
let lastKnownIP = null;

// Estados actuales por chipid
const estadosDispositivos = {};
// Estado conocido de cada pin ("ON"|"OFF"|otro)
const pinStates = {};
// Pines en tiempo real
const pinesEstados = {};
const pendingPinCommands = {};

// Comparación de chipid insensible a mayúsculas/minúsculas
function sameChip(a, b) {
  if (!a || !b) return false;
  return String(a).trim().toLowerCase() === String(b).trim().toLowerCase();
}

function isPinOn(valor) {
  const v = String(normalizePinValue(valor) || '').toLowerCase().trim();
  return v === 'on' || v === '1' || v === 'true' || v === 'high';
}

function normalizePinValue(valor) {
  if (valor && typeof valor === 'object') {
    if (Object.prototype.hasOwnProperty.call(valor, 'valor')) return valor.valor;
    if (Object.prototype.hasOwnProperty.call(valor, 'value')) return valor.value;
  }
  return valor;
}

function setSwitchVisual(switchEl, isOn, options) {
  if (!switchEl) return;
  const opts = options || {};
  const card = switchEl.closest('.quick-control-card') || switchEl.closest('.bg-white');
  const root = card || switchEl.closest('label') || switchEl.parentElement;
  const label = root ? root.querySelector('.state-label') : null;
  const track = root ? root.querySelector('.switch-track') : null;
  const thumb = root ? root.querySelector('.switch-thumb') : null;
  const icon = card ? card.querySelector('svg') : null;
  const stateColor = opts.pending ? 'text-amber-700' : (isOn ? 'text-emerald-700' : 'text-red-700');
  const trackColor = opts.pending ? 'bg-amber-500' : (isOn ? 'bg-emerald-500' : 'bg-red-500');

  switchEl.checked = !!isOn;

  if (label) {
    label.textContent = isOn ? 'ON' : 'OFF';
    label.className = `state-label text-sm font-medium ${stateColor}`;
  }

  if (track) {
    track.className = `switch-track relative w-14 h-8 rounded-full transition-colors duration-300 ${trackColor}`;
    if (opts.pulse) {
      track.classList.add('animate-pulse');
      setTimeout(() => track.classList.remove('animate-pulse'), 300);
    }
  }

  if (thumb) {
    thumb.className = `switch-thumb absolute left-1 top-1 w-6 h-6 bg-white rounded-full shadow-md transition-transform duration-300 ${isOn ? 'translate-x-6' : 'translate-x-0'}`;
  }

  if (icon) {
    icon.className = `w-5 h-5 ${isOn ? 'text-emerald-500' : 'text-slate-400'}`;
  }
}

function clearPendingPin(pin) {
  const pending = pendingPinCommands[pin];
  if (!pending) return null;
  clearTimeout(pending.timer);
  delete pendingPinCommands[pin];
  return pending;
}

function confirmPendingPin(pin, valor) {
  const pending = pendingPinCommands[pin];
  if (!pending) return;

  const received = isPinOn(normalizePinValue(valor)) ? 'ON' : 'OFF';
  if (received !== pending.expected) return;

  clearPendingPin(pin);
  const sw = document.querySelector(`.switch-pin[data-pin="${pin}"]`) || pending.switchEl;
  if (sw) {
    setSwitchVisual(sw, pending.expected === 'ON');
    sw.disabled = false;
  }
  mostrarToast(`${pin} confirmado ${pending.expected}`, { type: 'success', delay: 1800 });
}

function failPendingPin(pin, message) {
  const pending = clearPendingPin(pin);
  if (!pending) return;

  const sw = document.querySelector(`.switch-pin[data-pin="${pin}"]`) || pending.switchEl;
  if (sw) {
    setSwitchVisual(sw, pending.previous === 'ON', { pulse: true });
    sw.disabled = false;
  }
  if (!pinesEstados[chipid]) pinesEstados[chipid] = {};
  pinesEstados[chipid][pin] = pending.previous;
  let toastMessage = message || `No se pudo enviar comando a ${pin}`;
  if (String(toastMessage).indexOf('WebSocket JSON') !== -1) {
    toastMessage = `Comando enviado, pero ${pin} no confirmo ${pending.expected} en valores/${pin}. El dispositivo sigue reportando otro estado.`;
  }
  mostrarToast(toastMessage, { type: 'danger', delay: 5000 });
}

function updateConnectionStatus(estado) {
  const statusElement = document.getElementById('connection-status');
  if (estado === 'online') {
    statusElement.innerHTML = '<span class="w-2 h-2 rounded-full bg-emerald-500 animate-pulse"></span> Online';
    statusElement.className = 'inline-flex items-center gap-2 px-3 py-1.5 text-sm font-semibold rounded-full bg-emerald-100 text-emerald-700';
  } else if (estado === 'offline') {
    statusElement.innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500"></span> Offline';
    statusElement.className = 'inline-flex items-center gap-2 px-3 py-1.5 text-sm font-semibold rounded-full bg-red-100 text-red-700';
  } else {
    statusElement.innerHTML = '<span class="w-2 h-2 rounded-full bg-slate-400"></span> Desconocido';
    statusElement.className = 'inline-flex items-center gap-2 px-3 py-1.5 text-sm font-semibold rounded-full bg-slate-100 text-slate-700';
  }
}

function updateLastActivity() {
  const element = document.getElementById('last-activity');
  if (lastUpdateTime) {
    const now = new Date();
    const diff = Math.floor((now - lastUpdateTime) / 1000);
    
    if (diff < 10) {
      element.textContent = 'Ahora mismo';
    } else if (diff < 60) {
      element.textContent = `Hace ${diff} segundos`;
    } else if (diff < 3600) {
      const minutes = Math.floor(diff / 60);
      element.textContent = `Hace ${minutes} minuto${minutes !== 1 ? 's' : ''}`;
    } else if (diff < 86400) {
      const hours = Math.floor(diff / 3600);
      element.textContent = `Hace ${hours} hora${hours !== 1 ? 's' : ''}`;
    } else {
      const days = Math.floor(diff / 86400);
      element.textContent = `Hace ${days} día${days !== 1 ? 's' : ''}`;
    }
  } else {
    element.textContent = 'Sin datos';
  }
}

function loadDeviceInfo() {
  api.get('/api/get_dispositivos').then(data => {
    const deviceKey = Object.keys(data || {}).find(key => sameChip(key, chipid));
    if (deviceKey) {
      deviceData = data[deviceKey];
      document.getElementById('device-title').innerHTML = 
        `<strong>${deviceData.tag}</strong> (${deviceData.chipid}) - ${deviceData.ciudad}, ${deviceData.sector}`;
      const ipEl = document.getElementById('device-ip');
      if (ipEl) {
        ipEl.textContent = lastKnownIP || deviceData.ip || 'No disponible';
      }
      
      // Configurar botón a puertos
      (function(){
        const btn = document.getElementById('btn-config-ports');
        if (btn) {
          btn.onclick = function(){ window.location.href = `/puertos?chipid=${chipid}`; };
          btn.disabled = false;
        }
      })();
      
      // Estado inicial: usar API como fallback
      updateConnectionStatus(deviceData.online ? 'online' : 'offline');
      if (deviceData.pines && typeof deviceData.pines === 'object') {
        updateDispositivoPines(chipid, deviceData.pines);
        Object.keys(deviceData.pines).forEach(pin => updatePinStatus(pin, deviceData.pines[pin]));
      }
    } else {
      document.getElementById('device-info').innerHTML = 
        '<div class="alert alert-warning">Dispositivo no encontrado en el registro.</div>';
    }
  }).catch(err => {
    console.error('Error cargando dispositivo:', err);
    document.getElementById('device-info').innerHTML = 
      '<div class="alert alert-danger">Error al cargar información del dispositivo.</div>';
  });
}

function loadPinsStatus() {
  api.get('/api/get_puertos', { chipid: chipid }).then(data => {
    if (data && !data.error) {
      pinsData = data;
      renderPinsStatus();
      renderQuickControls();
      
      // Forzar sincronización inicial: solicitar estado actual si no hay datos
      setTimeout(() => {
        Object.keys(pinsData).forEach(pin => {
          if (pin === 'update') return;
          const p = pinsData[pin];
          if (p.modo === 'OUTPUT') {
            // El estado inicial llega por MQTT WebSocket.
          }
        });
      }, 500);
      
      // Re-render leve luego para aplicar estados iniciales
      setTimeout(renderQuickControls, 800);
    } else {
      document.getElementById('pins-status').innerHTML = 
        '<div class="col-12"><div class="alert alert-info">No hay configuración de puertos para este dispositivo.</div></div>';
    }
  }).catch(err => {
    console.error('Error cargando pines:', err);
    document.getElementById('pins-status').innerHTML = 
      '<div class="col-12"><div class="alert alert-danger">Error al cargar estados de pines.</div></div>';
  });
}

function renderPinsStatus() {
  let html = '';
  for (let pin in pinsData) {
    if (pin === 'update') continue;
    const p = pinsData[pin];
    const modo = p.modo || '';
    
    // Estilo inicial según modo
    let badgeCls = 'bg-slate-100 text-slate-700 border-slate-200';
    let badgeText = 'Sin datos';
    let iconColor = 'text-slate-400';
    
    if (modo === 'OUTPUT') { 
      badgeCls = 'bg-amber-100 text-amber-700 border-amber-200'; 
      badgeText = 'Salida'; 
      iconColor = 'text-amber-500';
    } else if (modo === 'INPUT' || modo === 'INPUT_PULLUP') { 
      badgeCls = 'bg-blue-100 text-blue-700 border-blue-200'; 
      badgeText = 'Entrada'; 
      iconColor = 'text-blue-500';
    }

    html += `
      <div class="bg-white rounded-lg border-2 border-slate-200 p-4 hover:shadow-md hover:-translate-y-0.5 transition-all duration-300">
        <div class="flex items-center justify-between mb-2">
          <span class="font-mono text-sm font-bold text-slate-900">${pin}</span>
          <svg class="w-4 h-4 ${iconColor}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
          </svg>
        </div>
        <span class="pin-status inline-flex items-center justify-center w-full px-2 py-1 text-xs font-semibold rounded-md border-2 ${badgeCls}" data-pin="${pin}">${badgeText}</span>
        <div class="mt-2 text-xs text-slate-600 text-center truncate" title="${p.disp || 'Sin asignar'}">${p.disp || 'Sin asignar'}</div>
      </div>`;
  }
  document.getElementById('pins-status').innerHTML = html;
}

function updatePinStatus(pin, valor) {
  const badge = document.querySelector(`.pin-status[data-pin="${pin}"]`);
  const prev = String(pinStates[pin] || '');
  const normalizedInput = normalizePinValue(valor);
  const v = String(normalizedInput || '').toLowerCase().trim();
  const isOn = isPinOn(normalizedInput);
  const normalizedValue = isOn ? 'ON' : 'OFF';
  
  console.log(`updatePinStatus: ${pin}="${valor}" -> normalized="${normalizedValue}" (${isOn})`); // Debug
  
  if (badge) {
    const base = 'pin-status inline-flex items-center justify-center w-full px-2 py-1 text-xs font-semibold rounded-md border-2';
    let variant = 'bg-slate-100 text-slate-700 border-slate-200';
    if (isOn) variant = 'bg-emerald-100 text-emerald-700 border-emerald-300';
    else if (!isOn && v !== '') variant = 'bg-red-100 text-red-700 border-red-300';
    badge.className = base + ' ' + variant;
    badge.textContent = isOn ? 'ON' : 'OFF';
  }
  
  // Guardar estado normalizado y reflejar en el switch si existe
  pinStates[pin] = normalizedValue;
  const sw = document.querySelector(`.switch-pin[data-pin="${pin}"]`);
  if (sw) {
    console.log(`Setting switch ${pin} checked=${isOn}`); // Debug
    setSwitchVisual(sw, isOn, { pulse: prev !== normalizedValue });
  }
}

function renderQuickControls() {
  const container = document.getElementById('quick-controls');
  if (!container) return;
  

  
  // Verificar si ya hay controles, entonces solo actualizar estados
  const existingSwitches = container.querySelectorAll('.switch-pin');
  if (existingSwitches.length > 0) {
    // Solo actualizar estados de switches existentes
    existingSwitches.forEach(switchEl => {
      const pin = switchEl.dataset.pin;
      const pinValue = (pinesEstados[chipid] && pinesEstados[chipid][pin]) || 'OFF'; // Estado dinámico
      if (pendingPinCommands[pin]) {
        setSwitchVisual(switchEl, pendingPinCommands[pin].expected === 'ON', { pending: true });
      } else {
        setSwitchVisual(switchEl, isPinOn(pinValue));
      }
    });
    
    return; // No reconstruir el HTML
  }
  
  // Primera vez: construir HTML completo
  let html = '';
  for (let pin in pinsData) {
    if (pin === 'update') continue;
    const p = pinsData[pin];
    
    if (p.modo === 'OUTPUT' && p.disp) {
      const pinValue = (pinesEstados[chipid] && pinesEstados[chipid][pin]) || 'OFF'; // Usar estado dinámico
      const isOn = isPinOn(pinValue);
      const notas = p.notas ? `<div class="text-xs text-slate-600 italic mb-2">${p.notas}</div>` : '';
      
      html += `
        <div class="quick-control-card bg-white rounded-lg border-2 border-slate-200 p-4 hover:shadow-md transition-all">
          <div class="flex items-center justify-between mb-3">
            <div class="flex-1">
              <div class="font-semibold text-slate-900">${p.disp}</div>
              <div class="text-xs text-slate-500 font-mono">${pin}</div>
            </div>
            <svg class="w-5 h-5 ${isOn ? 'text-emerald-500' : 'text-slate-400'}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
            </svg>
          </div>
          ${notas}
          <label class="flex items-center justify-between cursor-pointer select-none">
            <span class="state-label text-sm font-medium ${isOn ? 'text-emerald-700' : 'text-red-700'}">${isOn ? 'ON' : 'OFF'}</span>
            <div class="relative inline-flex items-center">
              <input class="switch-pin absolute opacity-0 w-0 h-0" type="checkbox" data-pin="${pin}" ${isOn ? 'checked' : ''}>
              <div class="switch-track relative w-14 h-8 rounded-full transition-colors duration-300 ${isOn ? 'bg-emerald-500' : 'bg-red-500'}">
                <div class="switch-thumb absolute left-1 top-1 w-6 h-6 bg-white rounded-full shadow-md transition-transform duration-300 ${isOn ? 'translate-x-6' : 'translate-x-0'}"></div>
              </div>
            </div>
          </label>
        </div>`;
    }
  }
  
  if (html === '') {
    html = '<div class="col-span-full text-center text-slate-500 py-8">No hay salidas configuradas para controlar.</div>';
  }
  
  container.innerHTML = html;
}

function refreshDashboard() {
  loadDeviceInfo();
  loadPinsStatus();
  mostrarToast('Dashboard actualizado');
}



// Construir objeto de información MQTT (desde estado y config de pines)
function buildMqttInfo() {
  try {
    const estado = deviceData && deviceData.online ? 'online' : 'offline';
    const info = {
      chipid: chipid,
      estado: estado,
      ip: lastKnownIP || '',
      firmware: (deviceData && deviceData.firmware) ? String(deviceData.firmware) : null,
      pines: {}
    };
    // Combinar config de pines con estado ON/OFF si se conoce
    Object.keys(pinsData || {}).forEach(function(pin){
      if (pin === 'update') return;
      const p = pinsData[pin] || {};
      info.pines[pin] = {
        disp: p.disp || null,
        modo: p.modo || null,
        estado: (pinesEstados[chipid] && pinesEstados[chipid][pin]) || null
      };
    });
    return info;
  } catch(e) {
    return { error: true, message: 'No se pudo construir la información', detail: String(e) };
  }
}

// Event listeners
document.getElementById('btn-reboot').addEventListener('click', function() {
  if (!confirm(`¿Confirmas reiniciar el dispositivo ${chipid}?`)) return;
  
  const topic = `dispositivo/${chipid}/comando/reboot`;
  const payload = '1';
  
  const publisher = window.mqttRealtime
    ? window.mqttRealtime.publish(topic, payload)
    : api.postJSON('/api/mqtt_publish', { topic, payload });

  publisher
    .then(function(resp) {
      mostrarToast(`Comando de reinicio enviado al dispositivo ${chipid}.`);
      document.getElementById('btn-reboot').disabled = true;
    })
    .catch(function(err) {
      mostrarToast('Error al enviar el comando de reinicio.');
      console.error(err);
    });
});

document.getElementById('btn-refresh').addEventListener('click', refreshDashboard);

// Modal MQTT: abrir/cerrar y pintar JSON
document.getElementById('btn-mqtt').addEventListener('click', function(){
  try {
    const modal = document.getElementById('mqttModal');
    const pre = document.getElementById('mqttJson');
    const data = buildMqttInfo();
    pre.textContent = JSON.stringify(data, null, 2);
    modal.classList.remove('hidden');
  } catch(e) { console.error(e); }
});



function closeMqttModal(){
  const modal = document.getElementById('mqttModal');
  if (modal) modal.classList.add('hidden');
}

document.getElementById('mqttModalClose').addEventListener('click', closeMqttModal);
document.getElementById('mqttModalClose2').addEventListener('click', closeMqttModal);
document.getElementById('mqttModalOverlay').addEventListener('click', closeMqttModal);

// Control de pines con switch (ON/OFF vía MQTT) - Delegación de eventos
document.addEventListener('change', function(e) {
  const switchPin = e.target.closest('.switch-pin');
  if (!switchPin) return;

  const pin = switchPin.dataset.pin;
  const checked = switchPin.checked;
  const action = checked ? 'ON' : 'OFF';
  const prevAction = checked ? 'OFF' : 'ON';
  switchPin.disabled = true;

  // Feedback visual mínimo mientras llega la confirmación por MQTT.
  const label = switchPin.closest('label')?.querySelector('.state-label');
  const track = switchPin.closest('label')?.querySelector('.switch-track');
  if (label) label.textContent = action;
  if (track) {
    track.className = 'switch-track relative w-14 h-8 rounded-full transition-colors duration-300 bg-amber-500';
    track.classList.add('animate-pulse');
  }
  setSwitchVisual(switchPin, checked, { pending: true, pulse: true });
  clearPendingPin(pin);
  pendingPinCommands[pin] = {
    expected: action,
    previous: prevAction,
    switchEl: switchPin,
    timer: setTimeout(function() {
      failPendingPin(pin, `No se confirmó el envío a ${pin}. Revisá la conexión WebSocket JSON o el estado del dispositivo.`);
    }, 6000)
  };
  
  console.log(`Switch clicked: ${pin} -> ${action}`); // Debug
  
  const topic = `dispositivo/${chipid}/comando`;
  const payload = { alias: String(pin), valor: String(action) };

  const publisher = window.mqttRealtime
    ? window.mqttRealtime.publish(topic, payload, { qos: 0, retain: true })
    : api.postJSON('/api/mqtt_publish', { topic, payload, qos: 0, retain: true });

  publisher
    .then(function() {
      console.log(`MQTT published: ${topic} -> ${JSON.stringify(payload)}`); // Debug log
      mostrarToast(`Enviando ${action} a ${pin}...`, { type: 'warning', delay: 1800 });
    })
    .catch(function(err) {
      const msg = (err.data && (err.data.message || err.data.msg)) || err.message || 'Error al enviar comando';
      failPendingPin(pin, msg);
      console.error('mqtt_publish error', err);
    });
});

function updateDispositivoPines(chipid, pines) {
  if (!pinesEstados[chipid]) pinesEstados[chipid] = {};
  Object.keys(pines || {}).forEach(function(pin) {
    pinesEstados[chipid][pin] = normalizePinValue(pines[pin]);
  });
  renderQuickControls(); // Re-renderizar controles
  Object.keys(pines || {}).forEach(pin => confirmPendingPin(pin, pines[pin]));
}

function isValueStateTopic(topic) {
  return /\/valores\/[^/]+$/.test('/' + String(topic || '').replace(/^\/+/, ''));
}

function refreshDashboard() {
  loadDeviceInfo();
  loadPinsStatus();
  mostrarToast('Dashboard actualizado');
}

// Inicialización
document.addEventListener('DOMContentLoaded', function() {
  loadDeviceInfo();
  loadPinsStatus();
  // Inicializar contador de actividad
  updateLastActivity();
  // Re-renderizar controles tras un breve tiempo para reflejar estados iniciales
  setTimeout(renderQuickControls, 1200);
  if (window.mqttRealtime) {
    window.mqttRealtime.onMessage(function(evt) {
      if (!sameChip(evt.chipid, chipid)) {
        console.debug('[Dashboard MQTT] evento ignorado', evt);
        return;
      }
      console.debug('[Dashboard MQTT] evento recibido', evt);

      if (evt.type === 'state') {
        if (deviceData) deviceData.online = evt.estado === 'online';
        updateConnectionStatus(evt.estado);
      }

      if (evt.type === 'ip') {
        lastKnownIP = evt.ip || lastKnownIP;
        const ipEl = document.getElementById('device-ip');
        if (ipEl && evt.ip) ipEl.textContent = evt.ip;
      }

      if (evt.type === 'pin') {
        if (!isValueStateTopic(evt.topic)) {
          console.debug('[Dashboard MQTT] comando publicado, esperando valores/<pin>', evt);
          return;
        }

        updateDispositivoPines(chipid, { [evt.alias]: evt.valor });
        updatePinStatus(evt.alias, evt.valor);
      }
    });
  }
});
</script>
<?php
$content = ob_get_clean();
// Si no se está renderizando como parcial, incluir el layout principal
if (!defined('RENDER_PARTIAL')) {
  include __DIR__ . '/../layouts/layout.php';
}
?>
