// LOLA Consola Web — CONFIGURACIÓN (Empresa · Seguridad · Biometría · IA · Notificaciones).
// Sobrescribe window.ConfiguracionView (se carga después de views.jsx).
//
// Empresa, el interruptor de 2FA, la política de contraseñas, los canales de notificación
// (push/WhatsApp/correo) y Biometría SÍ se guardan en el backend real (Config, vía PATCH
// /admin/config) y el servidor los hace cumplir de verdad (ver auth.controller.js
// validarPassword). El resto — bloqueo/expiración de sesión, IA, los EVENTOS de notificación
// y las opciones de cifrado/limpieza — son preferencias LOCALES de este navegador (no hay
// endpoint de servidor para ellas todavía) y se guardan en localStorage. Cada sección dice
// explícitamente cuál es cuál — nunca asumas "guardado" == "en la base" sin leer el rótulo.

const api = () => window.LOLA.api;
const CFG_KEY = 'lola_config';
const CFG_DEFAULTS = {
  nivel: 'estandar', bloqueo: 15, expiracion: 0, twofa: true, politica: 'basica', auditoria: true, limpieza: false, cifrado: false,
  iaAsistente: true, iaModelo: 'estandar', iaSugerencias: true, iaTono: 'profesional',
  notifPush: true, notifWa: false, notifCorreo: true, evSolicitudes: true, evAprobaciones: true, evPagos: true, evSeguridad: true,
  empresa: '', nit: '', correoEmpresa: '',
  bioProveedor: 'faceio', bioLiveness: true, bioUmbral: 85,
};
const NIVELES = {
  basico: { bloqueo: 0, expiracion: 0, twofa: false, politica: 'basica', auditoria: false },
  estandar: { bloqueo: 15, expiracion: 0, twofa: true, politica: 'basica', auditoria: true },
  estricto: { bloqueo: 5, expiracion: 60, twofa: true, politica: 'fuerte', auditoria: true },
};
function calcNivel(c) {
  for (const k of ['basico', 'estandar', 'estricto']) {
    const p = NIVELES[k];
    if (p.bloqueo === c.bloqueo && p.expiracion === c.expiracion && p.twofa === c.twofa && p.politica === c.politica && p.auditoria === c.auditoria) return k;
  }
  return 'personalizado';
}
function readCfg() { try { return Object.assign({}, CFG_DEFAULTS, JSON.parse(localStorage.getItem(CFG_KEY) || '{}')); } catch (e) { return Object.assign({}, CFG_DEFAULTS); } }

function CToggle({ t, on, onChange }) {
  return (
    <button onClick={() => onChange(!on)} style={{ width: 46, height: 27, borderRadius: 999, border: 'none', cursor: 'pointer',
      background: on ? t.success : '#CDD3DB', position: 'relative', transition: 'background .2s', flexShrink: 0 }}>
      <span style={{ position: 'absolute', top: 3, left: on ? 22 : 3, width: 21, height: 21, borderRadius: '50%', background: '#fff', transition: 'left .2s', boxShadow: '0 1px 3px rgba(0,0,0,.3)' }}/>
    </button>
  );
}
function CSeg({ t, options, value, onChange }) {
  return (
    <div style={{ display: 'inline-flex', gap: 3, background: t.grid, borderRadius: 9, padding: 3, flexWrap: 'wrap' }}>
      {options.map((o) => { const on = value === o.v; return (
        <button key={String(o.v)} onClick={() => onChange(o.v)} style={{ cursor: 'pointer', padding: '7px 13px', borderRadius: 7, border: 'none',
          background: on ? '#fff' : 'transparent', color: on ? t.brand : t.sec, fontFamily: t.font, fontSize: 12.5, fontWeight: on ? 700 : 600, boxShadow: on ? '0 1px 3px rgba(0,0,0,.12)' : 'none' }}>{o.l}</button>
      ); })}
    </div>
  );
}
function CRow({ t, title, sub, control, first }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, padding: '15px 0', borderTop: first ? 'none' : `1px solid ${t.grid}`, flexWrap: 'wrap' }}>
      <div style={{ flex: 1, minWidth: 200 }}><div style={{ fontSize: 14, fontWeight: 700, color: t.text }}>{title}</div><div style={{ fontSize: 12.5, color: t.ter, marginTop: 2, lineHeight: 1.45 }}>{sub}</div></div>
      {control}
    </div>
  );
}
function CCard({ t, title, sub, children, style }) {
  return (
    <div style={{ background: '#fff', border: `1px solid ${t.border}`, borderRadius: 16, padding: '20px 22px', ...style }}>
      {title && <div style={{ fontSize: 16, fontWeight: 800, color: t.text }}>{title}</div>}
      {sub && <div style={{ fontSize: 13, color: t.ter, marginTop: 3, marginBottom: 6 }}>{sub}</div>}
      {children}
    </div>
  );
}
function CField({ t, label, value, onChange, mono }) {
  return (
    <label style={{ display: 'block' }}>
      <span style={{ fontSize: 11, color: t.sec, fontFamily: t.mono, textTransform: 'uppercase', letterSpacing: .6, fontWeight: 700 }}>{label}</span>
      <input value={value} onChange={(e) => onChange(e.target.value)} style={{ width: '100%', marginTop: 6, padding: '10px 13px', borderRadius: 9,
        border: `1px solid ${t.border}`, fontFamily: mono ? t.mono : t.font, fontSize: 13.5, color: t.text, background: '#fff', outline: 'none', boxSizing: 'border-box' }}/>
    </label>
  );
}

function ConfiguracionView() {
  const t = window.WC, I = window.WI;
  const [sec, setSec] = React.useState('general');
  const [cfg, setCfg] = React.useState(readCfg);
  const [snap, setSnap] = React.useState(cfg);
  const [saved, setSaved] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [loadErr, setLoadErr] = React.useState('');
  const dirty = JSON.stringify(cfg) !== JSON.stringify(snap);

  // Trae la verdad del servidor (empresa / 2FA / notificaciones / biometría) y la superpone
  // sobre las preferencias locales — para ESOS campos puntuales, el servidor manda.
  React.useEffect(() => {
    api().getConfig().then((r) => {
      const c = (r && r.config) || {};
      const notif = c.notificaciones || {};
      const bio = c.biometria || {};
      setCfg((prev) => {
        const next = {
          ...prev,
          empresa: (c.empresa && c.empresa.nombre) || prev.empresa,
          nit: (c.empresa && c.empresa.nit) || prev.nit,
          correoEmpresa: (c.empresa && c.empresa.correo) || prev.correoEmpresa,
          twofa: c.seguridad && c.seguridad.require2FA !== undefined ? c.seguridad.require2FA !== false : prev.twofa,
          politica: (c.seguridad && c.seguridad.politica) || prev.politica,
          notifPush: notif.push !== undefined ? notif.push !== false : prev.notifPush,
          notifWa: notif.whatsapp !== undefined ? !!notif.whatsapp : prev.notifWa,
          notifCorreo: notif.correo !== undefined ? notif.correo !== false : prev.notifCorreo,
          bioProveedor: bio.proveedor || prev.bioProveedor,
          bioLiveness: bio.liveness !== undefined ? bio.liveness !== false : prev.bioLiveness,
          bioUmbral: bio.umbral != null ? bio.umbral : prev.bioUmbral,
        };
        next.nivel = calcNivel(next);
        setSnap(next);
        return next;
      });
    }).catch((e) => setLoadErr(e.message || 'No se pudo cargar la configuración del servidor; se muestran solo tus preferencias locales.'));
  }, []);

  const set = (patch) => setCfg((c) => { const n = { ...c, ...patch }; n.nivel = calcNivel(n); return n; });
  const setNivel = (k) => setCfg((c) => ({ ...c, ...NIVELES[k], nivel: k }));

  const guardar = async () => {
    setBusy(true);
    try {
      await api().setConfig({
        empresa: { nombre: cfg.empresa, nit: cfg.nit, correo: cfg.correoEmpresa },
        seguridad: { require2FA: cfg.twofa, politica: cfg.politica },
        notificaciones: { push: cfg.notifPush, whatsapp: cfg.notifWa, correo: cfg.notifCorreo },
        biometria: { proveedor: cfg.bioProveedor, liveness: cfg.bioLiveness, umbral: cfg.bioUmbral },
      });
      try { localStorage.setItem(CFG_KEY, JSON.stringify(cfg)); } catch (e) {}
      setSnap(cfg); setSaved(true); setTimeout(() => setSaved(false), 1800);
    } catch (e) { alert(e.message || 'No se pudo guardar en el servidor'); }
    setBusy(false);
  };

  const TABS = [['general', 'General', 'Building'], ['seguridad', 'Seguridad', 'Shield'], ['bio', 'Biometría', 'Scan'], ['ia', 'IA', 'Gear'], ['notif', 'Notificaciones', 'Bell']];
  const nivelLabel = { basico: 'Básico', estandar: 'Estándar', estricto: 'Estricto', personalizado: 'Personalizado' }[cfg.nivel];

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 900 }}>
      {/* Tabs */}
      <div style={{ display: 'inline-flex', gap: 4, background: '#fff', border: `1px solid ${t.border}`, borderRadius: 12, padding: 5, alignSelf: 'flex-start', flexWrap: 'wrap' }}>
        {TABS.map(([id, l, ic]) => { const Icn = I[ic] || I.Gear; const on = sec === id; return (
          <button key={id} onClick={() => setSec(id)} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer', padding: '9px 15px', borderRadius: 9, border: 'none', background: on ? t.brand + '12' : 'transparent', color: on ? t.brand : t.sec, fontFamily: t.font, fontSize: 13.5, fontWeight: on ? 700 : 600 }}><Icn size={16}/> {l}</button>
        ); })}
      </div>

      {loadErr && (
        <div style={{ padding: '11px 15px', borderRadius: 12, background: '#FDF0EF', border: '1px solid #F2C4C0', color: t.danger, fontSize: 13 }}>{loadErr}</div>
      )}

      {sec === 'general' && (
        <CCard t={t} title="Datos de la empresa" sub="Identidad fiscal que aparece en contratos y comprobantes · se guarda en el servidor">
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px,1fr))', gap: 14, marginTop: 4 }}>
            <CField t={t} label="Razón social" value={cfg.empresa} onChange={(v) => set({ empresa: v })}/>
            <CField t={t} label="NIT" value={cfg.nit} onChange={(v) => set({ nit: v })} mono/>
          </div>
          <div style={{ marginTop: 14 }}>
            <CField t={t} label="Correo de contacto" value={cfg.correoEmpresa} onChange={(v) => set({ correoEmpresa: v })}/>
          </div>
        </CCard>
      )}

      {sec === 'seguridad' && (
        <React.Fragment>
          <CCard t={t} title="Seguridad de datos" sub="Define qué tan estricta es la protección de acceso y datos.">
            <div style={{ fontSize: 11.5, color: t.sec, fontFamily: t.mono, textTransform: 'uppercase', letterSpacing: .8, fontWeight: 700, margin: '10px 0 10px' }}>Nivel de seguridad · <span style={{ color: t.brand }}>{nivelLabel}</span></div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px,1fr))', gap: 12 }}>
              {[['basico', 'Básico', 'Acceso simple, sin bloqueos automáticos.'], ['estandar', 'Estándar', 'Bloqueo 15 min · 2FA · auditoría.'], ['estricto', 'Estricto', 'Bloqueo 5 min · sesión 60 min · contraseña fuerte.']].map(([id, l, d]) => {
                const on = cfg.nivel === id;
                return (
                  <button key={id} onClick={() => setNivel(id)} style={{ textAlign: 'left', cursor: 'pointer', padding: '14px 15px', borderRadius: 13, border: `1.5px solid ${on ? t.brand : t.border}`, background: on ? '#F4F8FF' : '#fff' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}><span style={{ color: on ? t.brand : t.ter, display: 'flex' }}><I.Shield size={17}/></span><span style={{ fontSize: 14.5, fontWeight: 700, color: t.text }}>{l}</span></div>
                    <div style={{ fontSize: 12, color: t.ter, lineHeight: 1.45 }}>{d}</div>
                  </button>
                );
              })}
            </div>
            <div style={{ fontSize: 11.5, color: t.ter, marginTop: 10 }}>Este preset ajusta los controles de abajo; "Doble factor" y "Política de contraseñas" se guardan en el servidor y se hacen cumplir de verdad; el resto es preferencia local.</div>
          </CCard>

          <CCard t={t}>
            <CRow t={t} first title="Exigir verificación en dos pasos" sub="Todos los administradores verifican un código al iniciar sesión · se guarda en el servidor"
              control={<CToggle t={t} on={cfg.twofa} onChange={(v) => set({ twofa: v })}/>}/>
            <CRow t={t} title="Bloqueo automático por inactividad" sub="Bloquea la sesión tras un periodo sin actividad (preferencia local de este navegador)."
              control={<CSeg t={t} value={cfg.bloqueo} onChange={(v) => set({ bloqueo: v })} options={[{ v: 0, l: 'Desactivado' }, { v: 5, l: '5 min' }, { v: 15, l: '15 min' }, { v: 30, l: '30 min' }]}/>}/>
            <CRow t={t} title="Expiración de sesión" sub="Cierra la sesión por completo tras este tiempo (preferencia local)."
              control={<CSeg t={t} value={cfg.expiracion} onChange={(v) => set({ expiracion: v })} options={[{ v: 0, l: 'Desactivado' }, { v: 30, l: '30 min' }, { v: 60, l: '60 min' }, { v: 120, l: '120 min' }]}/>}/>
            <CRow t={t} title="Política de contraseñas" sub="Requisitos mínimos al crear o cambiar contraseñas · se guarda en el servidor y se exige de verdad al registrarse, cambiar o restablecer contraseña"
              control={<CSeg t={t} value={cfg.politica} onChange={(v) => set({ politica: v })} options={[{ v: 'basica', l: 'Básica (mín. 8)' }, { v: 'fuerte', l: 'Fuerte (8+, may/min/número)' }]}/>}/>
            <CRow t={t} title="Auditoría de accesos" sub="Preferencia local de este navegador — el registro de accesos e intentos fallidos en el servidor (Bitácora) siempre está activo y no se puede desactivar desde aquí."
              control={<CToggle t={t} on={cfg.auditoria} onChange={(v) => set({ auditoria: v })}/>}/>
            <CRow t={t} title="Limpieza automática tras sincronizar" sub="En dispositivos de campo: al confirmar el registro en el servidor, los datos locales se borran del navegador."
              control={<CToggle t={t} on={cfg.limpieza} onChange={(v) => set({ limpieza: v })}/>}/>
            <CRow t={t} title="Cifrar datos en el dispositivo (en reposo)" sub="Los registros guardados en el navegador se cifran con AES-256."
              control={<CToggle t={t} on={cfg.cifrado} onChange={(v) => set({ cifrado: v })}/>}/>
          </CCard>

          <CCard t={t} title="Cifrado de respaldos (AES-256)" sub="Exporta una copia cifrada de toda la base local, protegida con contraseña.">
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginTop: 6 }}>
              <button onClick={() => alert('Se generaría un respaldo cifrado (.enc) protegido con contraseña.')} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer', padding: '10px 16px', borderRadius: 10, border: 'none', background: t.brand, color: '#fff', fontFamily: t.font, fontSize: 13.5, fontWeight: 700 }}><I.Shield size={16}/> Exportar respaldo cifrado</button>
              <button onClick={() => alert('Aquí se seleccionaría un archivo .enc para restaurar.')} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer', padding: '10px 16px', borderRadius: 10, border: `1px solid ${t.border}`, background: '#fff', color: t.text, fontFamily: t.font, fontSize: 13.5, fontWeight: 700 }}><I.Download size={16}/> Restaurar respaldo</button>
            </div>
          </CCard>
        </React.Fragment>
      )}

      {sec === 'bio' && (
        <CCard t={t} title="Reconocimiento facial" sub="Se guarda en el servidor · la captura sigue siendo una demostración (ver face.jsx), esto solo fija qué proveedor y umbral usaría.">
          <div style={{ marginTop: 4, marginBottom: 16 }}>
            <div style={{ fontSize: 12.5, fontWeight: 700, color: t.sec, marginBottom: 9 }}>Proveedor de tecnología</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(160px,1fr))', gap: 10 }}>
              {[['faceio', 'FaceIO', 'Web · enrolamiento + auth'], ['regula', 'Regula', 'Documento + rostro'],
                ['aws', 'AWS Rekognition', 'Liveness + match'], ['device', 'Nativo del dispositivo', 'Face ID / Android']].map(([id, l, d]) => {
                const on = cfg.bioProveedor === id;
                return (
                  <button key={id} onClick={() => set({ bioProveedor: id })} style={{ textAlign: 'left', cursor: 'pointer', padding: '12px 14px', borderRadius: 10,
                    border: `1.5px solid ${on ? t.brand : t.border}`, background: on ? '#F4F8FF' : '#fff', fontFamily: t.font }}>
                    <div style={{ fontSize: 13.5, fontWeight: 700, color: t.text }}>{l}</div>
                    <div style={{ fontSize: 11.5, color: t.ter, marginTop: 4 }}>{d}</div>
                  </button>
                );
              })}
            </div>
          </div>
          <CRow t={t} first title="Prueba de vida (liveness)" sub="Exigir parpadeo / giro para evitar fotos"
            control={<CToggle t={t} on={cfg.bioLiveness} onChange={(v) => set({ bioLiveness: v })}/>}/>
          <div style={{ marginTop: 14, paddingTop: 14, borderTop: `1px solid ${t.grid}` }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
              <div>
                <div style={{ fontSize: 14, fontWeight: 700, color: t.text }}>Umbral de confianza</div>
                <div style={{ fontSize: 12.5, color: t.ter, marginTop: 1 }}>Qué tan estricta es la coincidencia facial.</div>
              </div>
              <div style={{ fontFamily: t.mono, fontWeight: 700, color: t.brand }}>{cfg.bioUmbral}%</div>
            </div>
            <input type="range" min="50" max="99" value={cfg.bioUmbral} onChange={(e) => set({ bioUmbral: Number(e.target.value) })} style={{ width: '100%' }}/>
          </div>
        </CCard>
      )}

      {sec === 'ia' && (
        <CCard t={t} title="Asistente de IA" sub="Ayuda contextual dentro de la consola (preferencia local de este navegador).">
          <div style={{ marginTop: 4 }}>
            <CRow t={t} first title="Activar Asistente IA" sub="Muestra el botón de ayuda con IA en cada pantalla."
              control={<CToggle t={t} on={cfg.iaAsistente} onChange={(v) => set({ iaAsistente: v })}/>}/>
            <CRow t={t} title="Modelo" sub="Equilibra velocidad y profundidad de las respuestas."
              control={<CSeg t={t} value={cfg.iaModelo} onChange={(v) => set({ iaModelo: v })} options={[{ v: 'rapido', l: 'Rápido' }, { v: 'estandar', l: 'Estándar' }, { v: 'avanzado', l: 'Avanzado' }]}/>}/>
            <CRow t={t} title="Sugerencias automáticas" sub="Propone acciones (aprobar, ajustar comisión) según el contexto."
              control={<CToggle t={t} on={cfg.iaSugerencias} onChange={(v) => set({ iaSugerencias: v })}/>}/>
            <CRow t={t} title="Tono de las respuestas" sub="Cómo se comunica el asistente."
              control={<CSeg t={t} value={cfg.iaTono} onChange={(v) => set({ iaTono: v })} options={[{ v: 'breve', l: 'Breve' }, { v: 'profesional', l: 'Profesional' }, { v: 'detallado', l: 'Detallado' }]}/>}/>
          </div>
        </CCard>
      )}

      {sec === 'notif' && (
        <React.Fragment>
          <CCard t={t} title="Canales" sub="Por dónde te avisamos · se guarda en el servidor">
            <div style={{ marginTop: 4 }}>
              <CRow t={t} first title="Notificaciones push" sub="Avisos en tiempo real en el navegador."
                control={<CToggle t={t} on={cfg.notifPush} onChange={(v) => set({ notifPush: v })}/>}/>
              <CRow t={t} title="WhatsApp Business" sub="Avisos importantes por WhatsApp."
                control={<CToggle t={t} on={cfg.notifWa} onChange={(v) => set({ notifWa: v })}/>}/>
              <CRow t={t} title="Correo electrónico" sub="Resúmenes y alertas por correo."
                control={<CToggle t={t} on={cfg.notifCorreo} onChange={(v) => set({ notifCorreo: v })}/>}/>
            </div>
          </CCard>
          <CCard t={t} title="Eventos" sub="De qué quieres enterarte (preferencia local de este navegador).">
            <div style={{ marginTop: 4 }}>
              <CRow t={t} first title="Nuevas solicitudes de aprobación" sub="Cuando un cliente o proveedor envía documentos."
                control={<CToggle t={t} on={cfg.evSolicitudes} onChange={(v) => set({ evSolicitudes: v })}/>}/>
              <CRow t={t} title="Aprobaciones y rechazos" sub="Resultado de las revisiones."
                control={<CToggle t={t} on={cfg.evAprobaciones} onChange={(v) => set({ evAprobaciones: v })}/>}/>
              <CRow t={t} title="Pagos y liquidaciones" sub="Recargas, retiros y pagos a proveedores."
                control={<CToggle t={t} on={cfg.evPagos} onChange={(v) => set({ evPagos: v })}/>}/>
              <CRow t={t} title="Alertas de seguridad" sub="Accesos fallidos y cambios sensibles."
                control={<CToggle t={t} on={cfg.evSeguridad} onChange={(v) => set({ evSeguridad: v })}/>}/>
            </div>
          </CCard>
        </React.Fragment>
      )}

      {/* Barra de guardado */}
      <div style={{ position: 'sticky', bottom: 0, display: 'flex', alignItems: 'center', gap: 14, padding: '13px 18px', borderRadius: 14,
        background: saved ? t.success + '12' : dirty ? '#fff' : '#FAFBFC', border: `1px solid ${saved ? t.success + '55' : dirty ? t.accent : t.border}`,
        boxShadow: dirty && !saved ? '0 8px 24px rgba(29,87,169,.1)' : 'none' }}>
        <span style={{ width: 9, height: 9, borderRadius: '50%', flexShrink: 0, background: saved ? t.success : dirty ? t.accent : t.ter }}/>
        <span style={{ flex: 1, fontSize: 13.5, fontWeight: 600, color: saved ? t.success : dirty ? t.text : t.ter }}>{saved ? 'Cambios guardados' : dirty ? 'Tienes cambios sin guardar' : 'Todo está guardado'}</span>
        {dirty && !saved && <button onClick={() => setCfg(snap)} style={{ cursor: 'pointer', padding: '9px 16px', borderRadius: 10, border: `1px solid ${t.border}`, background: '#fff', color: t.sec, fontFamily: t.font, fontSize: 13.5, fontWeight: 700 }}>Descartar</button>}
        <button onClick={guardar} disabled={(!dirty && !saved) || busy} style={{ cursor: ((!dirty && !saved) || busy) ? 'default' : 'pointer', padding: '10px 20px', borderRadius: 10, border: 'none', background: saved ? t.success : t.brand, color: '#fff', fontFamily: t.font, fontSize: 13.5, fontWeight: 700, opacity: (!dirty && !saved) ? .5 : 1, display: 'inline-flex', alignItems: 'center', gap: 8 }}>{saved ? <><I.Check size={16}/> Guardado</> : busy ? 'Guardando…' : 'Guardar cambios'}</button>
      </div>
    </div>
  );
}

window.ConfiguracionView = ConfiguracionView;
