import React, { useState, useEffect, useCallback, useRef } from 'react';
import Layout from '../components/Layout';
import { useAuth } from '../context/AuthContext';
import { toast } from 'sonner';
import { Siren, Wifi, WifiOff, RefreshCw, Bell, BellRing, MapPin, ShieldAlert, BellOff, Volume2, Stethoscope } from 'lucide-react';
import { getMisDispositivos, toggleDispositivo, enviarSOS, testAlerta, getNotificaciones, marcarLeidas, getPreferencias, updatePreferencias, getVapidKey, pushSubscribe, getPublicConfig, getProfile, updateProfile, diagnosticoPush, guardarDiagnostico } from '../lib/api';

const SOUND_OPTIONS = [
  { value: 'clasico', label: 'Clasico' },
  { value: 'urgente', label: 'Urgente' },
  { value: 'sirena', label: 'Sirena' },
  { value: 'suave', label: 'Suave' },
  { value: 'silencio', label: 'Silencioso' },
];

function urlBase64ToUint8Array(base64String) {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
  const raw = window.atob(base64);
  const arr = new Uint8Array(raw.length);
  for (let i = 0; i < raw.length; ++i) arr[i] = raw.charCodeAt(i);
  return arr;
}

export default function PanelPage() {
  const { user } = useAuth();
  const isAdmin = ['admin', 'superadmin', 'gerente'].includes(user?.rol);
  const [dispositivos, setDispositivos] = useState([]);
  const [notificaciones, setNotificaciones] = useState([]);
  const [loading, setLoading] = useState(true);
  const [toggling, setToggling] = useState(null);
  const [sosLoading, setSosLoading] = useState(false);
  const [pushEnabled, setPushEnabled] = useState(false);
  const [selectedNotif, setSelectedNotif] = useState(null);
  const [userSound, setUserSound] = useState('clasico');
  const [canTest, setCanTest] = useState(false);
  const [testLoading, setTestLoading] = useState(false);
  const [longPressMs, setLongPressMs] = useState(800);
  const [sosLongPressMs, setSosLongPressMs] = useState(1200);
  const [pressProgress, setPressProgress] = useState({});
  const [sosProgress, setSosProgress] = useState(0);
  const [showNotifs, setShowNotifs] = useState(false);

  const cooldownRef = useRef(0);
  const prevNotifCountRef = useRef(0);
  const pressTimersRef = useRef({});
  const sosTimerRef = useRef(null);

  useEffect(() => {
    getPreferencias().then(d => { setUserSound(d.sonido || 'clasico'); setCanTest(!!d.puede_probar); }).catch(() => {});
    getPublicConfig().then(d => { if (d.long_press_ms) setLongPressMs(d.long_press_ms); if (d.sos_long_press_ms) setSosLongPressMs(d.sos_long_press_ms); }).catch(() => {});
    checkPushStatus();
  }, []);

  const checkPushStatus = async () => {
    if (!('serviceWorker' in navigator) || !('PushManager' in window)) return;
    try { const reg = await navigator.serviceWorker.ready; const sub = await reg.pushManager.getSubscription(); setPushEnabled(!!sub); } catch {}
  };

  const getGPS = () => new Promise((resolve) => {
    if (!navigator.geolocation) return resolve({ lat: null, lng: null });
    navigator.geolocation.getCurrentPosition(
      (pos) => resolve({ lat: pos.coords.latitude, lng: pos.coords.longitude }),
      () => resolve({ lat: null, lng: null }),
      { timeout: 5000, enableHighAccuracy: true }
    );
  });

  const loadDevices = useCallback(async () => {
    if (Date.now() < cooldownRef.current) return;
    try { const data = await getMisDispositivos(); if (Date.now() >= cooldownRef.current) setDispositivos(data); } catch {}
  }, []);

  const loadNotifs = useCallback(async () => {
    try { const data = await getNotificaciones(); setNotificaciones(data); } catch {}
  }, []);

  const loadAll = useCallback(async () => {
    await Promise.all([loadDevices(), loadNotifs()]);
    setLoading(false);
  }, [loadDevices, loadNotifs]);

  useEffect(() => { loadAll(); }, [loadAll]);

  useEffect(() => {
    const ni = setInterval(async () => {
      try {
        const nn = await getNotificaciones();
        if (nn.length > prevNotifCountRef.current && prevNotifCountRef.current >= 0) playAlertSound(userSound);
        prevNotifCountRef.current = nn.length;
        setNotificaciones(nn);
      } catch {}
    }, 5000);
    const di = setInterval(loadDevices, 15000);
    return () => { clearInterval(ni); clearInterval(di); };
  }, [loadDevices, userSound]);

  const playAlertSound = (sound) => {
    try { if (sound === 'silencio') return; const a = new Audio(`/sounds/alert-${sound || 'clasico'}.wav`); a.volume = 0.8; a.play().catch(() => {}); } catch {}
  };

  const requestPush = async () => {
    if (!('serviceWorker' in navigator) || !('PushManager' in window)) { toast.error('Navegador no soporta push'); return; }
    try {
      const perm = await Notification.requestPermission();
      if (perm !== 'granted') { toast.error('Permiso denegado'); return; }
      const reg = await navigator.serviceWorker.ready;
      const ex = await reg.pushManager.getSubscription();
      if (ex) await ex.unsubscribe();
      const { key } = await getVapidKey();
      if (!key) { toast.error('VAPID no configurado'); return; }
      const sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(key) });
      await pushSubscribe(sub.toJSON());
      setPushEnabled(true);
      toast.success('Push activado');
    } catch (e) { toast.error('Error push'); }
  };

  const saveSound = async (sound) => { setUserSound(sound); playAlertSound(sound); try { await updatePreferencias({ sonido: sound }); } catch {} };

  const startLongPress = (disp) => {
    if (toggling || !disp.online) return;
    if (pressTimersRef.current[disp.id]?.interval) return;
    const startAt = Date.now();
    pressTimersRef.current[disp.id] = { startAt, triggered: false };
    if (navigator.vibrate) navigator.vibrate(15);
    const interval = setInterval(() => {
      const elapsed = Date.now() - startAt;
      const progress = Math.min(100, (elapsed / longPressMs) * 100);
      setPressProgress(prev => ({ ...prev, [disp.id]: progress }));
      if (progress >= 100 && !pressTimersRef.current[disp.id]?.triggered) {
        pressTimersRef.current[disp.id].triggered = true;
        cancelLongPress(disp.id);
        if (navigator.vibrate) navigator.vibrate([100, 50, 100]);
        handleToggle(disp);
      }
    }, 30);
    pressTimersRef.current[disp.id].interval = interval;
  };

  const cancelLongPress = (devId) => {
    const t = pressTimersRef.current[devId]; if (t?.interval) clearInterval(t.interval);
    pressTimersRef.current[devId] = null; setPressProgress(prev => ({ ...prev, [devId]: 0 }));
  };

  const handleToggle = async (disp) => {
    if (toggling) return;
    const newAction = disp.switch ? 'off' : 'on';
    setToggling(disp.id);
    setDispositivos(prev => prev.map(d => d.id === disp.id ? { ...d, switch: newAction === 'on' } : d));
    cooldownRef.current = Date.now() + 15000;
    try {
      const coords = await getGPS();
      const data = await toggleDispositivo(disp.id, newAction, coords.lat, coords.lng);
      toast.success(data.message);
    } catch (e) {
      toast.error(e.message || 'Error');
      setDispositivos(prev => prev.map(d => d.id === disp.id ? { ...d, switch: !(newAction === 'on') } : d));
      cooldownRef.current = 0;
    } finally { setToggling(null); }
  };

  const handleSOS = async () => {
    setSosLoading(true);
    if (navigator.vibrate) navigator.vibrate([300, 100, 300, 100, 300]);
    try { const coords = await getGPS(); const d = await enviarSOS(coords.lat, coords.lng); toast.success(`SOS enviado a ${d.notificados} vecino(s)`); }
    catch (e) { toast.error(e.message || 'Error SOS'); }
    finally { setSosLoading(false); }
  };

  const startSosLongPress = () => {
    if (sosLoading || sosTimerRef.current) return;
    const startAt = Date.now(); sosTimerRef.current = { startAt, triggered: false };
    if (navigator.vibrate) navigator.vibrate(20);
    const interval = setInterval(() => {
      const elapsed = Date.now() - startAt;
      const progress = Math.min(100, (elapsed / sosLongPressMs) * 100);
      setSosProgress(progress);
      if (progress >= 100 && !sosTimerRef.current?.triggered) {
        sosTimerRef.current.triggered = true; cancelSosLongPress();
        if (navigator.vibrate) navigator.vibrate([150, 80, 150, 80, 150]); handleSOS();
      }
    }, 30);
    sosTimerRef.current.interval = interval;
  };

  const cancelSosLongPress = () => {
    if (sosTimerRef.current?.interval) clearInterval(sosTimerRef.current.interval);
    sosTimerRef.current = null; setSosProgress(0);
  };

  const handleTest = async () => {
    setTestLoading(true);
    try { const coords = await getGPS(); const d = await testAlerta(coords.lat, coords.lng); toast.success(d.message); }
    catch (e) { toast.error(e.message); } finally { setTestLoading(false); }
  };

  return (
    <Layout>
      <div className="space-y-5">
        <div className="flex items-center justify-between">
          <h1 className="font-black text-2xl uppercase tracking-tight flex items-center gap-3">
            <Siren className="h-7 w-7 text-red-500" /> Mis Dispositivos
          </h1>
          <div className="flex items-center gap-2">
            <button onClick={() => setShowNotifs(!showNotifs)} className="relative p-2 rounded-lg border hover:bg-zinc-100 dark:hover:bg-zinc-800" data-testid="btn-notifs">
              <Bell className="h-4 w-4" />
              {notificaciones.length > 0 && <span className="absolute -top-1 -right-1 bg-red-500 text-white text-[10px] font-black rounded-full min-w-[18px] h-[18px] px-1 flex items-center justify-center animate-pulse">{notificaciones.length}</span>}
            </button>
            {pushEnabled ? <span className="text-xs text-emerald-500 border border-emerald-500 rounded-full px-2 py-0.5 flex items-center gap-1"><BellRing className="h-3 w-3" />Push</span>
              : <button onClick={requestPush} className="text-xs border rounded-full px-2 py-1 flex items-center gap-1 hover:bg-zinc-100"><BellOff className="h-3 w-3" />Activar</button>}
            <button onClick={loadAll} className="p-2 rounded-lg border hover:bg-zinc-100 dark:hover:bg-zinc-800"><RefreshCw className="h-4 w-4" /></button>
          </div>
        </div>

        {showNotifs && (
          <div className="border rounded-xl p-4 space-y-2 bg-white dark:bg-zinc-900">
            <div className="flex items-center justify-between"><span className="font-bold text-sm">Notificaciones ({notificaciones.length})</span>
              {notificaciones.length > 0 && <button onClick={() => { marcarLeidas(); setNotificaciones([]); }} className="text-xs text-zinc-500 hover:underline">Limpiar</button>}
            </div>
            {notificaciones.length === 0 ? <p className="text-sm text-zinc-400 text-center py-4">Sin notificaciones</p>
              : notificaciones.map(n => (
                <button key={n.id} onClick={() => setSelectedNotif(n)} className={`w-full text-left p-3 rounded-lg text-sm border hover:bg-zinc-50 ${n.tipo === 'sos' ? 'bg-red-50 border-red-200' : ''}`}>
                  <div className="flex items-center gap-2 mb-1">{n.tipo === 'sos' && <ShieldAlert className="h-4 w-4 text-red-500" />}<span className="font-bold">{n.titulo}</span>{n.lat && <MapPin className="h-3 w-3 text-zinc-400 ml-auto" />}</div>
                  <p className="text-zinc-500 text-xs">{n.mensaje}</p>
                </button>
              ))}
          </div>
        )}

        {loading ? <div className="grid grid-cols-1 md:grid-cols-2 gap-4">{[...Array(2)].map((_, i) => <div key={i} className="h-48 bg-zinc-200 dark:bg-zinc-800 rounded-2xl animate-pulse" />)}</div>
          : dispositivos.length === 0 ? (
            <div className="border-2 rounded-2xl py-16 text-center"><Siren className="h-16 w-16 mx-auto text-zinc-300 mb-4" /><p className="text-xl font-bold">Sin dispositivos</p><p className="text-zinc-400">No tiene dispositivos asignados</p></div>
          ) : (
            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
              {dispositivos.map(disp => {
                const isOn = disp.switch === true;
                const isProc = toggling === disp.id;
                const progress = pressProgress[disp.id] || 0;
                const holding = progress > 0 && progress < 100;
                return (
                  <div key={disp.id} role="button" tabIndex={0}
                    onMouseDown={() => startLongPress(disp)} onMouseUp={() => cancelLongPress(disp.id)} onMouseLeave={() => cancelLongPress(disp.id)}
                    onTouchStart={() => startLongPress(disp)} onTouchEnd={() => cancelLongPress(disp.id)} onTouchCancel={() => cancelLongPress(disp.id)}
                    onContextMenu={e => e.preventDefault()}
                    style={{ WebkitUserSelect: 'none', userSelect: 'none', WebkitTouchCallout: 'none' }}
                    className={`relative overflow-hidden rounded-2xl border-2 p-6 transition-all select-none cursor-pointer ${holding ? 'scale-[0.98]' : 'active:scale-[0.97]'} ${(isProc || !disp.online) ? 'opacity-50 pointer-events-none' : ''} ${isOn ? 'border-red-500 bg-red-500 text-white shadow-xl shadow-red-500/30' : 'border-zinc-300 dark:border-zinc-700 bg-zinc-100 dark:bg-zinc-900 hover:border-zinc-400'}`}
                    data-testid={`device-btn-${disp.id}`}
                  >
                    {holding && <div className="absolute bottom-0 left-0 h-2 bg-red-400 transition-none" style={{ width: `${progress}%` }} />}
                    <div className="flex items-center justify-between mb-4">
                      <div className="flex items-center gap-1.5">
                        {disp.online ? <Wifi className={`h-4 w-4 ${isOn ? 'text-white/70' : 'text-emerald-500'}`} /> : <WifiOff className="h-4 w-4 text-zinc-400" />}
                        <span className={`text-xs font-medium ${isOn ? 'text-white/70' : 'text-zinc-400'}`}>{disp.online ? 'Online' : 'Offline'}</span>
                      </div>
                      <span className={`text-xs font-black uppercase px-2 py-0.5 rounded-full ${isOn ? 'bg-white/20 text-white' : 'bg-zinc-200 dark:bg-zinc-800'}`}>
                        {isOn ? 'Encendido' : 'Apagado'}
                      </span>
                    </div>
                    <div className="flex flex-col items-center gap-3 py-4">
                      <div className={`p-4 rounded-full ${isOn ? 'bg-white/20' : 'bg-zinc-200 dark:bg-zinc-800'} ${holding ? 'scale-110' : ''} transition-transform`}>
                        <Siren className={`h-10 w-10 ${isOn ? 'text-white animate-pulse' : 'text-zinc-500'}`} />
                      </div>
                      <span className="font-black text-lg uppercase tracking-wide">{disp.nombre}</span>
                    </div>
                    <div className={`text-center text-sm font-bold mt-2 ${isOn ? 'text-white/80' : 'text-zinc-500'}`}>
                      {isProc ? 'Procesando...' : holding ? 'Mantén presionado...' : isOn ? 'Mantén presionado para APAGAR' : 'Mantén presionado para ENCENDER'}
                    </div>
                  </div>
                );
              })}
            </div>
          )}

        {/* SOS */}
        <div role="button" tabIndex={0}
          onMouseDown={startSosLongPress} onMouseUp={cancelSosLongPress} onMouseLeave={cancelSosLongPress}
          onTouchStart={startSosLongPress} onTouchEnd={cancelSosLongPress} onTouchCancel={cancelSosLongPress}
          onContextMenu={e => e.preventDefault()}
          style={{ WebkitUserSelect: 'none', userSelect: 'none', WebkitTouchCallout: 'none' }}
          className={`relative overflow-hidden w-full p-5 rounded-2xl font-black text-lg uppercase tracking-wider flex items-center justify-center gap-3 transition-all select-none cursor-pointer bg-gradient-to-r from-orange-500 to-red-600 text-white shadow-lg ${sosLoading ? 'opacity-50 pointer-events-none' : ''}`}
          data-testid="btn-sos"
        >
          {sosProgress > 0 && sosProgress < 100 && <div className="absolute bottom-0 left-0 h-2 bg-white/80 transition-none" style={{ width: `${sosProgress}%` }} />}
          <ShieldAlert className={`h-7 w-7 ${sosLoading || sosProgress > 0 ? 'animate-pulse' : ''}`} />
          {sosLoading ? 'Enviando SOS...' : sosProgress > 0 && sosProgress < 100 ? 'Mantén presionado...' : 'SOS Silencioso'}
        </div>

        {(canTest || isAdmin) && (
          <button onClick={handleTest} disabled={testLoading}
            className="w-full p-3 rounded-xl font-bold text-sm uppercase tracking-wider flex items-center justify-center gap-2 border-2 border-blue-500/30 bg-blue-500/10 text-blue-600 hover:bg-blue-500/20 disabled:opacity-50"
            data-testid="btn-test"
          >
            <Bell className={`h-5 w-5 ${testLoading ? 'animate-pulse' : ''}`} />
            {testLoading ? 'Enviando prueba...' : 'Probar Alerta (solo yo)'}
          </button>
        )}

        <div className="flex items-center gap-3 p-3 bg-zinc-100 dark:bg-zinc-900 rounded-xl">
          <Volume2 className="h-4 w-4 text-zinc-400" />
          <span className="text-sm text-zinc-400">Sonido:</span>
          <select value={userSound} onChange={e => saveSound(e.target.value)} className="bg-transparent text-sm font-medium outline-none" data-testid="select-sound">
            {SOUND_OPTIONS.map(s => <option key={s.value} value={s.value}>{s.label}</option>)}
          </select>
        </div>
      </div>

      {/* Notif Detail Modal */}
      {selectedNotif && (
        <div className="fixed inset-0 z-50 bg-black/50 flex items-center justify-center p-4" onClick={() => setSelectedNotif(null)}>
          <div className="bg-white dark:bg-zinc-900 rounded-2xl p-6 max-w-md w-full space-y-4" onClick={e => e.stopPropagation()}>
            <h3 className="text-lg font-bold flex items-center gap-2">{selectedNotif.tipo === 'sos' && <ShieldAlert className="h-5 w-5 text-red-500" />}{selectedNotif.titulo}</h3>
            <p className="text-lg">{selectedNotif.mensaje}</p>
            {selectedNotif.lat && selectedNotif.lng && (
              <a href={`https://www.google.com/maps?q=${selectedNotif.lat},${selectedNotif.lng}`} target="_blank" rel="noopener noreferrer"
                className="flex items-center justify-center gap-2 w-full p-3 rounded-xl bg-blue-500 text-white font-bold hover:bg-blue-600">
                <MapPin className="h-5 w-5" /> Ver en Google Maps
              </a>
            )}
            <button onClick={() => setSelectedNotif(null)} className="w-full p-2 border rounded-xl text-sm">Cerrar</button>
          </div>
        </div>
      )}
    </Layout>
  );
}
