// wh-app.jsx — Login, Sidebar, App shell, Tweaks

const { useState, useEffect, useRef } = React;
const {
  Icon, Avatar, Badge, Modal, SecHead,
  Toaster, ConfirmDialog,
  sbClient, apiFetch,
  ConnectionSection, GruposSection, ContactosSection,
  EnviosSection, AltasSection, UsuariosSection, ActividadSection, PerfilesSection
} = window;

/* ── Tweakable defaults ───────────────────────────────── */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "collapsed": false,
  "accentHue": 162
}/*EDITMODE-END*/;

/* ── Helpers de rol ──────────────────────────────────── */
const ROLE_LABEL = { super_admin: 'Super Admin', admin: 'Administrador', agente: 'Agente' };
const ROLE_COLOR = { super_admin: 'brand', admin: 'teal', agente: 'gray' };
const isAdmin = role => role === 'admin' || role === 'super_admin';

/* ══════════════════════════════════════════════════════════
   LOGIN  (Supabase Auth real + tracking de intentos fallidos)
══════════════════════════════════════════════════════════ */
function Login({ onLogin, theme, onThemeToggle }) {
  const [email, setEmail] = useState('');
  const [pass,  setPass]  = useState('');
  const [busy,  setBusy]  = useState(false);
  const [err,   setErr]   = useState('');

  const submit = async e => {
    e.preventDefault();
    if (!email.trim() || !pass.trim()) { setErr('Completa todos los campos.'); return; }
    setErr(''); setBusy(true);
    try {
      const { data, error } = await sbClient.auth.signInWithPassword({ email: email.trim(), password: pass });

      if (error) {
        // Rastrear intento fallido (sin esperar respuesta)
        fetch('/api/auth/track-failure', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ email: email.trim() })
        }).catch(() => {});
        setErr('Email o contraseña incorrectos.');
        return;
      }

      // Cargar perfil del backend
      const res = await fetch('/api/me', {
        headers: { 'Authorization': `Bearer ${data.session.access_token}` }
      });

      if (!res.ok) {
        const errBody = await res.json().catch(() => ({}));
        await sbClient.auth.signOut();
        if (errBody.code === 'blocked') {
          setErr('Tu cuenta está bloqueada por múltiples intentos fallidos. Contactá al administrador.');
        } else {
          setErr(errBody.error || 'No se pudo cargar el perfil.');
        }
        return;
      }

      const profile = await res.json();
      onLogin({ ...profile, session: data.session });
    } catch {
      setErr('Error de conexión. Verificá que el servidor esté corriendo.');
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="login-bg">
      <button onClick={onThemeToggle} className="btn btn-ghost btn-icon"
        style={{ position:'absolute', top:20, right:20, zIndex:10, background:'oklch(100% 0 0 / .1)', borderColor:'transparent', color:'oklch(80% 0.03 162)' }}
        title="Cambiar tema">
        <Icon name={theme === 'light' ? 'moon' : 'sun'} size={16}/>
      </button>

      <div className="login-card">
        <div className="login-logo-area">
          <img src={theme === 'dark' ? 'assets/Whasint-logo-hightcontrast2.png' : 'assets/whasint-logo3.png'}
            alt="Whasint" className="login-logo"/>
          <p className="login-tag">Gestión inteligente de WhatsApp Web</p>
        </div>

        <div className="login-rule">Acceso al panel</div>

        <form className="stack" onSubmit={submit}>
          <div className="field">
            <label className="field-lbl">Email</label>
            <div style={{ position:'relative' }}>
              <Icon name="user" size={14} style={{ position:'absolute', left:11, top:'50%', transform:'translateY(-50%)', color:'var(--muted)', pointerEvents:'none' }}/>
              <input className="inp" style={{ paddingLeft:34 }} placeholder="tu@email.com" type="email"
                value={email} onChange={e => setEmail(e.target.value)} autoComplete="email"/>
            </div>
          </div>

          <div className="field">
            <label className="field-lbl">Contraseña</label>
            <div style={{ position:'relative' }}>
              <Icon name="key" size={14} style={{ position:'absolute', left:11, top:'50%', transform:'translateY(-50%)', color:'var(--muted)', pointerEvents:'none' }}/>
              <input className="inp" type="password" style={{ paddingLeft:34 }} placeholder="••••••••"
                value={pass} onChange={e => setPass(e.target.value)} autoComplete="current-password"/>
            </div>
          </div>

          {err && (
            <div style={{ fontSize:12.5, color:'var(--danger)', background:'var(--danger-soft)', padding:'8px 12px', borderRadius:'var(--r-sm)' }}>
              {err}
            </div>
          )}

          <button className="btn btn-primary btn-lg btn-full" type="submit" disabled={busy}>
            {busy ? 'Ingresando…' : <><Icon name="zap" size={15}/>Iniciar sesión</>}
          </button>
        </form>

        <p style={{ textAlign:'center', fontSize:11.5, color:'var(--muted)' }}>
          Whasint · Panel de Gestión WhatsApp Web
        </p>
      </div>
    </div>
  );
}

/* ══════════════════════════════════════════════════════════
   SIDEBAR
══════════════════════════════════════════════════════════ */
const NAV = [
  { id:'conexion',   label:'Conexión',   icon:'wifi',       group:'Principal', roles:['admin','agente','super_admin'] },
  { id:'grupos',     label:'Grupos',     icon:'layers',     group:'Principal', roles:['admin','agente','super_admin'] },
  { id:'contactos',  label:'Contactos',  icon:'users',      group:'Principal', roles:['admin','agente','super_admin'] },
  { id:'envios',     label:'Envíos',     icon:'send',       group:'Campañas',  roles:['admin','agente','super_admin'] },
  { id:'altas',      label:'Altas',      icon:'user-plus',  group:'Campañas',  roles:['admin','agente','super_admin'] },
  { id:'usuarios',   label:'Usuarios',   icon:'shield',     group:'Admin',     roles:['admin','super_admin']          },
  { id:'actividad',  label:'Actividad',  icon:'activity',   group:'Admin',     roles:['admin','agente','super_admin'] },
];

function Sidebar({ active, onNav, collapsed, mobileOpen, user, theme, onThemeToggle, onLogout }) {
  const role = user?.role || 'agente';
  const visibleNav = NAV.filter(n => n.roles.includes(role));
  const groups = [...new Set(visibleNav.map(n => n.group))];

  return (
    <aside className={`sidebar${mobileOpen ? ' mobile-open' : ''}`}>
      <div className="sb-top">
        <img src="assets/Whasint-logo-hightcontrast2.png" alt="Whasint" className="sb-logo sb-logo-full"/>
        <img src="assets/whasint-mark.png" alt="Whasint" className="sb-logo sb-logo-mark"/>
      </div>

      <nav className="sb-nav">
        {groups.map(grp => (
          <div key={grp}>
            <div className="sb-group-label">{grp}</div>
            {visibleNav.filter(n => n.group === grp).map(item => (
              <div key={item.id}
                className={`nav-item ${active === item.id ? 'active' : ''}`}
                onClick={() => onNav(item.id)}
                title={collapsed ? item.label : ''}>
                <Icon name={item.icon} size={17}/>
                <span className="nav-label">{item.label}</span>
              </div>
            ))}
          </div>
        ))}
      </nav>

      <div className="sb-footer">
        <div className="theme-toggle" onClick={onThemeToggle} title={theme==='light'?'Modo oscuro':'Modo claro'}>
          <Icon name={theme==='light' ? 'moon' : 'sun'} size={17}/>
          <span className="theme-label">{theme==='light' ? 'Modo oscuro' : 'Modo claro'}</span>
        </div>

        <div style={{ height:1, background:'var(--sb-border)', margin:'6px 0' }}/>

        {/* Usuario — clic navega a sección Perfiles */}
        <div className="sb-user" onClick={() => onNav('perfiles')} style={{ cursor:'pointer' }} title="Ver mis perfiles">
          <Avatar name={user?.full_name || user?.email || 'U'} size="sm"/>
          <div className="sb-user-info">
            <div className="sb-user-name">{user?.full_name || user?.email || '—'}</div>
            <div className="sb-user-role">{ROLE_LABEL[user?.role] || 'Agente'}</div>
          </div>
        </div>

        <div className="nav-item" onClick={onLogout} style={{ color:'oklch(65% 0.15 22)' }}>
          <Icon name="log-out" size={16}/>
          <span className="nav-label">Cerrar sesión</span>
        </div>
      </div>
    </aside>
  );
}

/* ══════════════════════════════════════════════════════════
   TWEAKS PANEL
══════════════════════════════════════════════════════════ */
function TweaksPanel({ open, onClose, tweaks, update }) {
  const ACCENTS = [
    { hue:162, label:'Verde' }, { hue:220, label:'Azul' },
    { hue:280, label:'Violeta' }, { hue:28, label:'Naranja' },
  ];
  const applyAccent = hue => {
    document.documentElement.style.setProperty('--brand',       `oklch(44% 0.16 ${hue})`);
    document.documentElement.style.setProperty('--brand-h',     `oklch(39% 0.15 ${hue})`);
    document.documentElement.style.setProperty('--brand-soft',  `oklch(96% 0.04 ${hue})`);
    document.documentElement.style.setProperty('--accent',      `oklch(64% 0.22 ${hue+10})`);
    document.documentElement.style.setProperty('--accent-soft', `oklch(95% 0.05 ${hue+10})`);
    document.documentElement.style.setProperty('--focus',       `0 0 0 3px oklch(64% 0.22 ${hue+10} / .28)`);
    update('accentHue', hue);
  };
  return (
    <div className={`tweaks-panel ${open ? 'open' : ''}`}>
      <div className="flex-r">
        <div style={{ fontSize:13, fontWeight:800, color:'var(--ink)' }}>Tweaks</div>
        <button className="btn btn-ghost btn-icon btn-sm mla" onClick={onClose}><Icon name="x" size={14}/></button>
      </div>
      <div>
        <div className="tw-lbl">Tema</div>
        <div className="flex-r" style={{ gap:7 }}>
          {[['light','Claro','sun'],['dark','Oscuro','moon']].map(([v,l,ic]) => (
            <button key={v} className={`btn btn-sm ${tweaks.theme===v?'btn-primary':'btn-ghost'}`}
              onClick={() => update('theme', v)}><Icon name={ic} size={13}/>{l}</button>
          ))}
        </div>
      </div>
      <div>
        <div className="tw-lbl">Sidebar</div>
        <div className="flex-r" style={{ gap:7 }}>
          {[[false,'Expandido'],[true,'Colapsado']].map(([v,l]) => (
            <button key={l} className={`btn btn-sm ${tweaks.collapsed===v?'btn-primary':'btn-ghost'}`}
              onClick={() => update('collapsed', v)}>{l}</button>
          ))}
        </div>
      </div>
      <div>
        <div className="tw-lbl">Color de acento</div>
        <div className="tw-swatches">
          {ACCENTS.map(a => (
            <div key={a.hue} className={`tw-swatch ${tweaks.accentHue===a.hue?'on':''}`}
              style={{ background:`oklch(54% 0.2 ${a.hue})` }} title={a.label}
              onClick={() => applyAccent(a.hue)}/>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ══════════════════════════════════════════════════════════
   APP ROOT
══════════════════════════════════════════════════════════ */
const TITLES = {
  conexion:'Conexión WhatsApp', grupos:'Grupos y Listas', contactos:'Contactos',
  envios:'Envíos', altas:'Altas de Participantes', usuarios:'Usuarios',
  actividad:'Actividad', perfiles:'Perfiles',
};

function App() {
  const saved = (() => { try { return JSON.parse(localStorage.getItem('wh_tweaks')||'{}'); } catch { return {}; } })();
  const [tweaks,        setTweaks]        = useState({ ...TWEAK_DEFAULTS, ...saved });
  const [auth,          setAuth]          = useState(false);
  const [loading,       setLoading]       = useState(true);
  const [user,          setUser]          = useState(null);
  const [section,       setSection]       = useState(() => localStorage.getItem('wh_section') || 'conexion');
  const [tweaksOpen,    setTweaksOpen]    = useState(false);
  const [mobileNavOpen, setMobileNavOpen] = useState(false);

  // Estado compartido del backend
  const [whStatus,   setWhStatus]   = useState({ status:'stopped', hasQr:false, groupsCount:0, isSyncingGroups:false, lastError:null });
  const [qrUrl,      setQrUrl]      = useState(null);
  const [groups,     setGroups]     = useState([]);
  const [contacts,   setContacts]   = useState([]);
  const [groupLists, setGroupLists] = useState([]);
  const [jobs,       setJobs]       = useState([]);
  const realtimeRevokingRef = useRef(false);

  const resetSessionState = () => {
    setAuth(false);
    setUser(null);
    setWhStatus({ status:'stopped', hasQr:false, groupsCount:0, isSyncingGroups:false, lastError:null });
    setQrUrl(null);
    setGroups([]);
    setContacts([]);
    setGroupLists([]);
    setJobs([]);
  };

  const revokeRealtimeSession = async (message) => {
    if (realtimeRevokingRef.current) return;
    realtimeRevokingRef.current = true;
    if (message) {
      window.showToast?.(message, 'warning');
    }
    try {
      await sbClient.auth.signOut();
    } catch {
      resetSessionState();
    }
  };

  /* ── Verificar sesión al cargar ── */
  useEffect(() => {
    sbClient.auth.getSession().then(async ({ data: { session } }) => {
      if (session) {
        try {
          const res = await fetch('/api/me', {
            headers: { 'Authorization': `Bearer ${session.access_token}` }
          });
          if (res.ok) {
            const profile = await res.json();
            setUser({ ...profile, session });
            setAuth(true);
          }
        } catch { /* sesión inválida */ }
      }
      setLoading(false);
    });

    const { data: { subscription } } = sbClient.auth.onAuthStateChange(async (event, session) => {
      if (event === 'TOKEN_REFRESHED' && session) {
        setUser(prev => prev ? { ...prev, session } : prev);
      }
      if (event === 'SIGNED_OUT') {
        realtimeRevokingRef.current = false;
        resetSessionState();
      }
    });
    return () => subscription.unsubscribe();
  }, []);

  /* ── Tema ── */
  useEffect(() => {
    document.documentElement.setAttribute('data-theme', tweaks.theme);
  }, [tweaks.theme]);

  /* ── Persistir sección ── */
  useEffect(() => {
    if (section !== 'perfiles') localStorage.setItem('wh_section', section);
  }, [section]);

  /* ── Edit mode protocol ── */
  useEffect(() => {
    const handler = e => {
      if (e.data?.type === '__activate_edit_mode')   setTweaksOpen(true);
      if (e.data?.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  /* ── Socket.IO + carga inicial ── */
  useEffect(() => {
    if (!auth) return;
    let mounted = true;
    let socket = null;

    (async () => {
      const { data: { session } } = await sbClient.auth.getSession();
      if (!mounted || !session?.access_token) return;

      socket = io({
        auth: { token: session.access_token }
      });

      socket.on('whatsapp:update', ({ event, payload, status }) => {
        setWhStatus(status);
        if (event === 'qr') setQrUrl(payload?.qr || null);
        if (['ready','disconnected','authenticated'].includes(event)) setQrUrl(null);
        if (event === 'groups' && Array.isArray(payload?.groups)) setGroups(payload.groups);
      });
      socket.on('groups:update', gs => setGroups(gs));
      socket.on('jobs:init', js => setJobs(js));
      socket.on('job:update', job => {
        setJobs(prev => {
          const idx = prev.findIndex(j => j.id === job.id);
          if (idx === -1) return [job, ...prev].slice(0, 25);
          const next = [...prev]; next[idx] = job; return next;
        });
      });
      socket.on('session:revoked', ({ error }) => {
        revokeRealtimeSession(error || 'Tu sesion en tiempo real dejo de ser valida.');
      });
      socket.on('connect_error', (error) => {
        const message = String(error?.message || '').trim();
        if (/token|sesion|autenticar|cuenta/i.test(message)) {
          revokeRealtimeSession(message || 'No se pudo autenticar el canal en tiempo real.');
        }
      });
    })();

    apiFetch('/api/contacts').then(r => r.json()).then(setContacts).catch(() => {});
    apiFetch('/api/group-lists').then(r => r.json()).then(setGroupLists).catch(() => {});
    apiFetch('/api/jobs').then(r => r.json()).then(setJobs).catch(() => {});
    return () => {
      mounted = false;
      socket?.disconnect();
    };
  }, [auth]);

  const update = (key, value) => {
    const next = { ...tweaks, [key]: value };
    setTweaks(next);
    localStorage.setItem('wh_tweaks', JSON.stringify(next));
    window.parent.postMessage({ type:'__edit_mode_set_keys', edits:{ [key]:value } }, '*');
  };

  const toggleTheme    = () => update('theme',     tweaks.theme === 'light' ? 'dark' : 'light');
  const toggleCollapse = () => {
    if (window.innerWidth <= 860) {
      setMobileNavOpen(v => !v);
    } else {
      update('collapsed', !tweaks.collapsed);
    }
  };

  const navTo = (id) => {
    setSection(id);
    setMobileNavOpen(false); // cerrar drawer en móvil al navegar
  };

  const handleLogin = (profile) => { setUser(profile); setAuth(true); };

  const handleLogout = async () => {
    await sbClient.auth.signOut();
    resetSessionState();
  };

  // Upsert: Socket.IO puede haber agregado el job antes que el response HTTP
  const onJobCreated = job => setJobs(prev => {
    if (prev.some(j => j.id === job.id)) return prev; // ya existe, no duplicar
    return [job, ...prev].slice(0, 25);
  });

  // Redirigir a sección válida si el rol no tiene acceso
  useEffect(() => {
    if (!user) return;
    const role = user.role || 'agente';
    const allowed = NAV.filter(n => n.roles.includes(role)).map(n => n.id);
    if (!allowed.includes(section) && section !== 'perfiles') setSection(allowed[0] || 'conexion');
  }, [user]);

  // Cerrar drawer móvil al rotar a desktop
  useEffect(() => {
    const mq = window.matchMedia('(max-width: 860px)');
    const handler = e => { if (!e.matches) setMobileNavOpen(false); };
    mq.addEventListener('change', handler);
    return () => mq.removeEventListener('change', handler);
  }, []);

  const renderSection = () => {
    const shared = {
      whStatus, qrUrl, groups, contacts, groupLists, jobs,
      onGroupsChange:     setGroups,
      onContactsChange:   setContacts,
      onGroupListsChange: setGroupLists,
      onJobCreated,
    };
    const map = {
      conexion:  <ConnectionSection  {...shared} user={user} />,
      grupos:    <GruposSection    {...shared} />,
      contactos: <ContactosSection {...shared} />,
      envios:    <EnviosSection    {...shared} />,
      altas:     <AltasSection     {...shared} />,
      usuarios:  <UsuariosSection  currentUser={user} />,
      actividad: <ActividadSection {...shared} />,
      perfiles:  <PerfilesSection  user={user} onProfileUpdate={updates => setUser(prev => ({ ...prev, ...updates }))} />,
    };
    return map[section] || <div className="t-muted">Sección no encontrada</div>;
  };

  /* ── Pantalla de carga inicial ── */
  if (loading) {
    return (
      <div style={{ display:'flex', alignItems:'center', justifyContent:'center', height:'100vh', background:'var(--bg)' }}>
        <div style={{ textAlign:'center', color:'var(--muted)' }}>
          <Icon name="wifi" size={32} style={{ opacity:0.4 }}/>
          <div style={{ marginTop:12, fontSize:14 }}>Verificando sesión…</div>
        </div>
      </div>
    );
  }

  if (!auth) {
    return <Login onLogin={handleLogin} theme={tweaks.theme} onThemeToggle={toggleTheme}/>;
  }

  return (
    <>
      {/* Backdrop para drawer móvil */}
      <div
        className={`mobile-backdrop${mobileNavOpen ? ' open' : ''}`}
        onClick={() => setMobileNavOpen(false)}
      />

      <div className={`app-shell ${tweaks.collapsed ? 'collapsed' : ''}`}>
        <Sidebar
          active={section}
          onNav={navTo}
          collapsed={tweaks.collapsed}
          mobileOpen={mobileNavOpen}
          user={user}
          theme={tweaks.theme}
          onThemeToggle={toggleTheme}
          onLogout={handleLogout}
        />

        <div className="main-area">
          <div className="topbar">
            <button className="topbar-menu-btn" onClick={toggleCollapse} title="Menú">
              <Icon name="menu" size={18}/>
            </button>
            <div className="topbar-title">{TITLES[section] || section}</div>
            <div className="flex-r mla" style={{ gap:10 }}>
              <button className="btn btn-ghost btn-icon btn-sm" onClick={() => navTo('perfiles')} title="Mis perfiles">
                <Avatar name={user?.full_name || user?.email || 'U'} size="sm"/>
              </button>
            </div>
          </div>

          <div className="main-scroll">
            {renderSection()}
          </div>
        </div>
      </div>

      <TweaksPanel open={tweaksOpen} onClose={() => setTweaksOpen(false)} tweaks={tweaks} update={update}/>
      <Toaster/>
      <ConfirmDialog/>
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
