// ─── Micos CRM · Shell (sidebar + topbar) ──────────
// Visual clone of the ERP shell: same brand wordmark, sectioned nav with
// icon-in-rounded-square items, accent vertical-bar active indicator,
// breadcrumbs in the topbar + cmd+K-style search trigger, pulse-dot bell.

const { useState: _useStateCS, useEffect: _useEffectCS, useRef: _useRefCS } = React;

// Map icon ids (from CRM_FOLDERS / CRM_SMART_VIEWS) to icon components
const CRM_ICON_MAP = {
  inbox: IconInbox,
  layers: IconLayers,
  star: IconStar,
  send: IconSend,
  pencil: IconPencil,
  clock: IconClock,
  archive: IconArchive,
  shield: IconShield,
  trash: IconTrash,
  'check-circle': IconCheckCircle,
  wallet: IconWallet,
  calendar: IconCalendar,
  'file-text': IconFileText,
  sparkles: IconSparkles,
  tag: IconTag,
};

// ─── Sidebar ───────────────────────────────────────
// `etiquetas` = catálogo vivo de crm_etiquetas (equipo, persistente);
// onAddLabel(nombre, color) / onEditLabel(id, patch) / onDeleteLabel(id)
// pegan contra /api/crm-etiquetas (viven en crm/app.jsx).
function CrmSidebar({ folder, smartView, labelFilter, onChangeFolder, onChangeSmartView, onChangeLabel, onAddLabel, onEditLabel, onDeleteLabel, etiquetas, onCompose, counts, rol }) {
  const esJefe = rol === 'ADMIN' || rol === 'JEFE';
  // Shared nav-item renderer — mirrors ERP shell.jsx structure exactly.
  const renderNavItem = ({ key, label, Icon, iconColor, badge, badgeTone, active, onClick }) => {
    const dim = 'color-mix(in oklab, var(--foreground) 75%, transparent)';
    return (
      <button
        key={key}
        type="button"
        onClick={onClick}
        className="nav-item group relative flex items-center gap-3 pl-3 pr-3 py-2.5 text-[13.5px] font-semibold rounded-xl cursor-pointer transition-all duration-200"
        style={{
          background: active ? 'color-mix(in oklab, var(--accent) 12%, transparent)' : 'transparent',
          color: active ? 'var(--accent)' : dim,
        }}
        onMouseEnter={(e) => { if (!active) { e.currentTarget.style.background = 'var(--surface-hover)'; e.currentTarget.style.color = 'var(--foreground)'; } }}
        onMouseLeave={(e) => { if (!active) { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = dim; } }}
      >
        {active && <span className="nav-active-indicator" />}
        <span
          className="flex h-9 w-9 items-center justify-center rounded-lg transition-all duration-200 flex-shrink-0"
          style={{
            background: active
              ? 'color-mix(in oklab, var(--accent) 18%, transparent)'
              : (iconColor
                  ? `color-mix(in oklab, ${iconColor} 14%, transparent)`
                  : 'color-mix(in oklab, var(--muted-foreground) 6%, transparent)'),
            color: active ? 'var(--accent)' : (iconColor || 'var(--muted-foreground)'),
          }}
        >
          <Icon size={17} />
        </span>
        <span className="flex-1 text-left truncate">{label}</span>
        {badge != null && badge > 0 && (
          <span
            className="inline-flex items-center justify-center rounded-full text-[10.5px] font-extrabold px-1.5 min-w-[20px] h-5 tabular-nums"
            style={{
              background: badgeTone === 'alert'
                ? 'rgba(245, 158, 11, 0.18)'
                : (active
                    ? 'color-mix(in oklab, var(--accent) 18%, transparent)'
                    : 'color-mix(in oklab, var(--muted-foreground) 12%, transparent)'),
              color: badgeTone === 'alert'
                ? 'var(--warning-soft)'
                : (active ? 'var(--accent)' : 'var(--muted-foreground)'),
            }}
          >
            {badge}
          </span>
        )}
      </button>
    );
  };

  return (
    <aside
      className="hidden md:flex flex-col w-[272px] sticky top-0 h-screen z-10"
      style={{
        background: 'var(--sidebar)',
        borderRight: '1px solid var(--sidebar-border)',
      }}
    >
      {/* Brand wordmark + CRM tag — identical scale to ERP */}
      <div className="flex items-end gap-2 py-7 px-7">
        <button
          type="button"
          onClick={() => onChangeFolder('inbox')}
          className="group flex items-center bg-transparent border-0 p-0 cursor-pointer"
          aria-label="Ir a Recibidos"
        >
          <MicosWordmark
            style={{ height: 30, width: 'auto', color: 'var(--accent)' }}
            className="transition-transform duration-200 group-hover:scale-105"
          />
        </button>
        <span
          className="text-[9.5px] font-extrabold uppercase tracking-[0.22em]"
          style={{ color: 'color-mix(in oklab, var(--muted-foreground) 75%, transparent)' }}
        >
          CRM
        </span>
      </div>

      <nav className="flex-1 overflow-y-auto pt-5 pb-4 px-4 space-y-7 scrollbar-none">
        {/* Para responder — LA pila de trabajo: lo que espera respuesta,
            el más viejo primero. Arriba de todo a propósito (top10 #7). */}
        <div className="flex flex-col gap-1">
          {renderNavItem({
            key: 'para-responder',
            label: 'Para responder',
            Icon: IconReply,
            iconColor: 'var(--accent)',
            badge: counts['para-responder'] || 0,
            active: folder === 'para-responder' && !smartView && !labelFilter,
            onClick: () => onChangeFolder('para-responder'),
          })}
        </div>

        {/* Bandejas */}
        <div className="flex flex-col gap-1">
          <p
            className="px-3 pb-2.5 text-[10.5px] font-bold uppercase tracking-[0.18em]"
            style={{ color: 'color-mix(in oklab, var(--muted-foreground) 75%, transparent)' }}
          >
            Bandejas
          </p>
          {CRM_FOLDERS.map((f) => {
            const Icon = CRM_ICON_MAP[f.icon] || IconInbox;
            // Estas bandejas se llenan por acción del usuario (o son archivo):
            // no deben "notificar" novedades como Recibidos / Spam.
            const NO_NOTIFY = new Set(['starred', 'scheduled', 'sent', 'all', 'trash', 'archived']);
            const n = NO_NOTIFY.has(f.key) ? 0 : (counts[f.key] || 0);
            return renderNavItem({
              key: f.key,
              label: f.label,
              Icon,
              badge: n,
              active: folder === f.key && !smartView,
              onClick: () => onChangeFolder(f.key),
            });
          })}
        </div>

        {/* Etiquetas */}
        <div className="flex flex-col gap-1">
          <div className="flex items-center justify-between px-3 pb-2.5">
            <p
              className="text-[10.5px] font-bold uppercase tracking-[0.18em]"
              style={{ color: 'color-mix(in oklab, var(--muted-foreground) 75%, transparent)' }}
            >
              Etiquetas
            </p>
            <AddLabelButton onAddLabel={onAddLabel} />
          </div>
          {Object.keys(CRM_LABELS).filter((id) => CRM_LABELS[id].pinned).map((id) => (
            <LabelNavItem
              key={id}
              id={id}
              count={counts[`tag:${id}`] || 0}
              active={labelFilter === id}
              onClick={() => onChangeLabel(id)}
            />
          ))}
          {(etiquetas || []).map((et) => (
            <LabelNavItem
              key={et.id}
              id={et.id}
              custom={{ id: et.id, label: et.nombre, colorHex: et.color }}
              count={counts[`tag:${et.id}`] || 0}
              active={labelFilter === et.id}
              onClick={() => onChangeLabel(et.id)}
              onEdit={onEditLabel ? (patch) => onEditLabel(et.id, patch) : null}
              onDelete={onDeleteLabel ? () => {
                if (window.confirm(`¿Eliminar la etiqueta "${et.nombre}"? Los correos no se tocan, solo pierden la etiqueta.`)) onDeleteLabel(et.id);
              } : null}
            />
          ))}
        </div>

        {/* Jefes — Métricas del equipo. Solo visible para ADMIN/JEFE (el rol
            viaja como prop desde CrmApp, sincronizado con /api/me). Navegación
            COMPLETA a /crm?vista=metricas: crm-metrics.jsx se auto-monta como
            overlay leyendo el querystring al cargar la página (el CRM no tiene
            router propio, por eso no basta un pushState). El server igual
            devuelve 403 en /api/crm-metricas si alguien fuerza la URL sin ser
            jefe — esto es solo la entrada de UI. */}
        {esJefe && (
          <div className="flex flex-col gap-1">
            <p
              className="px-3 pb-2.5 text-[10.5px] font-bold uppercase tracking-[0.18em]"
              style={{ color: 'color-mix(in oklab, var(--muted-foreground) 75%, transparent)' }}
            >
              Jefes
            </p>
            {renderNavItem({
              key: 'metricas',
              label: 'Métricas del equipo',
              Icon: IconTrendingUp,
              iconColor: 'var(--accent)',
              active: false,
              onClick: () => { window.location.assign('/crm?vista=metricas'); },
            })}
          </div>
        )}
      </nav>
    </aside>
  );
}

// ─── Etiqueta (label) nav item — colored chip in icon slot ────────
// `custom` (etiquetas del equipo, crm_etiquetas): {id, label, colorHex} — el
// color es hex plano de la DB. `onEdit`/`onDelete` (solo custom) muestran
// lápiz/tacho al pasar el mouse: renombrar inline y eliminar (soft-delete).
function LabelNavItem({ id, count, custom, active, onClick, onEdit, onDelete }) {
  const [editing, setEditing] = _useStateCS(false);
  const [nombre, setNombre] = _useStateCS('');
  const cfg = custom || CRM_LABELS[id];
  if (!cfg) return null;
  const palette = {
    presupuesto:  ['var(--pipeline-presupuesto-bg)',  'var(--pipeline-presupuesto)'],
    remito:       ['var(--pipeline-remito-bg)',       'var(--pipeline-remito)'],
    'doc-medica': ['var(--pipeline-doc-medica-bg)',   'var(--pipeline-doc-medica)'],
    recibo:       ['var(--pipeline-recibo-bg)',       'var(--pipeline-recibo)'],
    oc:           ['var(--pipeline-oc-bg)',           'var(--pipeline-oc)'],
    factura:      ['var(--pipeline-factura-bg)',      'var(--pipeline-factura)'],
    iniciado:     ['var(--pipeline-iniciado-bg)',     'var(--pipeline-iniciado)'],
    destructive:  ['rgba(220, 38, 38, 0.14)',         'var(--danger)'],
    neutral:      ['color-mix(in oklab, var(--muted-foreground) 14%, transparent)', 'var(--muted-foreground)'],
  };
  const custColor = custom && cfg.colorHex;
  const [bg, color] = custColor
    ? [`color-mix(in oklab, ${custColor} 14%, transparent)`, custColor]
    : (palette[cfg.tone] || palette.neutral);
  const dim = 'color-mix(in oklab, var(--foreground) 75%, transparent)';

  const commitRename = () => {
    const v = nombre.trim();
    setEditing(false);
    if (v && v !== cfg.label && onEdit) onEdit({ nombre: v });
  };

  if (editing) {
    return (
      <div className="flex items-center gap-3 pl-3 pr-3 py-2" style={{ borderRadius: 12 }}>
        <span className="flex h-9 w-9 items-center justify-center rounded-lg flex-shrink-0" style={{ background: bg }}>
          <span style={{ width: 11, height: 11, borderRadius: 3, background: color, display: 'block' }} />
        </span>
        <input
          autoFocus
          value={nombre}
          onChange={(e) => setNombre(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter') commitRename(); if (e.key === 'Escape') setEditing(false); }}
          onBlur={commitRename}
          className="flex-1 min-w-0 bg-transparent outline-none text-[13px] font-semibold rounded-lg px-2 py-1"
          style={{ color: 'var(--foreground)', border: '1px solid var(--border)' }}
        />
      </div>
    );
  }

  return (
    <button
      type="button"
      onClick={onClick}
      title={cfg.desc || cfg.label}
      className="nav-item group relative flex items-center gap-3 pl-3 pr-3 py-2.5 text-[13.5px] font-semibold rounded-xl cursor-pointer transition-all duration-200"
      style={{
        color: active ? color : dim,
        background: active ? `color-mix(in oklab, ${color} 12%, transparent)` : 'transparent',
      }}
      onMouseEnter={(e) => { if (!active) { e.currentTarget.style.background = 'var(--surface-hover)'; e.currentTarget.style.color = 'var(--foreground)'; } }}
      onMouseLeave={(e) => { if (!active) { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = dim; } }}
    >
      {active && <span className="nav-active-indicator" style={{ background: color }} />}
      <span
        className="flex h-9 w-9 items-center justify-center rounded-lg flex-shrink-0"
        style={{ background: bg }}
      >
        <span style={{ width: 11, height: 11, borderRadius: 3, background: color, display: 'block' }} />
      </span>
      <span className="flex-1 text-left truncate">{cfg.label}</span>
      {(onEdit || onDelete) && (
        <span className="hidden group-hover:inline-flex items-center gap-1 flex-shrink-0">
          {onEdit && (
            <span
              role="button" tabIndex={0} title="Renombrar"
              onClick={(e) => { e.stopPropagation(); setNombre(cfg.label); setEditing(true); }}
              onKeyDown={(e) => { if (e.key === 'Enter') { e.stopPropagation(); setNombre(cfg.label); setEditing(true); } }}
              className="inline-flex h-6 w-6 items-center justify-center rounded-md cursor-pointer"
              style={{ color: 'var(--muted-foreground)' }}
              onMouseEnter={(e) => { e.currentTarget.style.color = 'var(--accent)'; }}
              onMouseLeave={(e) => { e.currentTarget.style.color = 'var(--muted-foreground)'; }}
            >
              <IconPencil size={12} />
            </span>
          )}
          {onDelete && (
            <span
              role="button" tabIndex={0} title="Eliminar etiqueta"
              onClick={(e) => { e.stopPropagation(); onDelete(); }}
              onKeyDown={(e) => { if (e.key === 'Enter') { e.stopPropagation(); onDelete(); } }}
              className="inline-flex h-6 w-6 items-center justify-center rounded-md cursor-pointer"
              style={{ color: 'var(--muted-foreground)' }}
              onMouseEnter={(e) => { e.currentTarget.style.color = 'var(--danger)'; }}
              onMouseLeave={(e) => { e.currentTarget.style.color = 'var(--muted-foreground)'; }}
            >
              <IconTrash size={12} />
            </span>
          )}
        </span>
      )}
      {cfg.pinned && (
        <span title="Etiqueta Micos" style={{ color, opacity: 0.55, flexShrink: 0, display: 'inline-flex' }}>
          <IconPin size={12} />
        </span>
      )}
      {count > 0 && (
        <span
          className="inline-flex items-center justify-center rounded-full text-[10.5px] font-extrabold px-1.5 min-w-[20px] h-5 tabular-nums"
          style={{
            background: active ? `color-mix(in oklab, ${color} 18%, transparent)` : 'color-mix(in oklab, var(--muted-foreground) 12%, transparent)',
            color: active ? color : 'var(--muted-foreground)',
          }}
        >
          {count}
        </span>
      )}
    </button>
  );
}

// Pin glyph for the fixed "Micos" etiquetas
const IconPin = (p) => (
  <Icon {...p}>
    <line x1="12" y1="17" x2="12" y2="22" />
    <path d="M9 9V3h6v6l2 3v2H7v-2l2-3z" />
  </Icon>
);

// ─── "+ Nueva etiqueta" inline creator ─────────────
// Crea una etiqueta REAL del equipo (POST /api/crm-etiquetas vía onAddLabel
// de crm/app.jsx): nombre + color (swatches de CRM_ETIQUETA_COLORES).
function AddLabelButton({ onAddLabel }) {
  const [open, setOpen] = _useStateCS(false);
  const [name, setName] = _useStateCS('');
  const [color, setColor] = _useStateCS(CRM_ETIQUETA_COLORES[0]);
  const [pos, setPos] = _useStateCS({ left: 0, top: 0 });
  const btnRef = _useRefCS(null);
  const inputRef = _useRefCS(null);

  _useEffectCS(() => { if (open && inputRef.current) inputRef.current.focus(); }, [open]);

  const openPopover = () => {
    if (btnRef.current) {
      const r = btnRef.current.getBoundingClientRect();
      setPos({ left: r.right - 232, top: r.bottom + 8 });
    }
    setOpen(true);
  };

  const cerrar = () => { setOpen(false); setName(''); setColor(CRM_ETIQUETA_COLORES[0]); };

  const commit = () => {
    const v = name.trim();
    if (v) onAddLabel(v, color);
    cerrar();
  };

  return (
    <>
      <button
        ref={btnRef}
        type="button"
        onClick={openPopover}
        title="Nueva etiqueta"
        className="flex h-6 w-6 items-center justify-center rounded-lg transition-all cursor-pointer"
        style={{ color: 'color-mix(in oklab, var(--muted-foreground) 70%, transparent)' }}
        onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--surface-hover)'; e.currentTarget.style.color = 'var(--accent)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'color-mix(in oklab, var(--muted-foreground) 70%, transparent)'; }}
      >
        <IconPlus size={15} />
      </button>
      {open && (
        <div className="fixed inset-0 z-40" onClick={cerrar}>
          <div
            onClick={(e) => e.stopPropagation()}
            className="fixed flex flex-col gap-2 p-2.5 rounded-xl"
            style={{
              left: pos.left, top: pos.top, width: 232,
              background: 'var(--card)', border: '1px solid var(--border)', boxShadow: 'var(--shadow-lg)',
            }}
          >
            <div className="flex items-center gap-2">
              <input
                ref={inputRef}
                value={name}
                onChange={(e) => setName(e.target.value)}
                onKeyDown={(e) => { if (e.key === 'Enter') commit(); if (e.key === 'Escape') cerrar(); }}
                placeholder="Nombre de la etiqueta"
                className="bg-transparent border-0 outline-none text-[12.5px] font-medium flex-1 min-w-0"
                style={{ color: 'var(--foreground)' }}
              />
              <button type="button" onClick={commit} className="btn btn-primary h-7 px-2.5 text-[11px]">Crear</button>
            </div>
            <div className="flex items-center gap-1.5">
              {CRM_ETIQUETA_COLORES.map((c) => (
                <button
                  key={c}
                  type="button"
                  onClick={() => setColor(c)}
                  title={c}
                  className="cursor-pointer"
                  style={{
                    width: 18, height: 18, borderRadius: 6, background: c,
                    border: color === c ? '2px solid var(--foreground)' : '2px solid transparent',
                  }}
                />
              ))}
            </div>
          </div>
        </div>
      )}
    </>
  );
}

// ─── Topbar (sticky top bar) ───────────────────────
function CrmTopbar({ search, onSearch, onRefresh, refreshing, onOpenConfig, configActive, contextTitle, contextSubtitle, theme, onToggleTheme, user }) {
  // Identidad: `user` viaja como prop desde CrmApp (sincronizada con /api/me);
  // si no llega (compat), cae al const congelado de crm-data.js.
  const u = user || CRM_USER;
  // Lupa mobile (auditoría 05/07 #3: no tenía onClick — en mobile no había
  // forma de buscar): abre una fila de búsqueda debajo del topbar, mismo
  // estado `search` que el buscador de escritorio.
  const [mobileSearchOpen, setMobileSearchOpen] = _useStateCS(false);
  const mobileInputRef = _useRefCS(null);
  _useEffectCS(() => { if (mobileSearchOpen && mobileInputRef.current) mobileInputRef.current.focus(); }, [mobileSearchOpen]);
  // Breadcrumbs in ERP style: section + current view (2 levels, matches ERP density).
  const crumbs = [
    { label: 'Correos' },
    { label: contextTitle || '—' },
  ];

  return (
    <header
      className="sticky top-0 z-20 px-4 sm:px-6 lg:px-8 py-3.5 flex items-center justify-between gap-4 no-print"
      style={{
        background: 'color-mix(in oklab, var(--background) 78%, transparent)',
        backdropFilter: 'saturate(150%) blur(14px)',
        WebkitBackdropFilter: 'saturate(150%) blur(14px)',
        borderBottom: '1px solid color-mix(in oklab, var(--border) 55%, transparent)',
      }}
    >
      {/* Breadcrumbs */}
      <nav className="flex items-center gap-1.5 text-[13px] font-semibold flex-1 min-w-0" aria-label="Breadcrumb">
        {crumbs.map((b, i) => {
          const last = i === crumbs.length - 1;
          return (
            <div key={i} className={`flex items-center gap-1.5 ${last ? 'min-w-0 flex-shrink' : 'flex-shrink-0'}`}>
              {i > 0 && (
                <IconChevronRight size={12} className="flex-shrink-0" style={{ color: 'color-mix(in oklab, var(--muted-foreground) 55%, transparent)' }} />
              )}
              {last ? (
                <span className="truncate font-bold" style={{ color: 'var(--foreground)' }}>{b.label}</span>
              ) : (
                <span className="whitespace-nowrap" style={{ color: 'var(--muted-foreground)' }}>{b.label}</span>
              )}
            </div>
          );
        })}
      </nav>

      {/* Tools cluster */}
      <div className="flex items-center gap-1.5 flex-shrink-0">
        {/* Search trigger — looks like ERP's cmd+K, but accepts real input */}
        <div
          className="hidden md:flex items-center gap-2.5 h-9 pl-3 pr-3 rounded-xl transition-all"
          style={{
            background: 'var(--card)',
            border: '1px solid var(--border)',
            width: 'clamp(220px, 26vw, 340px)',
          }}
          onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'color-mix(in oklab, var(--accent) 35%, var(--border))'; }}
          onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--border)'; }}
        >
          <IconSearch size={14} style={{ color: 'var(--muted-foreground)', flexShrink: 0 }} />
          <input
            type="text"
            value={search}
            onChange={(e) => onSearch(e.target.value)}
            placeholder="Buscar correos…"
            className="flex-1 bg-transparent border-0 outline-none text-[12.5px] font-medium min-w-0"
            style={{ color: 'var(--foreground)' }}
          />
        </div>

        {/* Mobile search */}
        <button
          type="button"
          onClick={() => setMobileSearchOpen(o => !o)}
          className="btn btn-icon md:hidden"
          style={{
            background: mobileSearchOpen ? 'color-mix(in oklab, var(--accent) 12%, transparent)' : 'var(--card)',
            color: mobileSearchOpen ? 'var(--accent)' : 'var(--muted-foreground)',
            border: '1px solid var(--border)',
          }}
          title="Buscar"
        >
          <IconSearch size={16} />
        </button>
        {mobileSearchOpen && (
          <div
            className="md:hidden fixed left-0 right-0 px-4 py-2.5 z-20 flex items-center gap-2"
            style={{
              top: 62,
              background: 'var(--card)',
              borderBottom: '1px solid var(--border)',
              boxShadow: 'var(--shadow-card)',
            }}
          >
            <IconSearch size={14} style={{ color: 'var(--muted-foreground)', flexShrink: 0 }} />
            <input
              ref={mobileInputRef}
              type="text"
              value={search}
              onChange={(e) => onSearch(e.target.value)}
              placeholder="Buscar correos…"
              className="flex-1 bg-transparent border-0 outline-none text-[13px] font-medium min-w-0"
              style={{ color: 'var(--foreground)' }}
            />
            <button
              type="button"
              onClick={() => { onSearch(''); setMobileSearchOpen(false); }}
              className="cursor-pointer"
              style={{ color: 'var(--muted-foreground)' }}
              title="Cerrar búsqueda"
            >
              <IconX size={15} />
            </button>
          </div>
        )}

        {/* Theme toggle */}
        <button
          type="button"
          onClick={onToggleTheme}
          className="btn btn-icon"
          style={{ background: 'var(--card)', color: 'var(--muted-foreground)', border: '1px solid var(--border)' }}
          title={theme === 'light' ? 'Cambiar a oscuro' : 'Cambiar a claro'}
        >
          {theme === 'light' ? <IconMoon size={16} /> : <IconSun size={16} />}
        </button>

        {/* Refresh — real (MicosStore.refresh + etiquetas + borradores);
            gira mientras trabaja para que se vea que hizo algo. */}
        <button
          type="button"
          onClick={onRefresh}
          disabled={refreshing}
          className="btn btn-icon"
          style={{ background: 'var(--card)', color: refreshing ? 'var(--accent)' : 'var(--muted-foreground)', border: '1px solid var(--border)' }}
          title="Refrescar"
        >
          <span className={refreshing ? 'animate-spin inline-flex' : 'inline-flex'}>
            <IconRefresh size={15} />
          </span>
        </button>

        {/* Configuración (filtros + firma) */}
        <button
          type="button"
          onClick={onOpenConfig}
          className="btn btn-icon hidden sm:flex"
          style={{
            background: configActive ? 'color-mix(in oklab, var(--accent) 12%, transparent)' : 'var(--card)',
            color: configActive ? 'var(--accent)' : 'var(--muted-foreground)',
            border: '1px solid var(--border)',
          }}
          title="Configuración"
        >
          <IconSettings size={16} />
        </button>

        <div className="w-px h-5 mx-0.5" style={{ background: 'var(--border)' }} />

        {/* User pill */}
        <button
          type="button"
          className="flex items-center gap-2 pl-1 pr-2 h-9 rounded-xl transition-all"
          style={{ background: 'var(--card)', border: '1px solid var(--border)' }}
          onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'color-mix(in oklab, var(--accent) 35%, var(--border))'; }}
          onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--border)'; }}
          title={`${u.nombre} ${u.apellido} · ${u.email}`}
        >
          <div
            className="h-7 w-7 rounded-lg flex items-center justify-center text-[11px] font-extrabold"
            style={{ background: 'color-mix(in oklab, var(--accent) 14%, transparent)', color: 'var(--accent)' }}
          >
            {((u.nombre || '')[0] || '') + ((u.apellido || '')[0] || '')}
          </div>
          <IconChevronDown size={13} style={{ color: 'var(--muted-foreground)' }} />
        </button>
      </div>
    </header>
  );
}

// ─── Configuración (engranaje) — SOLO dos secciones: Filtros y Firma ──────
// Persiste contra /api/crm-config (fila propia del usuario, contrato B0):
// `filtros` = [{id, nombre, query:{campo, contiene, accion, etiquetaId}}]
// (jsonb opaco para el server — este shape lo define el front y lo consume
// la ingesta al clasificar correos entrantes), `firmaHtml` + `firmaActiva`.
function CrmConfigScreen({ etiquetas, onClose }) {
  const [cargando, setCargando] = _useStateCS(true);
  const [errorCarga, setErrorCarga] = _useStateCS(false);
  const [guardando, setGuardando] = _useStateCS(false);
  const [guardadoOk, setGuardadoOk] = _useStateCS(false);
  const [firmaHtml, setFirmaHtml] = _useStateCS('');
  const [firmaActiva, setFirmaActiva] = _useStateCS(true);
  const [filtros, setFiltros] = _useStateCS([]);
  const [editandoRegla, setEditandoRegla] = _useStateCS(null); // null | {id?, campo, contiene, accion, etiquetaId}
  const okTimerRef = _useRefCS(null);

  _useEffectCS(() => {
    let cancelled = false;
    fetch('/api/crm-config', { credentials: 'same-origin' })
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('GET /api/crm-config → ' + r.status))))
      .then(cfg => {
        if (cancelled) return;
        setFirmaHtml(cfg.firmaHtml || '');
        setFirmaActiva(cfg.firmaActiva !== false);
        setFiltros(Array.isArray(cfg.filtros) ? cfg.filtros : []);
        setCargando(false);
      })
      .catch(e => { console.warn('[crm] config:', e.message); if (!cancelled) { setErrorCarga(true); setCargando(false); } });
    return () => { cancelled = true; clearTimeout(okTimerRef.current); };
  }, []);

  // PATCH parcial (upsert de la fila propia). Un solo camino de guardado
  // para las dos secciones; feedback visible siempre.
  const guardar = (patch, onOk) => {
    setGuardando(true); setGuardadoOk(false);
    fetch('/api/crm-config', {
      method: 'PATCH', credentials: 'same-origin',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(patch),
    })
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('PATCH /api/crm-config → ' + r.status))))
      .then(() => {
        setGuardadoOk(true);
        clearTimeout(okTimerRef.current);
        okTimerRef.current = setTimeout(() => setGuardadoOk(false), 2600);
        if (onOk) onOk();
      })
      .catch(e => {
        try {
          window.dispatchEvent(new CustomEvent('micos:store-error', {
            detail: { action: 'update', key: 'crmConfig', message: e.message, humano: 'No se pudo guardar la configuración. Reintentá.' },
          }));
        } catch (_) {}
      })
      .then(() => setGuardando(false));
  };

  const guardarFiltros = (nuevos) => { setFiltros(nuevos); guardar({ filtros: nuevos }); };

  const describirRegla = (f) => {
    const q = f.query || {};
    const campo = q.campo === 'asunto' ? 'el asunto' : 'el remitente';
    const et = q.accion === 'etiquetar' ? (etiquetas || []).find(x => x.id === q.etiquetaId) : null;
    const accion = q.accion === 'archivar' ? 'archivar'
      : q.accion === 'spam' ? 'mandar a Spam'
      : `etiquetar con "${et ? et.nombre : 'etiqueta eliminada'}"`;
    return `Si ${campo} contiene "${q.contiene}", ${accion}.`;
  };

  const commitRegla = () => {
    const r = editandoRegla;
    if (!r || !(r.contiene || '').trim()) return;
    if (r.accion === 'etiquetar' && !r.etiquetaId) return;
    const query = { campo: r.campo, contiene: r.contiene.trim(), accion: r.accion, etiquetaId: r.accion === 'etiquetar' ? r.etiquetaId : null };
    const regla = { id: r.id || ('flt-' + Date.now()), nombre: '', query };
    regla.nombre = describirRegla(regla);
    const nuevos = r.id ? filtros.map(f => (f.id === r.id ? regla : f)) : [...filtros, regla];
    setEditandoRegla(null);
    guardarFiltros(nuevos);
  };

  const cardStyle = {
    background: 'var(--card)',
    border: '1px solid color-mix(in oklab, var(--border) 55%, transparent)',
    boxShadow: 'var(--shadow-card)',
  };
  const selectStyle = {
    background: 'color-mix(in oklab, var(--surface) 50%, transparent)',
    border: '1px solid color-mix(in oklab, var(--border) 45%, transparent)',
    color: 'var(--foreground)',
  };

  return (
    <div className="flex-1 overflow-y-auto" style={{ minWidth: 0, background: 'var(--background)' }}>
      <div className="px-4 sm:px-6 lg:px-8 pt-2 pb-12 space-y-7 max-w-4xl">
        {/* Header */}
        <div className="flex flex-wrap items-end justify-between gap-4 animate-fade-in-up pt-2">
          <div className="space-y-3 min-w-0">
            <p className="text-[11px] font-bold uppercase tracking-[0.18em]" style={{ color: 'var(--accent)' }}>
              Correos · Configuración
            </p>
            <h1 className="text-[clamp(28px,4.2vw,40px)] leading-[1.05] font-extrabold tracking-[-0.02em]" style={{ color: 'var(--foreground)' }}>
              Configuración
            </h1>
            <p className="text-[13.5px] font-medium max-w-2xl" style={{ color: 'var(--muted-foreground)' }}>
              Filtros para los correos que llegan y tu firma. Nada más — lo demás ya funciona solo.
            </p>
          </div>
          <div className="flex items-center gap-2.5 flex-shrink-0">
            {guardadoOk && (
              <span key="ok" className="animate-name-pop text-[12px] font-bold" style={{ color: 'var(--success)' }}>Guardado</span>
            )}
            <button className="btn btn-outline" type="button" onClick={onClose}>Volver a la bandeja</button>
          </div>
        </div>

        {cargando ? (
          <p className="text-[13px] font-medium" style={{ color: 'var(--muted-foreground)' }}>Cargando…</p>
        ) : errorCarga ? (
          <div className="rounded-2xl p-5" style={cardStyle}>
            <p className="text-[13px] font-bold" style={{ color: 'var(--foreground)' }}>No se pudo cargar la configuración.</p>
            <p className="text-[12px] mt-1" style={{ color: 'var(--muted-foreground)' }}>Probá recargar la página. Si sigue, avisale a sistemas.</p>
          </div>
        ) : (
          <>
            {/* ── Filtros ── */}
            <div className="rounded-2xl overflow-hidden animate-fade-in-up" style={cardStyle}>
              <div className="px-5 py-4" style={{ borderBottom: '1px solid color-mix(in oklab, var(--border) 55%, transparent)' }}>
                <p className="text-[14px] font-extrabold" style={{ color: 'var(--foreground)' }}>Filtros</p>
                <p className="text-[12px] mt-0.5" style={{ color: 'var(--muted-foreground)' }}>
                  Reglas que se aplican a los correos nuevos que van llegando.
                </p>
              </div>
              {filtros.length === 0 && !editandoRegla && (
                <p className="px-5 py-4 text-[12.5px]" style={{ color: 'var(--muted-foreground)' }}>
                  Todavía no tenés filtros. Creá el primero con el botón de abajo.
                </p>
              )}
              {filtros.map(f => (
                <div key={f.id} className="flex items-center gap-3 px-5 py-3" style={{ borderBottom: '1px solid color-mix(in oklab, var(--border) 40%, transparent)' }}>
                  <IconFilter size={14} style={{ color: 'var(--muted-foreground)', flexShrink: 0 }} />
                  <span className="flex-1 text-[13px] font-medium min-w-0 truncate" style={{ color: 'var(--foreground)' }}>
                    {f.nombre || describirRegla(f)}
                  </span>
                  <button type="button" className="btn btn-ghost h-8 px-2" title="Editar regla"
                    onClick={() => setEditandoRegla({ id: f.id, campo: (f.query || {}).campo || 'remitente', contiene: (f.query || {}).contiene || '', accion: (f.query || {}).accion || 'etiquetar', etiquetaId: (f.query || {}).etiquetaId || null })}>
                    <IconPencil size={13} />
                  </button>
                  <button type="button" className="btn btn-ghost h-8 px-2" title="Eliminar regla"
                    onClick={() => guardarFiltros(filtros.filter(x => x.id !== f.id))}>
                    <IconTrash size={13} />
                  </button>
                </div>
              ))}
              {editandoRegla ? (
                <div className="px-5 py-4 flex flex-wrap items-center gap-2" style={{ background: 'color-mix(in oklab, var(--accent) 4%, transparent)' }}>
                  <span className="text-[12.5px] font-bold" style={{ color: 'var(--foreground)' }}>Si</span>
                  <select value={editandoRegla.campo} onChange={(e) => setEditandoRegla(r => ({ ...r, campo: e.target.value }))}
                    className="h-9 px-2 rounded-lg text-[12.5px] font-semibold outline-none" style={selectStyle}>
                    <option value="remitente">el remitente</option>
                    <option value="asunto">el asunto</option>
                  </select>
                  <span className="text-[12.5px] font-bold" style={{ color: 'var(--foreground)' }}>contiene</span>
                  <input value={editandoRegla.contiene} onChange={(e) => setEditandoRegla(r => ({ ...r, contiene: e.target.value }))}
                    placeholder="texto o dirección" className="h-9 px-3 rounded-lg text-[12.5px] font-medium outline-none flex-1 min-w-[140px]" style={selectStyle} />
                  <span className="text-[12.5px] font-bold" style={{ color: 'var(--foreground)' }}>→</span>
                  <select value={editandoRegla.accion} onChange={(e) => setEditandoRegla(r => ({ ...r, accion: e.target.value }))}
                    className="h-9 px-2 rounded-lg text-[12.5px] font-semibold outline-none" style={selectStyle}>
                    <option value="etiquetar">Etiquetar</option>
                    <option value="archivar">Archivar</option>
                    <option value="spam">Mandar a Spam</option>
                  </select>
                  {editandoRegla.accion === 'etiquetar' && (
                    <select value={editandoRegla.etiquetaId || ''} onChange={(e) => setEditandoRegla(r => ({ ...r, etiquetaId: e.target.value || null }))}
                      className="h-9 px-2 rounded-lg text-[12.5px] font-semibold outline-none" style={selectStyle}>
                      <option value="">Elegí etiqueta…</option>
                      {(etiquetas || []).map(et => <option key={et.id} value={et.id}>{et.nombre}</option>)}
                    </select>
                  )}
                  <div className="flex items-center gap-2 ml-auto">
                    <button type="button" className="btn btn-ghost h-9" onClick={() => setEditandoRegla(null)}>Cancelar</button>
                    <button type="button" className="btn btn-primary h-9" disabled={guardando} onClick={commitRegla}>Guardar regla</button>
                  </div>
                </div>
              ) : (
                <div className="px-5 py-3.5">
                  <button type="button" className="btn btn-outline h-9" onClick={() => setEditandoRegla({ campo: 'remitente', contiene: '', accion: 'etiquetar', etiquetaId: (etiquetas && etiquetas[0] && etiquetas[0].id) || null })}>
                    <IconPlus size={14} />
                    <span>Agregar filtro</span>
                  </button>
                </div>
              )}
            </div>

            {/* ── Firma ── */}
            <div className="rounded-2xl overflow-hidden animate-fade-in-up" style={cardStyle}>
              <div className="px-5 py-4 flex items-center justify-between gap-3" style={{ borderBottom: '1px solid color-mix(in oklab, var(--border) 55%, transparent)' }}>
                <div>
                  <p className="text-[14px] font-extrabold" style={{ color: 'var(--foreground)' }}>Firma</p>
                  <p className="text-[12px] mt-0.5" style={{ color: 'var(--muted-foreground)' }}>
                    Se agrega al final de los correos que mandás.
                  </p>
                </div>
                <label className="inline-flex items-center gap-2 cursor-pointer flex-shrink-0">
                  <input type="checkbox" className="cc-check" checked={firmaActiva} onChange={(e) => setFirmaActiva(e.target.checked)} />
                  <span className="text-[12.5px] font-semibold" style={{ color: 'var(--foreground)' }}>Usar firma</span>
                </label>
              </div>
              <div className="px-5 py-4 space-y-3">
                <textarea
                  value={firmaHtml}
                  onChange={(e) => setFirmaHtml(e.target.value)}
                  rows={6}
                  placeholder={'Ej.:\nJuan Pérez\nMICOS S.R.L. — Ventas\nTel. 299 000-0000'}
                  className="w-full px-3 py-2.5 rounded-lg text-[13px] font-medium outline-none resize-y"
                  style={{ ...selectStyle, fontFamily: 'inherit', lineHeight: 1.6, minHeight: 120 }}
                />
                <div>
                  <p className="text-[10.5px] font-bold uppercase tracking-[0.14em] mb-1.5" style={{ color: 'var(--muted-foreground)' }}>Así se ve</p>
                  <div
                    className="rounded-lg px-4 py-3 text-[13px]"
                    style={{ border: '1px dashed var(--border)', color: firmaActiva ? 'var(--foreground)' : 'var(--muted-foreground)', opacity: firmaActiva ? 1 : 0.6, lineHeight: 1.6 }}
                    // La firma es contenido PROPIO del usuario (viene de su
                    // config, nunca de un mail ajeno) — render directo a HTML,
                    // con \n → <br> para las firmas de texto plano.
                    dangerouslySetInnerHTML={{ __html: /<[a-z][\s\S]*>/i.test(firmaHtml) ? firmaHtml : (firmaHtml || 'Sin firma todavía.').replace(/\n/g, '<br/>') }}
                  />
                </div>
                <div className="flex items-center justify-end">
                  <button type="button" className="btn btn-primary" disabled={guardando}
                    onClick={() => guardar({ firmaHtml: firmaHtml || null, firmaActiva })}>
                    Guardar firma
                  </button>
                </div>
              </div>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { CrmSidebar, CrmTopbar, LabelNavItem, CrmConfigScreen });
