// ═══════════════════════════════════════════════════════
// BAUKO CRM — Shared Components
// ═══════════════════════════════════════════════════════
/* global React, CRM_DATA */
const { useState, useEffect, useRef } = React;

// ── ErrorBoundary ─────────────────────────────────────
// Captura crashes de reconciliação do React (especialmente conflitos com Lucide DOM-mutation)
// e força remount do conteúdo após pequeno delay. Sem isso, o app inteiro trava.
// NOTA: usa `var` (não `class` declaration direta) pra criar binding global —
// classes ES6 no top-level NÃO viram globais automaticamente em script type=text/babel.
var ErrorBoundary = class extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, remountKey: 0 };
  }
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  componentDidCatch(error, info) {
    console.warn('[CRM] ErrorBoundary capturou:', error && error.message);
  }
  componentDidUpdate(prevProps, prevState) {
    if (this.state.hasError && !prevState.hasError) {
      var self = this;
      setTimeout(function() {
        self.setState(function(s){ return { hasError: false, remountKey: s.remountKey + 1 }; });
      }, 50);
    }
  }
  render() {
    if (this.state.hasError) {
      return React.createElement('div', { style: { padding: 24, color: 'var(--tx-3)', font: '400 12px var(--ff-mono)' } }, 'Recarregando…');
    }
    return React.createElement(React.Fragment, { key: 'eb-' + this.state.remountKey }, this.props.children);
  }
};
window.ErrorBoundary = ErrorBoundary;

// ── Formatters ────────────────────────────────────────
function fR(v) {
  return (v == null ? 0 : Number(v)).toLocaleString("pt-BR", { style: "currency", currency: "BRL", minimumFractionDigits: 0, maximumFractionDigits: 0 });
}
function fR2(v) {
  return (v == null ? 0 : Number(v)).toLocaleString("pt-BR", { style: "currency", currency: "BRL", minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function fN(v, d = 1) {
  return v.toLocaleString("pt-BR", { minimumFractionDigits: d, maximumFractionDigits: d });
}
function fDate(s) {
  if (!s) return "—";
  const d = new Date(s.replace(" ", "T"));
  return d.toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit", year: "numeric" });
}
function fDateTime(s) {
  if (!s) return "—";
  const d = new Date(s.replace(" ", "T"));
  return d.toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit" }) + " " + d.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
}
window.fR = fR; window.fR2 = fR2; window.fN = fN; window.fDate = fDate; window.fDateTime = fDateTime;

// ── Badge ─────────────────────────────────────────────
function Badge({ status, label, dot = true }) {
  const map = {
    ativo:          { cls: "bo", text: label || "Ativo" },
    prospecto:      { cls: "bi", text: label || "Prospecto" },
    inativo:        { cls: "bd", text: label || "Inativo" },
    enviada:             { cls: "bw", text: label || "Aguard. envio" },
    aceita:              { cls: "bo", text: label || "Aceita" },
    rascunho:            { cls: "bx", text: label || "Rascunho" },
    perdida:             { cls: "bd", text: label || "Perdida" },
    aprovada:            { cls: "bo", text: label || "Aprovada" },
    aguardando_aprovacao:{ cls: "bi", text: label || "Aguard. aprovação" },
    em_negociacao:       { cls: "bp", text: label || "Em negociação" },
    pedido:              { cls: "bo", text: label || "Pedido emitido" },
    envio_confirmado:    { cls: "bo", text: label || "Envio confirmado" },
    emitido:             { cls: "bw", text: label || "Emitido" },
    pedido_assinado:     { cls: "bo", text: label || "Assinado" },
    cancelado_correcao:       { cls: "bd", text: label || "Cancelado p/ correção" },
    cancelado_apos_assinatura:{ cls: "bd", text: label || "Cancelado após assinatura" },
    cancelado:           { cls: "bd", text: label || "Cancelado" },
    cancelada:           { cls: "bd", text: label || "Cancelada" },
    positivo:       { cls: "bo", text: label || "Positivo" },
    neutro:         { cls: "bx", text: label || "Neutro" },
    negativo:       { cls: "bd", text: label || "Negativo" },
    alta:           { cls: "bd", text: label || "Alta" },
    media:          { cls: "bw", text: label || "Média" },
    baixa:          { cls: "bx", text: label || "Baixa" },
    lead:           { cls: "bx", text: label || "Lead" },
    qualificacao:   { cls: "bi", text: label || "Qualificação" },
    proposta:       { cls: "bw", text: label || "Proposta" },
    negociacao:     { cls: "bp", text: label || "Negociação" },
    fechado_ganho:  { cls: "bo", text: label || "Ganho" },
    fechado_perdido:{ cls: "bd", text: label || "Perdido" },
  };
  const s = map[status] || { cls: "bx", text: label || status };
  return (
    <span className={"b " + s.cls} style={dot ? {} : { gap: 0 }}>
      {dot && <span className="b-dot"></span>}
      {s.text}
    </span>
  );
}
window.Badge = Badge;

// ── KPI Card ──────────────────────────────────────────
function KPICard({ eyebrow, value, unit, delta, deltaTone, sub, mono, accent }) {
  const tone = deltaTone === "neg" ? "neg" : deltaTone === "warn" ? "warn" : "pos";
  const arrow = deltaTone === "neg" ? "▼" : deltaTone === "warn" ? "·" : "▲";
  return (
    <div className="kpi-card" style={accent ? { borderTop: "3px solid var(--grn)" } : {}}>
      <div className="kpi-card__eyebrow">{eyebrow}</div>
      <div className={"kpi-card__v " + (mono ? "kpi-card__v--mono" : "")}>
        {value}{unit && <span className="kpi-card__u">{unit}</span>}
      </div>
      {delta && (
        <div className={"kpi-card__delta kpi-card__delta--" + tone}>
          {arrow} {delta}
          {sub && <span className="kpi-card__sub"> · {sub}</span>}
        </div>
      )}
    </div>
  );
}
window.KPICard = KPICard;

// ── Sidebar ───────────────────────────────────────────
function Sidebar({ active, onNav, collapsed, onToggle }) {
  // Visibilidade dos itens por papel (CRM_USER reativa a "Visualizar como")
  var _podeVerBDR = !!(window.CRM_USER && window.CRM_USER.podeVerBDR);
  const items = [
    { id: "dashboard",   icon: "layout-dashboard", label: "Dashboard" },
    { id: "pipeline",    icon: "kanban",            label: "Pipeline" },
    { id: "clientes",    icon: "building-2",        label: "Clientes" },
    { id: "carteiras",   icon: "briefcase",         label: "Carteiras" },
    { id: "frota",       icon: "truck",             label: "Frota" },
    // BDR: oculto para "comercial" (vendedor); visível para BDR, Admin e Gerência
    { id: "bdr",         icon: "users",             label: "BDR", hidden: !_podeVerBDR },
    { id: "prospeccao",  icon: "search",            label: "Prospecção" },
    { id: "propostas",   icon: "file-text",         label: "Propostas" },
    { id: "pedidos",     icon: "package",           label: "Pedidos" },
    { id: "atividades",  icon: "activity",          label: "Atividades" },
    { id: "agenda",      icon: "calendar-days",     label: "Agenda" },
  ].filter(function(it){ return !it.hidden; });
  const foot = [
    { id: "relatorios",  icon: "bar-chart-2",       label: "Relatórios" },
    { id: "config",      icon: "settings",          label: "Configurações" },
  ];
  return (
    <aside className={"sb " + (collapsed ? "sb--c" : "")} style={{ minHeight: "100vh" }}>
      <div className="sb__logo">
        {collapsed
          ? <img src="../assets/Logo Quadrado.png" alt="B"
                 style={{ width: '100%', maxWidth: 40, height: 40, display: 'block', objectFit: 'contain', margin: '0 auto' }} />
          : <img src="../assets/bauko-logo-white.png" alt="Bauko"
                 style={{ width: '100%', height: 36, display: 'block', objectFit: 'contain', objectPosition: 'left' }} />
        }
        {!collapsed && <span className="sb__logo-sub">CRM Comercial</span>}
      </div>
      <nav className="sb__nav">
        {items.map(it => (
          <button
            key={it.id}
            className={"sb__item " + (active === it.id ? "is-active" : "")}
            onClick={() => onNav(it.id)}
            title={collapsed ? it.label : ""}
          >
            <i data-lucide={it.icon}></i>
            <span>{it.label}</span>
          </button>
        ))}
      </nav>
      <div className="sb__foot">
        {foot.map(it => (
          <button key={it.id} className="sb__item" title={collapsed ? it.label : ""} onClick={() => onNav && onNav(it.id)}>
            <i data-lucide={it.icon}></i>
            <span>{it.label}</span>
          </button>
        ))}
        <a href="/hub/index.html" className="sb__item" title={collapsed ? "Voltar ao Hub" : ""}
          style={{ textDecoration:'none', opacity:0.7 }}>
          <i data-lucide="house"></i>
          <span>Voltar ao Hub</span>
        </a>
        <button className="sb__item sb__collapse" onClick={onToggle} title="Recolher menu">
          <i data-lucide={collapsed ? "chevrons-right" : "chevrons-left"}></i>
          <span>Recolher</span>
        </button>
      </div>
    </aside>
  );
}
window.Sidebar = Sidebar;

// ── MobileNav — bottom navigation bar (visível só no celular via CSS) ──
function MobileNav({ active, onNav, unreadNotifs }) {
  var items = [
    { id: "atividades",   icon: "activity",      label: "Visitas"   },
    { id: "agenda",       icon: "calendar-days", label: "Agenda"    },
    { id: "pipeline",     icon: "kanban",        label: "Pipeline"  },
    { id: "propostas",    icon: "file-text",     label: "Propostas" },
    { id: "notificacoes", icon: "bell",          label: "Alertas"   },
  ];
  return (
    <nav className="mob-nav" style={{ gridTemplateColumns: "repeat(" + items.length + ",1fr)" }}>
      {items.map(function(it) {
        var isActive = active === it.id;
        return (
          <button key={it.id}
                  className={"mob-nav__item" + (isActive ? " is-active" : "")}
                  onClick={function() { onNav(it.id); }}>
            <span style={{ position:"relative", display:"inline-flex" }}>
              <i data-lucide={it.icon}></i>
              {it.id === "notificacoes" && unreadNotifs > 0 && (
                <span className="mob-nav__badge">{unreadNotifs > 9 ? "9+" : unreadNotifs}</span>
              )}
            </span>
            <span>{it.label}</span>
          </button>
        );
      })}
    </nav>
  );
}
window.MobileNav = MobileNav;

// ── Topbar ────────────────────────────────────────────
const NOTIF_KEY  = 'bauko_crm_notifs';
const POLL_MS    = 30000; // 30s

function _loadNotifsStorage() {
  try { return JSON.parse(localStorage.getItem(NOTIF_KEY) || '[]'); } catch(e) { return []; }
}
function _saveNotifsStorage(arr) {
  try { localStorage.setItem(NOTIF_KEY, JSON.stringify(arr.slice(0, 60))); } catch(e) {}
}
function _fNotifTime(iso) {
  if (!iso) return '—';
  try {
    var d = new Date(iso), diff = Date.now() - d.getTime();
    if (diff < 60000) return 'agora';
    if (diff < 3600000) return Math.floor(diff / 60000) + ' min atrás';
    if (diff < 86400000) return 'hoje às ' + d.toLocaleTimeString('pt-BR', { hour:'2-digit', minute:'2-digit' });
    return d.toLocaleDateString('pt-BR', { day:'2-digit', month:'2-digit' }) + ' às ' + d.toLocaleTimeString('pt-BR', { hour:'2-digit', minute:'2-digit' });
  } catch(e) { return '—'; }
}

const TIPO_ICON = { cliente: 'building-2', oportunidade: 'target', proposta: 'file-text' };
const TIPO_COR  = { cliente: 'var(--accent)', oportunidade: 'var(--grn)', proposta: '#f97316' };

function Topbar({ title, eyebrow, theme, onThemeToggle, onSearch, user, onNewOp, onNav,
                  globalQ, globalOpen, globalResultados, onGlobalClose, onGlobalSelect,
                  allUsers, realUserId, onUserSwitch }) {
  const u = user || CRM_DATA.usuarios[0];
  const [notifs, setNotifs]         = useState(_loadNotifsStorage);
  const [showPanel, setShowPanel]   = useState(false);
  const [showUserMenu, setShowUserMenu] = useState(false);
  const panelRef   = useRef(null);
  const bellRef    = useRef(null);
  const userMenuRef = useRef(null);
  const userBtnRef  = useRef(null);

  const unread = notifs.filter(function(n) { return !n.lido; }).length;
  var isViewingAs = !!(realUserId && u.id !== realUserId);

  // Fecha painel notif ao clicar fora
  useEffect(function() {
    if (!showPanel) return;
    function onDown(e) {
      if (panelRef.current && !panelRef.current.contains(e.target) &&
          bellRef.current  && !bellRef.current.contains(e.target)) {
        setShowPanel(false);
      }
    }
    document.addEventListener('mousedown', onDown);
    return function() { document.removeEventListener('mousedown', onDown); };
  }, [showPanel]);

  // Fecha menu de usuário ao clicar fora
  useEffect(function() {
    if (!showUserMenu) return;
    function onDown(e) {
      if (userMenuRef.current && !userMenuRef.current.contains(e.target) &&
          userBtnRef.current  && !userBtnRef.current.contains(e.target)) {
        setShowUserMenu(false);
      }
    }
    document.addEventListener('mousedown', onDown);
    return function() { document.removeEventListener('mousedown', onDown); };
  }, [showUserMenu]);

  // Polling: verifica pedidos assinados a cada 2 min
  useEffect(function() {
    // Chave para guardar último status conhecido das propostas
    var PROP_STATUS_KEY = 'bauko_crm_prop_status';
    function _loadPropStatus() { try { return JSON.parse(localStorage.getItem(PROP_STATUS_KEY) || '{}'); } catch(e) { return {}; } }
    function _savePropStatus(obj) { try { localStorage.setItem(PROP_STATUS_KEY, JSON.stringify(obj)); } catch(e) {} }
    // Chave para guardar último status conhecido dos pedidos (cancelamentos)
    var PED_STATUS_KEY = 'bauko_crm_ped_status';
    function _loadPedStatus() { try { return JSON.parse(localStorage.getItem(PED_STATUS_KEY) || '{}'); } catch(e) { return {}; } }
    function _savePedStatus(obj) { try { localStorage.setItem(PED_STATUS_KEY, JSON.stringify(obj)); } catch(e) {} }

    function checkSigns() {
      if (!window.CRM_API) return;
      // Identifica grupo do usuário efetivo (CRM_USER reflete "Visualizar como")
      var userGroup = (window.CRM_USER && window.CRM_USER.group) || '';

      // ── 1. Pedidos assinados + cancelamentos ──────────────────────────────
      if (window.CRM_API.loadPedidos) {
        window.CRM_API.loadPedidos().then(function(pedidos) {
          if (window.CRM_DATA) window.CRM_DATA.pedidos = pedidos;
          var signed = pedidos.filter(function(p) {
            return p.status === 'pedido_assinado' && (p.cliente_aprovado_em || (p.assinatura && p.assinatura.ts));
          });
          // Detecta cancelamentos comparando com snapshot anterior (só notifica gerente)
          var pedKnown = _loadPedStatus();
          var canceladosNovos = [];
          pedidos.forEach(function(p) {
            var prev = pedKnown[p.id];
            var curr = p.status;
            var isCancelado = curr === 'cancelado_correcao' || curr === 'cancelado_apos_assinatura';
            // Só notifica gerentes em transição NOVA para cancelado
            if (isCancelado && prev && prev !== curr && userGroup === 'gerencia') {
              var cli = window.CRM_DATA && window.CRM_DATA.getCliente && window.CRM_DATA.getCliente(p.cliente_id);
              var vend = window.CRM_DATA && window.CRM_DATA.getUsuario && window.CRM_DATA.getUsuario(p.vendedor_id);
              canceladosNovos.push({
                id:          'cancelado_' + p.id + '_' + (p.updated || Date.now()),
                tipo:        curr, // cancelado_correcao ou cancelado_apos_assinatura
                pedidoId:    p.id,
                propId:      p.proposta_id || '',
                opId:        p.op_id || '',
                clienteNome: (cli && cli.razao) || p.cliente_id || '—',
                vendedorNome:(vend && vend.nome) || p.vendedor_id || '—',
                lido:        false,
                ts:          Date.now(),
              });
            }
            pedKnown[p.id] = curr;
          });
          _savePedStatus(pedKnown);

          // Filtra notificações de pedidos pelo papel: comercial só vê próprios
          var _podeVerPedAlheio = !!(window.CRM_USER && window.CRM_USER.podeVerOpAlheia);
          var _meuId = (window.CRM_USER && window.CRM_USER.userId) || '';
          setNotifs(function(prev) {
            var existingIds = new Set(prev.map(function(n) { return n.id; }));
            var newOnes = [];
            signed.forEach(function(p) {
              var nid = 'assinado_' + p.id;
              if (existingIds.has(nid)) return;
              // Comercial: só vê pedidos de oportunidades próprias
              if (!_podeVerPedAlheio && p.vendedor_id && p.vendedor_id !== _meuId) return;
              var cli = window.CRM_DATA && window.CRM_DATA.getCliente && window.CRM_DATA.getCliente(p.cliente_id);
              newOnes.push({
                id:         nid,
                tipo:       'pedido_assinado',
                pedidoId:   p.id,
                propId:     p.proposta_id || '',
                opId:       p.op_id       || '',
                clienteNome: (cli && cli.razao) || p.cliente_id || '—',
                assinante:  (p.assinatura && p.assinatura.nome) || p.assinatura_nome || '—',
                assinado_em: (p.assinatura && p.assinatura.ts) || p.cliente_aprovado_em || new Date().toISOString(),
                lido: false,
                ts: Date.now(),
              });
            });
            // Acrescenta cancelamentos novos (sem duplicar)
            canceladosNovos.forEach(function(n) {
              if (!existingIds.has(n.id)) newOnes.push(n);
            });
            if (newOnes.length === 0) return prev;
            var updated = newOnes.concat(prev);
            _saveNotifsStorage(updated);
            return updated;
          });
        }).catch(function() {});
      }

      // ── 2. Propostas: aprovação/recusa de desconto ────────────────────────
      if (window.CRM_API.loadPropostas) {
        var currentUserId = (window.CRM_USER && window.CRM_USER.userId) || '';

        window.CRM_API.loadPropostas().then(function(propostas) {
          var known = _loadPropStatus();
          var novos = [];

          propostas.forEach(function(p) {
            // Só notifica o consultor dono da proposta
            if (currentUserId && p.vendedor_id !== currentUserId) return;

            var prev = known[p.id];
            var curr = p.status;

            // Detecta transição para aprovada (gerente_aprovou)
            if (curr === 'aprovada' && prev && prev !== 'aprovada' && prev === 'aguardando_aprovacao') {
              var nid = 'aprovou_' + p.id + '_' + (p.updated || Date.now());
              var cli = window.CRM_DATA && window.CRM_DATA.getCliente ? window.CRM_DATA.getCliente(p.cliente_id) : null;
              novos.push({
                id: nid,
                tipo: 'gerente_aprovou',
                propId: p.id,
                opId: p.op_id || '',
                clienteNome: (cli && cli.razao) || p.cliente_id || '—',
                lido: false,
                ts: Date.now(),
              });
            }

            // Detecta transição para rascunho vindo de aguardando_aprovacao (gerente_recusou)
            if (curr === 'rascunho' && prev === 'aguardando_aprovacao') {
              var nid2 = 'recusou_' + p.id + '_' + (p.updated || Date.now());
              var cli2 = window.CRM_DATA && window.CRM_DATA.getCliente ? window.CRM_DATA.getCliente(p.cliente_id) : null;
              novos.push({
                id: nid2,
                tipo: 'gerente_recusou',
                propId: p.id,
                opId: p.op_id || '',
                clienteNome: (cli2 && cli2.razao) || p.cliente_id || '—',
                lido: false,
                ts: Date.now(),
              });
            }

            // Atualiza estado conhecido
            known[p.id] = curr;
          });

          _savePropStatus(known);

          if (novos.length > 0) {
            setNotifs(function(prev2) {
              var existingIds = new Set(prev2.map(function(n) { return n.id; }));
              var filtrados = novos.filter(function(n) { return !existingIds.has(n.id); });
              if (filtrados.length === 0) return prev2;
              var updated = filtrados.concat(prev2);
              _saveNotifsStorage(updated);
              return updated;
            });
          }
        }).catch(function() {});
      }
    }
    // Aguarda 6s para CRM_API estar pronto, depois polling a cada 2 min
    var t0 = setTimeout(checkSigns, 6000);
    var iv = setInterval(checkSigns, POLL_MS);
    return function() { clearTimeout(t0); clearInterval(iv); };
  }, []);

  function markAllRead() {
    setNotifs(function(prev) {
      var u = prev.map(function(n) { return Object.assign({}, n, { lido: true }); });
      _saveNotifsStorage(u); return u;
    });
  }
  function markRead(id) {
    setNotifs(function(prev) {
      var u = prev.map(function(n) { return n.id === id ? Object.assign({}, n, { lido: true }) : n; });
      _saveNotifsStorage(u); return u;
    });
  }
  function handleNotifClick(n) {
    markRead(n.id);
    setShowPanel(false);
    // Tenta opId direto; se vazio, busca via propId no CRM_DATA
    var targetOpId = n.opId || '';
    if (!targetOpId && n.propId && window.CRM_DATA && window.CRM_DATA.propostas) {
      var propMatch = window.CRM_DATA.propostas.find(function(p) { return p.id === n.propId; });
      if (propMatch && propMatch.op_id) targetOpId = propMatch.op_id;
    }
    if (targetOpId && onNav) {
      onNav('oportunidade', targetOpId);
    } else if (n.propId && onNav) {
      // Último recurso: abre pipeline para o usuário localizar manualmente
      onNav('pipeline');
    }
  }

  return (
    <header className="tb">
      <div className="tb__left">
        <div className="tb__crumbs">
          <span>Comercial</span>
          <i data-lucide="chevron-right"></i>
          <span>{eyebrow || title}</span>
        </div>
        <h1 className="tb__title">{title}</h1>
      </div>
      <div className="tb__right">
        <div className="tb__search" style={{ position: 'relative' }}>
          <i data-lucide="search"></i>
          <input
            placeholder="Buscar cliente, oportunidade, proposta..."
            value={globalQ || ''}
            onChange={function(e) { onSearch && onSearch(e.target.value); }}
            onKeyDown={function(e) { if (e.key === 'Escape') onGlobalClose && onGlobalClose(); }}
          />
          {globalQ ? (
            <span style={{ cursor: 'pointer', color: 'var(--tx-3)', fontSize: 14, padding: '0 4px' }}
              onMouseDown={function(e) { e.preventDefault(); onGlobalClose && onGlobalClose(); }}>✕</span>
          ) : <kbd>⌘K</kbd>}
          {globalOpen && globalResultados && (
            <div style={{
              position: 'absolute', top: 'calc(100% + 6px)', left: 0, right: 0,
              background: 'var(--surface)', border: '1px solid var(--border)',
              borderRadius: 'var(--r-md)', boxShadow: '0 8px 24px rgba(0,0,0,.14)',
              zIndex: 500, maxHeight: 360, overflowY: 'auto', minWidth: 340,
            }}>
              {globalResultados.length === 0 ? (
                <div style={{ padding: '20px 16px', textAlign: 'center', color: 'var(--tx-3)', font: '400 12px/1 var(--ff-body)' }}>
                  Nenhum resultado encontrado
                </div>
              ) : (
                globalResultados.map(function(item, i) {
                  return (
                    <div key={i}
                      onMouseDown={function(e) { e.preventDefault(); onGlobalSelect && onGlobalSelect(item); }}
                      style={{
                        display: 'flex', alignItems: 'center', gap: 10,
                        padding: '10px 14px', cursor: 'pointer',
                        borderBottom: i < globalResultados.length - 1 ? '1px solid var(--border)' : 'none',
                        background: 'transparent',
                      }}
                      onMouseEnter={function(e) { e.currentTarget.style.background = 'var(--surface-2)'; }}
                      onMouseLeave={function(e) { e.currentTarget.style.background = 'transparent'; }}
                    >
                      <i data-lucide={TIPO_ICON[item.tipo] || 'search'}
                        style={{ width: 14, height: 14, color: TIPO_COR[item.tipo] || 'var(--tx-3)', flexShrink: 0 }}></i>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ font: '500 12px/1.2 var(--ff-body)', color: 'var(--tx)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                          {item.label}
                        </div>
                        {item.sub && (
                          <div style={{ font: '400 11px/1 var(--ff-body)', color: 'var(--tx-3)', marginTop: 2 }}>
                            {item.sub}
                          </div>
                        )}
                      </div>
                      <span style={{ font: '500 10px/1 var(--ff-body)', color: 'var(--tx-3)', textTransform: 'uppercase',
                                     letterSpacing: '.05em', flexShrink: 0 }}>
                        {item.tipo}
                      </span>
                    </div>
                  );
                })
              )}
            </div>
          )}
        </div>
        {onNewOp && (
          <button className="btn btn-primary" onClick={onNewOp} style={{ whiteSpace:"nowrap" }}>
            <i data-lucide="plus"></i> Nova oportunidade
          </button>
        )}

        {/* ── Bell + painel de notificações ── */}
        <div style={{ position:'relative' }}>
          <button ref={bellRef} className="tb__icon" title="Notificações"
            onClick={() => setShowPanel(function(p) { return !p; })}
            style={{ position:'relative' }}>
            <i data-lucide="bell"></i>
            {unread > 0 && (
              <span style={{
                position:'absolute', top:4, right:4,
                background:'#e03131', color:'#fff', borderRadius:99,
                fontSize:9, fontWeight:700, minWidth:14, height:14,
                lineHeight:'14px', textAlign:'center', padding:'0 3px',
                pointerEvents:'none',
              }}>{unread > 9 ? '9+' : unread}</span>
            )}
          </button>

          {showPanel && (
            <div ref={panelRef} style={{
              position:'absolute', top:'calc(100% + 8px)', right:0,
              width:340, maxHeight:440,
              background:'var(--surface)', border:'1px solid var(--border)',
              borderRadius:'var(--r-lg)', boxShadow:'var(--shadow-3)',
              zIndex:9000, display:'flex', flexDirection:'column', overflow:'hidden',
            }}>
              {/* Cabeçalho */}
              <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'12px 16px', borderBottom:'1px solid var(--border)', flexShrink:0 }}>
                <span style={{ font:'600 13px/1 var(--ff-body)', color:'var(--tx)' }}>Notificações</span>
                {unread > 0 && (
                  <button onClick={markAllRead} style={{ background:'none', border:'none', cursor:'pointer', font:'500 11px/1 var(--ff-body)', color:'var(--ok)', padding:0 }}>
                    Marcar todas como lidas
                  </button>
                )}
              </div>
              {/* Lista */}
              <div style={{ overflowY:'auto', flex:1 }}>
                {notifs.length === 0 ? (
                  <div style={{ padding:'32px 16px', textAlign:'center', color:'var(--tx-3)', font:'400 13px/1.6 var(--ff-body)' }}>
                    <i data-lucide="bell-off" style={{ width:26, height:26, display:'block', margin:'0 auto 10px', color:'var(--border-2)' }}></i>
                    Nenhuma notificação ainda
                  </div>
                ) : notifs.slice(0, 5).map(function(n) {
                  return (
                    <div key={n.id} onClick={function() { handleNotifClick(n); }}
                      style={{
                        display:'flex', alignItems:'flex-start', gap:10, padding:'12px 16px',
                        cursor:'pointer', borderBottom:'1px solid var(--border)',
                        background: n.lido ? 'transparent' : 'rgba(0,124,68,.05)',
                        transition:'background .12s',
                      }}
                      onMouseEnter={function(e){ e.currentTarget.style.background='var(--surface-2, rgba(0,0,0,.04))'; }}
                      onMouseLeave={function(e){ e.currentTarget.style.background = n.lido ? 'transparent' : 'rgba(0,124,68,.05)'; }}>
                      {/* Dot não lido */}
                      <div style={{ width:7, height:7, borderRadius:'50%', background: n.lido ? 'transparent' : 'var(--ok)', flexShrink:0, marginTop:5 }} />
                      <div style={{ flex:1, minWidth:0 }}>
                        {n.tipo === 'pedido_assinado' && (
                          <>
                            <div style={{ font:'500 12px/1.4 var(--ff-body)', color:'var(--tx)', marginBottom:2 }}>
                              Pedido <strong>{n.pedidoId}</strong> assinado
                            </div>
                            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-2)', marginBottom:2 }}>
                              {n.assinante !== '—' ? n.assinante + ' · ' : ''}{_fNotifTime(n.assinado_em)}
                            </div>
                          </>
                        )}
                        {n.tipo === 'gerente_aprovou' && (
                          <>
                            <div style={{ font:'500 12px/1.4 var(--ff-body)', color:'var(--ok)', marginBottom:2 }}>
                              ✓ Desconto aprovado — <strong>{n.propId}</strong>
                            </div>
                            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-2)', marginBottom:2 }}>
                              {_fNotifTime(n.ts)}
                            </div>
                          </>
                        )}
                        {n.tipo === 'gerente_recusou' && (
                          <>
                            <div style={{ font:'500 12px/1.4 var(--ff-body)', color:'var(--danger)', marginBottom:2 }}>
                              ✗ Desconto recusado — <strong>{n.propId}</strong>
                            </div>
                            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-2)', marginBottom:2 }}>
                              {_fNotifTime(n.ts)}
                            </div>
                          </>
                        )}
                        {n.tipo === 'cancelado_correcao' && (
                          <>
                            <div style={{ font:'500 12px/1.4 var(--ff-body)', color:'var(--warn)', marginBottom:2 }}>
                              ⚠ Pedido <strong>{n.pedidoId}</strong> cancelado para correção
                            </div>
                            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-2)', marginBottom:2 }}>
                              por {n.vendedorNome} · {_fNotifTime(n.ts)}
                            </div>
                          </>
                        )}
                        {n.tipo === 'cancelado_apos_assinatura' && (
                          <>
                            <div style={{ font:'500 12px/1.4 var(--ff-body)', color:'var(--danger)', marginBottom:2 }}>
                              ⚠ Pedido assinado <strong>{n.pedidoId}</strong> foi cancelado
                            </div>
                            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-2)', marginBottom:2 }}>
                              por {n.vendedorNome} · {_fNotifTime(n.ts)}
                            </div>
                          </>
                        )}
                        {n.clienteNome !== '—' && (
                          <div style={{ font:'400 11px/1 var(--ff-body)', color:'var(--tx-3)' }}>{n.clienteNome}</div>
                        )}
                        {n.opId && (
                          <div style={{ font:'400 10px/1 var(--ff-mono)', color:'var(--tx-3)', marginTop:3 }}>{n.opId}</div>
                        )}
                      </div>
                      <i data-lucide="arrow-right" style={{ width:13, height:13, color:'var(--tx-3)', flexShrink:0, marginTop:3 }}></i>
                    </div>
                  );
                })}
              </div>
              {/* Rodapé — link histórico completo */}
              {notifs.length > 0 && (
                <div style={{ borderTop:'1px solid var(--border)', padding:'10px 16px', flexShrink:0 }}>
                  <button onClick={function(){ setShowPanel(false); onNav && onNav('notificacoes'); }}
                    style={{ background:'none', border:'none', cursor:'pointer', font:'500 12px/1 var(--ff-body)', color:'var(--ok)', padding:0, width:'100%', textAlign:'center' }}>
                    Ver histórico completo ({notifs.length}) →
                  </button>
                </div>
              )}
            </div>
          )}
        </div>

        <button className="tb__icon" onClick={onThemeToggle} title="Alternar tema">
          <i data-lucide={theme === "dark" ? "sun" : "moon"}></i>
        </button>
        {/* ── User switcher ──────────────────────────── */}
        <div ref={userBtnRef}
             className="tb__user"
             onClick={onUserSwitch ? function() { setShowUserMenu(function(o) { return !o; }); } : undefined}
             style={onUserSwitch ? { cursor:'pointer', position:'relative', userSelect:'none' } : { position:'relative' }}>
          {/* Avatar com badge "👁" quando em modo view-as */}
          <div style={{ position:'relative', flexShrink:0 }}>
            <div className="tb__avatar" style={{ background: u.avatar_color }}>{u.iniciais}</div>
            {isViewingAs && (
              <span style={{ position:'absolute', top:-3, right:-3, background:'#f59e0b',
                             borderRadius:'50%', width:14, height:14, display:'grid',
                             placeItems:'center', fontSize:8, lineHeight:1, border:'1.5px solid var(--bg)' }}>👁</span>
            )}
          </div>
          <div className="tb__meta">
            <div style={{ display:'flex', alignItems:'center', gap:4 }}>
              {u.nome.split(" ").slice(0, 2).join(" ")}
              {onUserSwitch && <i data-lucide="chevron-down" style={{ width:11, height:11, color:'var(--tx-3)', flexShrink:0 }}></i>}
            </div>
            <small style={isViewingAs ? { color:'#f59e0b' } : {}}>
              {isViewingAs ? '👁 Visualização' : u.cargo}
            </small>
          </div>

          {/* Dropdown menu */}
          {showUserMenu && onUserSwitch && (
            <div ref={userMenuRef} style={{
              position:'absolute', top:'calc(100% + 10px)', right:0, zIndex:600,
              background:'var(--bg)', border:'1px solid var(--border)', borderRadius:10,
              boxShadow:'0 8px 32px rgba(0,0,0,.14)', minWidth:230, overflow:'hidden'
            }}>
              {/* Usuário atual */}
              <div style={{ padding:'10px 14px', borderBottom:'1px solid var(--border)',
                            background:'var(--bg-2)' }}>
                <div style={{ font:'500 10px/1 var(--ff-mono)', color:'var(--tx-3)',
                              letterSpacing:'.1em', marginBottom:8 }}>USUÁRIO ATIVO</div>
                <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                  <div className="tb__avatar" style={{ background:u.avatar_color, width:26, height:26,
                                                       fontSize:10, flexShrink:0 }}>{u.iniciais}</div>
                  <div>
                    <div style={{ font:'500 12px/1.3 var(--ff-body)', color:'var(--tx-1)' }}>
                      {u.nome.split(" ").slice(0,2).join(" ")}
                    </div>
                    <div style={{ font:'400 11px/1.3 var(--ff-body)', color:'var(--tx-3)' }}>
                      {u.cargo}
                    </div>
                  </div>
                </div>
              </div>

              {/* Voltar para usuário real */}
              {isViewingAs && (function() {
                var real = (allUsers||[]).find(function(x) { return x.id === realUserId; });
                if (!real) return null;
                return (
                  <div onClick={function(e) { e.stopPropagation(); onUserSwitch(realUserId); setShowUserMenu(false); }}
                       style={{ padding:'9px 14px', cursor:'pointer', display:'flex', alignItems:'center',
                                gap:8, borderBottom:'1px solid var(--border)',
                                background:'rgba(245,158,11,.07)' }}
                       onMouseEnter={function(e) { e.currentTarget.style.background='rgba(245,158,11,.15)'; }}
                       onMouseLeave={function(e) { e.currentTarget.style.background='rgba(245,158,11,.07)'; }}>
                    <span style={{ fontSize:14, flexShrink:0 }}>↩</span>
                    <div>
                      <div style={{ font:'500 12px/1.3 var(--ff-body)', color:'#d97706' }}>
                        Sair da visualização
                      </div>
                      <div style={{ font:'400 11px/1.3 var(--ff-body)', color:'var(--tx-3)' }}>
                        Voltar para {real.nome.split(" ").slice(0,2).join(" ")}
                      </div>
                    </div>
                  </div>
                );
              })()}

              {/* Lista de outros usuários */}
              <div style={{ padding:'6px 0', maxHeight:260, overflowY:'auto' }}>
                <div style={{ padding:'6px 14px 4px', font:'500 10px/1 var(--ff-mono)',
                              color:'var(--tx-3)', letterSpacing:'.1em' }}>VISUALIZAR COMO</div>
                {(allUsers||[]).filter(function(x) { return x.id !== u.id; }).map(function(x) {
                  return (
                    <div key={x.id}
                         onClick={function(e) { e.stopPropagation(); onUserSwitch(x.id); setShowUserMenu(false); }}
                         style={{ padding:'7px 14px', cursor:'pointer', display:'flex',
                                  alignItems:'center', gap:8 }}
                         onMouseEnter={function(e) { e.currentTarget.style.background='var(--bg-2)'; }}
                         onMouseLeave={function(e) { e.currentTarget.style.background=''; }}>
                      <div className="tb__avatar" style={{ background:x.avatar_color, width:26, height:26,
                                                           fontSize:10, flexShrink:0 }}>{x.iniciais}</div>
                      <div style={{ flex:1, minWidth:0 }}>
                        <div style={{ font:'500 12px/1.3 var(--ff-body)', color:'var(--tx-1)' }}>
                          {x.nome.split(" ").slice(0,2).join(" ")}
                        </div>
                        <div style={{ font:'400 11px/1.3 var(--ff-body)', color:'var(--tx-3)' }}>
                          {x.cargo}
                        </div>
                      </div>
                      {x.id === realUserId && (
                        <span style={{ font:'400 10px/1 var(--ff-mono)', color:'var(--tx-3)',
                                       flexShrink:0 }}>você</span>
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
          )}
        </div>
      </div>
    </header>
  );
}
window.Topbar = Topbar;

// ── Panel ─────────────────────────────────────────────
function Panel({ title, meta, actions, children, noPad }) {
  return (
    <div className="panel">
      {(title || actions) && (
        <div className="panel__hd">
          {title && <h3>{title}</h3>}
          {meta && <span className="meta">{meta}</span>}
          {actions && <div style={{ display: "flex", gap: 8 }}>{actions}</div>}
        </div>
      )}
      {noPad ? children : <div className="panel__body">{children}</div>}
    </div>
  );
}
window.Panel = Panel;

// ── Modal ─────────────────────────────────────────────
function Modal({ open, onClose, title, subtitle, children, wide, xl }) {
  useEffect(() => {
    const h = e => { if (e.key === "Escape") onClose && onClose(); };
    if (open) document.addEventListener("keydown", h);
    return () => document.removeEventListener("keydown", h);
  }, [open, onClose]);
  if (!open) return null;
  const maxW = xl ? 1100 : (wide ? 680 : 500);
  return (
    <div className="modal-overlay" onClick={e => e.target === e.currentTarget && onClose && onClose()}>
      <div className="modal-box" style={{ maxWidth: maxW }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 4 }}>
          <div>
            <div className="modal-title">{title}</div>
            {subtitle && <div className="modal-sub">{subtitle}</div>}
          </div>
          <button onClick={onClose} className="modal-close-btn">
            <i data-lucide="x"></i>
          </button>
        </div>
        {children}
      </div>
    </div>
  );
}
window.Modal = Modal;

// ── FormField ─────────────────────────────────────────
function FormField({ label, hint, children, col }) {
  return (
    <div className="f" style={col ? { gridColumn: `span ${col}` } : {}}>
      <label>{label}{hint && <span className="hint"> · {hint}</span>}</label>
      {children}
    </div>
  );
}
window.FormField = FormField;

// ── Atividade Icon ────────────────────────────────────
function AtivIcon({ tipo, size = 16 }) {
  const map    = { ligacao: "phone", whatsapp: "message-circle", visita: "map-pin", email: "mail", followup: "clock", reuniao: "users" };
  const icon   = map[tipo] || "activity";
  const colors = { ligacao: "var(--grn)", whatsapp: "#25d366", visita: "var(--info)", email: "var(--warn)", followup: "var(--tx-3)", reuniao: "var(--ok)" };
  return (
    <span style={{
      width: size + 12, height: size + 12, borderRadius: "50%",
      background: "var(--surface-2)", border: "1px solid var(--border)",
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      flexShrink: 0, color: colors[tipo] || "var(--tx-3)"
    }}>
      <i data-lucide={icon} style={{ width: size, height: size }}></i>
    </span>
  );
}
window.AtivIcon = AtivIcon;

// ── CRM_CONFIRM — substituição para window.confirm() ──────────────────────
// Uso: await window.CRM_CONFIRM('Mensagem')  → true | false
// Opts: { title, confirmLabel, cancelLabel, danger }
window.CRM_CONFIRM = function(msg, opts) {
  opts = opts || {};
  var title        = opts.title        || 'Confirmar ação';
  var confirmLabel = opts.confirmLabel || 'Confirmar';
  var cancelLabel  = opts.cancelLabel  || 'Cancelar';
  var danger       = opts.danger !== false;

  return new Promise(function(resolve) {
    // Overlay
    var overlay = document.createElement('div');
    overlay.style.cssText = [
      'position:fixed','inset:0','background:rgba(0,0,0,.5)',
      'z-index:99999','display:flex','align-items:center',
      'justify-content:center','padding:16px',
    ].join(';');

    // Box
    var box = document.createElement('div');
    box.style.cssText = [
      'background:var(--surface-1,#fff)','border-radius:12px',
      'box-shadow:0 8px 32px rgba(0,0,0,.22)','padding:24px 24px 20px',
      'max-width:420px','width:100%',
      'font-family:var(--ff-sans,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif)',
    ].join(';');

    // Title
    var h = document.createElement('p');
    h.style.cssText = 'margin:0 0 8px;font-size:15px;font-weight:600;color:var(--tx-1,#111);';
    h.textContent = title;

    // Message
    var p = document.createElement('p');
    p.style.cssText = 'margin:0 0 20px;font-size:13.5px;color:var(--tx-2,#444);line-height:1.5;white-space:pre-line;';
    p.textContent = msg;

    // Button row
    var row = document.createElement('div');
    row.style.cssText = 'display:flex;justify-content:flex-end;gap:8px;';

    var btnCancel = document.createElement('button');
    btnCancel.textContent = cancelLabel;
    btnCancel.style.cssText = [
      'padding:7px 16px','font-size:13px','border-radius:6px','cursor:pointer',
      'border:1px solid var(--border,#ddd)','background:transparent',
      'color:var(--tx-2,#555)','transition:background .15s',
    ].join(';');

    var btnOk = document.createElement('button');
    btnOk.textContent = confirmLabel;
    btnOk.style.cssText = [
      'padding:7px 16px','font-size:13px','border-radius:6px','cursor:pointer',
      'border:none','font-weight:600',
      danger
        ? 'background:#dc2626;color:#fff;'
        : 'background:var(--green-1,#007c44);color:#fff;',
      'transition:opacity .15s',
    ].join(';');

    row.appendChild(btnCancel);
    row.appendChild(btnOk);

    box.appendChild(h);
    box.appendChild(p);
    box.appendChild(row);
    overlay.appendChild(box);
    document.body.appendChild(overlay);

    function close(result) {
      if (overlay.parentNode) document.body.removeChild(overlay);
      document.removeEventListener('keydown', onKey);
      resolve(result);
    }

    function onKey(e) { if (e.key === 'Escape') close(false); }
    document.addEventListener('keydown', onKey);

    btnCancel.addEventListener('click', function() { close(false); });
    btnOk.addEventListener('click',     function() { close(true); });
    overlay.addEventListener('click',   function(e) { if (e.target === overlay) close(false); });

    // Foco no botão cancelar por segurança (previne Enter acidental confirmando)
    setTimeout(function() { btnCancel.focus(); }, 10);
  });
};
