// Desasf — shared icons, helpers, navigation

// Global navigate function (set by App)
function navigate(screenId, data) {
  if (window._desasfNavigate) window._desasfNavigate(screenId, data);
}
function openModal(modalId, data) {
  if (window._desasfOpenModal) window._desasfOpenModal(modalId, data);
}

const Icon = {
  dashboard: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></svg>,
  ticket: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M3 7a2 2 0 012-2h14a2 2 0 012 2v3a2 2 0 100 4v3a2 2 0 01-2 2H5a2 2 0 01-2-2v-3a2 2 0 100-4V7z"/><path d="M13 5v14" strokeDasharray="2 2"/></svg>,
  cash: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><rect x="2" y="6" width="20" height="12" rx="2"/><circle cx="12" cy="12" r="3"/><path d="M6 10v.01M18 14v.01"/></svg>,
  users: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><circle cx="9" cy="8" r="3.5"/><path d="M2 20c0-3.5 3.1-6 7-6s7 2.5 7 6"/><circle cx="17" cy="7" r="2.5"/><path d="M16 20c0-2.5 1.5-4.5 5-4.5"/></svg>,
  catalog: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M4 5a2 2 0 012-2h11l3 3v15a2 2 0 01-2 2H6a2 2 0 01-2-2V5z"/><path d="M8 9h8M8 13h8M8 17h5"/></svg>,
  help: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><circle cx="12" cy="12" r="9"/><path d="M9.5 9a2.5 2.5 0 015 0c0 1.5-2.5 2-2.5 4M12 17.5v.01"/></svg>,
  audit: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M9 4h6l4 4v12a2 2 0 01-2 2H7a2 2 0 01-2-2V6a2 2 0 012-2z"/><path d="M9 12l2 2 4-4"/></svg>,
  reports: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M4 20V10M10 20V4M16 20v-7M22 20H2"/></svg>,
  repo: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><rect x="3" y="3" width="18" height="6" rx="1"/><rect x="3" y="11" width="18" height="6" rx="1"/><path d="M7 6h.01M7 14h.01M5 21h14"/></svg>,
  settings: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 00.3 1.8l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.8-.3 1.7 1.7 0 00-1 1.5V21a2 2 0 11-4 0v-.1a1.7 1.7 0 00-1.1-1.5 1.7 1.7 0 00-1.8.3l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.7 1.7 0 00.3-1.8 1.7 1.7 0 00-1.5-1H3a2 2 0 110-4h.1A1.7 1.7 0 004.6 9a1.7 1.7 0 00-.3-1.8l-.1-.1a2 2 0 112.8-2.8l.1.1a1.7 1.7 0 001.8.3h.1a1.7 1.7 0 001-1.5V3a2 2 0 114 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.8-.3l.1-.1a2 2 0 112.8 2.8l-.1.1a1.7 1.7 0 00-.3 1.8v.1a1.7 1.7 0 001.5 1H21a2 2 0 110 4h-.1a1.7 1.7 0 00-1.5 1z"/></svg>,
  sales: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M3 12l4-4 4 4 4-6 6 8"/><path d="M3 19h18"/></svg>,
  search: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.5-4.5"/></svg>,
  bell: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M6 8a6 6 0 1112 0c0 5 2 6 2 6H4s2-1 2-6z"/><path d="M10 19a2 2 0 004 0"/></svg>,
  filter: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M3 5h18l-7 8v6l-4 2v-8L3 5z"/></svg>,
  plus: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 5v14M5 12h14"/></svg>,
  download: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M12 4v12M6 10l6 6 6-6M4 20h16"/></svg>,
  upload: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M12 16V4M6 10l6-6 6 6M4 20h16"/></svg>,
  arrow: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  arrowUp: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M7 14l5-5 5 5"/></svg>,
  arrowDown: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M7 10l5 5 5-5"/></svg>,
  more: <svg viewBox="0 0 24 24" fill="currentColor"><circle cx="6" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="18" cy="12" r="1.6"/></svg>,
  truck: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><rect x="1" y="6" width="13" height="10" rx="1"/><path d="M14 10h4l3 3v3h-7"/><circle cx="6" cy="18" r="2"/><circle cx="17" cy="18" r="2"/></svg>,
  beaker: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M9 3h6M10 3v6L4 19a2 2 0 002 2h12a2 2 0 002-2L14 9V3"/><path d="M7 14h10"/></svg>,
  doc: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M14 3H6a2 2 0 00-2 2v14a2 2 0 002 2h12a2 2 0 002-2V9z"/><path d="M14 3v6h6M9 13h6M9 17h4"/></svg>,
  check: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2"><path d="M5 12l5 5 9-11"/></svg>,
  clock: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>,
  pin: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M12 22s7-7 7-13a7 7 0 10-14 0c0 6 7 13 7 13z"/><circle cx="12" cy="9" r="2.5"/></svg>,
  phone: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M22 16.9v3a2 2 0 01-2.2 2 19 19 0 01-8.3-3 19 19 0 01-6-6 19 19 0 01-3-8.4A2 2 0 014.5 2h3a2 2 0 012 1.7c.1 1 .3 2 .6 2.9a2 2 0 01-.5 2.1L8.1 10a16 16 0 006 6l1.3-1.3a2 2 0 012.1-.5c1 .3 1.9.5 2.9.6a2 2 0 011.7 2z"/></svg>,
  mail: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>,
  building: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><rect x="4" y="2" width="16" height="20"/><path d="M8 6h.01M12 6h.01M16 6h.01M8 10h.01M12 10h.01M16 10h.01M8 14h.01M12 14h.01M16 14h.01M10 22v-4h4v4"/></svg>,
  x: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M18 6L6 18M6 6l12 12"/></svg>,
  logout: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><path d="M16 17l5-5-5-5"/><path d="M21 12H9"/></svg>,
};

function logout() {
  if (window._desasfLogout) window._desasfLogout();
}

function fmtNum(n, decimals) {
  const x = Number(n);
  if (!isFinite(x)) return '';
  const opts = decimals != null
    ? { minimumFractionDigits: decimals, maximumFractionDigits: decimals }
    : { maximumFractionDigits: 2 };
  return x.toLocaleString('en-US', opts);
}
function fmtMoney(n, currency) {
  const cur = currency || (window._appConfig?.moneda) || 'PEN';
  const sym = { PEN: 'S/', USD: '$', EUR: '€' }[cur] || cur;
  return sym + ' ' + fmtNum(n, 2);
}

function solicitudTitulo(sol) {
  if (!sol) return '';
  const proy = (sol.proyecto || '').trim();
  if (proy) return proy;
  if (sol.producto_nombre && sol.volumen != null) {
    const u = sol.unidad || 'm³';
    return `${sol.producto_nombre} — ${fmtNum(sol.volumen)} ${u}`;
  }
  return sol.producto_nombre || sol.ticket || '';
}
function solicitudSubtitulo(sol) {
  if (!sol) return '';
  const parts = [];
  if (sol.ticket) parts.push(sol.ticket);
  if ((sol.proyecto || '').trim() && sol.producto_nombre) {
    const u = sol.unidad || 'm³';
    const vol = sol.volumen != null ? `${fmtNum(sol.volumen)} ${u} ` : '';
    parts.push(`${vol}${sol.producto_nombre}`);
  }
  if (sol.oc_numero) parts.push(`OC ${sol.oc_numero}`);
  return parts.join(' · ');
}

function exportCSV(filename, rows, columns) {
  const escape = (v) => {
    if (v == null) return '';
    const s = String(v).replace(/"/g, '""');
    return /[",\n]/.test(s) ? `"${s}"` : s;
  };
  const header = columns.map(c => escape(c.label)).join(',');
  const body   = rows.map(r => columns.map(c =>
    escape(typeof c.value === 'function' ? c.value(r) : r[c.value])
  ).join(',')).join('\n');
  const csv  = '﻿' + header + '\n' + body;
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
  const url  = URL.createObjectURL(blob);
  const a    = document.createElement('a');
  a.href = url; a.download = filename;
  document.body.appendChild(a); a.click(); a.remove();
  URL.revokeObjectURL(url);
}

function DesasfLogo({ size = 32 }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: 6,
      background: 'var(--hi-vis)',
      display: 'grid', placeItems: 'center',
      fontFamily: 'var(--cond)', fontWeight: 700,
      color: 'var(--ink-0)', fontSize: size * 0.56,
      letterSpacing: '-0.04em', position: 'relative', overflow: 'hidden'
    }}>
      <svg viewBox="0 0 32 32" width={size * 0.7} height={size * 0.7} style={{ position: 'absolute' }}>
        <path d="M4 22 L14 8 L18 14 L28 22" stroke="#0B0D0E" strokeWidth="3" fill="none" strokeLinecap="square"/>
        <circle cx="14" cy="8" r="2" fill="#0B0D0E"/>
      </svg>
    </div>
  );
}

function Sidebar({ active = 'dashboard' }) {
  const [counts, setCounts] = React.useState({ solicitudes: null, pagos: null });

  React.useEffect(() => {
    DesasfAPI.get('/dashboard/stats')
      .then(s => setCounts({
        solicitudes: Number(s?.solicitudes?.total ?? 0) || null,
        pagos:       Number(s?.pagos?.por_validar ?? 0) || null,
      }))
      .catch(() => {});
  }, []);

  const u      = DesasfAPI.getCurrentUser() || {};
  const parts  = (u.nombre || 'Usuario').trim().split(/\s+/);
  const initials = parts.length >= 2
    ? (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
    : (parts[0]?.[0] || '?').toUpperCase();
  const displayName = parts.length >= 2
    ? `${parts[0][0].toUpperCase()}. ${parts[parts.length - 1]}`
    : parts[0] || 'Usuario';
  const rolLabels = { dev: 'Dev', admin: 'Admin', gerente: 'Gerente', finanzas: 'Finanzas',
    vendedor: 'Asist. téc. com.', operador_planta: 'Planta', conductor: 'Conductor',
    gerente_general: 'Gte. General',
    gerente_comercial: 'Gte. Comercial', cliente: 'Cliente', solo_lectura: 'Lectura' };
  const rolLabel = rolLabels[u.rol] || u.rol || '';

  // Cada apartado se muestra solo si el rol tiene el permiso que la pantalla
  // necesita — sin permiso, el item simplemente no aparece.
  const hasPerm = DesasfAPI.hasPerm;
  const items = [
    { id: 'dashboard',        label: 'Dashboard',          icon: Icon.dashboard },
    hasPerm('solicitudes.ver') &&
      { id: 'solicitudes',      label: 'Solicitudes',        icon: Icon.ticket,  count: counts.solicitudes },
    hasPerm('pagos.ver') &&
      { id: 'pagos',            label: 'Pagos y depósitos',  icon: Icon.cash,    count: counts.pagos },
    hasPerm('clientes.ver') &&
      { id: 'gestion-clientes', label: 'Empresas clientes',  icon: Icon.users },
    hasPerm('catalogo.ver') &&
      { id: 'catalogo',         label: 'Catálogo',           icon: Icon.catalog },
    hasPerm('logistica.ver') &&
      { id: 'logistica',        label: 'Logística',          icon: Icon.truck },
    (hasPerm('reportes.ver') || u.rol === 'vendedor') &&
      { id: 'fuerza',           label: 'Fuerza de ventas',   icon: Icon.sales },
  ].filter(Boolean);
  const items2 = [
    hasPerm('reportes.ver') &&
      { id: 'reportes',  label: 'Reportes',        icon: Icon.reports },
    hasPerm('auditoria.ver') &&
      { id: 'auditoria', label: 'Auditoría',       icon: Icon.audit },
    { id: 'ayuda',       label: 'Centro de ayuda', icon: Icon.help },
    hasPerm('config.ver') &&
      { id: 'config',    label: 'Configuración',   icon: Icon.settings },
  ].filter(Boolean);
  return (
    <aside className="sidebar">
      <div className="sidebar__brand" style={{ cursor: 'pointer' }} onClick={() => navigate('dashboard')}>
        <DesasfLogo size={32}/>
        <div>
          <div className="name">{(window._appConfig?.panel_nombre) || 'DESASF'}<small>Panel</small></div>
        </div>
      </div>
      <div className="sidebar__group">
        <div className="sidebar__group-title">Operación</div>
        {items.map(it => (
          <div key={it.id}
            className={`nav-item ${it.id === active ? 'is-active' : ''}`}
            style={{ cursor: 'pointer' }}
            onClick={() => navigate(it.id)}>
            {it.icon}
            <span>{it.label}</span>
            {it.count != null && <span className="count">{it.count}</span>}
          </div>
        ))}
      </div>
      <div className="sidebar__group">
        <div className="sidebar__group-title">Información</div>
        {items2.map(it => (
          <div key={it.id}
            className={`nav-item ${it.id === active ? 'is-active' : ''}`}
            style={{ cursor: 'pointer' }}
            onClick={() => navigate(it.id)}>
            {it.icon}
            <span>{it.label}</span>
          </div>
        ))}
      </div>
      <div className="sidebar__bottom">
        <div className="avatar" onClick={() => navigate('mi-cuenta')} style={{ cursor: 'pointer' }} title="Mi cuenta">{initials}</div>
        <div className="who" onClick={() => navigate('mi-cuenta')} style={{ cursor: 'pointer' }}>
          {displayName}
          <small>{rolLabel}</small>
        </div>
        <div className="icon-btn" onClick={logout} title="Cerrar sesión"
          style={{ marginLeft: 'auto', color: 'var(--ink-5)' }}>
          {Icon.logout}
        </div>
      </div>
    </aside>
  );
}

// Helper: elige Sidebar o CliSidebar según rol
function AppSidebar({ active }) {
  const u = DesasfAPI.getCurrentUser() || {};
  if (u.rol !== 'cliente') return <Sidebar active={active}/>;
  const map = {
    dashboard:  'inicio',
    clientes:   'docs',
    logistica:  'despachos',
    'logistica-cliente': 'despachos',
    'cliente-final': 'inicio',
    'mi-vendedor': 'vendedor',
    'mis-documentos': 'docs',
    'mi-cuenta': 'mi-cuenta',
  };
  return <CliSidebar active={map[active] || active}/>;
}

// Client-facing sidebar (simplified)
function CliSidebar({ active = 'inicio' }) {
  const items = [
    { id: 'inicio',       screen: 'cliente-final', label: 'Inicio',             icon: Icon.dashboard },
    { id: 'solicitudes',  screen: 'solicitudes',   label: 'Mis solicitudes',    icon: Icon.ticket },
    { id: 'pagos',        screen: 'pagos',         label: 'Pagos y facturas',   icon: Icon.cash },
    { id: 'despachos',    screen: 'logistica-cliente', label: 'Despachos',      icon: Icon.truck },
    { id: 'catalogo',     screen: 'catalogo',      label: 'Catálogo',           icon: Icon.catalog },
  ];
  const items2 = [
    { id: 'ayuda',        screen: 'ayuda',         label: 'Centro de ayuda',    icon: Icon.help },
    { id: 'vendedor',     screen: 'mi-vendedor',   label: 'Mi asistente téc.',  icon: Icon.users },
    { id: 'docs',         screen: 'mis-documentos', label: 'Mis documentos',    icon: Icon.repo },
    { id: 'mi-cuenta',    screen: 'mi-cuenta',     label: 'Mi cuenta',          icon: Icon.settings },
  ];
  return (
    <aside className="sidebar">
      <div className="sidebar__brand" style={{ cursor: 'pointer' }} onClick={() => navigate('cliente-final')}>
        <DesasfLogo size={32}/>
        <div>
          <div className="name">{(window._appConfig?.panel_nombre) || 'DESASF'}<small>Mi cuenta · Cliente</small></div>
        </div>
      </div>
      <div className="sidebar__group">
        <div className="sidebar__group-title">Mi cuenta</div>
        {items.map(it => (
          <div key={it.id}
            className={`nav-item ${it.id === active ? 'is-active' : ''}`}
            style={{ cursor: 'pointer' }}
            onClick={() => navigate(it.screen)}>
            {it.icon}<span>{it.label}</span>
            {it.count != null && <span className="count">{it.count}</span>}
          </div>
        ))}
      </div>
      <div className="sidebar__group">
        <div className="sidebar__group-title">Soporte</div>
        {items2.map(it => (
          <div key={it.id}
            className={`nav-item ${it.id === active ? 'is-active' : ''}`}
            style={{ cursor: 'pointer' }}
            onClick={() => navigate(it.screen)}>
            {it.icon}<span>{it.label}</span>
          </div>
        ))}
      </div>
      <div className="sidebar__bottom">
        {(() => {
          const cu = DesasfAPI.getCurrentUser() || {};
          const cParts = (cu.nombre || 'Cliente').trim().split(/\s+/);
          const cInit = cParts.length >= 2
            ? (cParts[0][0] + cParts[cParts.length-1][0]).toUpperCase()
            : (cParts[0]?.[0] || '?').toUpperCase();
          const cName = cParts.length >= 2
            ? `${cParts[0][0].toUpperCase()}. ${cParts[cParts.length-1]}`
            : cParts[0] || 'Cliente';
          return (<>
            <div className="avatar">{cInit}</div>
            <div className="who">{cName}<small>Mi cuenta</small></div>
            <div className="icon-btn" onClick={logout} title="Cerrar sesión"
              style={{ marginLeft: 'auto', color: 'var(--ink-5)' }}>
              {Icon.logout}
            </div>
          </>);
        })()}
      </div>
    </aside>
  );
}

function Topbar({ crumbs = ['Dashboard'], cta }) {
  const [searchQ,     setSearchQ]     = React.useState('');
  const [searchRes,   setSearchRes]   = React.useState(null);
  const [searchOpen,  setSearchOpen]  = React.useState(false);
  const [searchLoad,  setSearchLoad]  = React.useState(false);
  const [notifOpen,   setNotifOpen]   = React.useState(false);
  const [notifs,      setNotifs]      = React.useState([]);
  const [notifLoad,   setNotifLoad]   = React.useState(false);
  const searchTimer = React.useRef(null);
  const wrapperRef  = React.useRef(null);

  const u = DesasfAPI.getCurrentUser() || {};
  const isCliente = u.rol === 'cliente';

  React.useEffect(() => {
    function onDocClick(e) {
      if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
        setSearchOpen(false);
        setNotifOpen(false);
      }
    }
    function onKey(e) {
      if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        const el = document.getElementById('topbar-search-input');
        if (el) { el.focus(); setSearchOpen(true); }
      }
      if (e.key === 'Escape') { setSearchOpen(false); setNotifOpen(false); }
    }
    document.addEventListener('mousedown', onDocClick);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('mousedown', onDocClick);
      document.removeEventListener('keydown', onKey);
    };
  }, []);

  function loadNotifs() {
    setNotifLoad(true);
    DesasfAPI.get('/dashboard/notificaciones')
      .then(d => setNotifs(d.items || []))
      .catch(() => setNotifs([]))
      .finally(() => setNotifLoad(false));
  }

  React.useEffect(() => {
    loadNotifs();
    const id = setInterval(loadNotifs, 60000);
    return () => clearInterval(id);
  }, []);

  function onSearchChange(v) {
    setSearchQ(v);
    setSearchOpen(true);
    if (searchTimer.current) clearTimeout(searchTimer.current);
    if (v.trim().length < 2) { setSearchRes(null); return; }
    setSearchLoad(true);
    searchTimer.current = setTimeout(() => {
      DesasfAPI.get('/dashboard/buscar?q=' + encodeURIComponent(v.trim()))
        .then(d => setSearchRes(d))
        .catch(() => setSearchRes(null))
        .finally(() => setSearchLoad(false));
    }, 200);
  }

  function openSolicitud(id) {
    setSearchOpen(false); setSearchQ('');
    navigate('solicitud-detalle', { solicitudId: id });
  }
  function openCliente(id) {
    setSearchOpen(false); setSearchQ('');
    navigate('clientes', { clienteId: id });
  }
  function openProducto(_id) {
    setSearchOpen(false); setSearchQ('');
    navigate(isCliente ? 'catalogo' : 'catalogo');
  }

  function clickNotif(n) {
    setNotifOpen(false);
    if (n.link) navigate(n.link.screen, n.link.payload || {});
  }

  function fmtTime(d) {
    if (!d) return '';
    return window.formatRelativeTime ? window.formatRelativeTime(d) : new Date(d).toLocaleString('es-PE');
  }

  const tipoIcon = {
    pago: Icon.cash, solicitud: Icon.ticket,
    despacho: Icon.truck, stock: Icon.beaker,
  };

  const hasResults = searchRes && (searchRes.solicitudes?.length || searchRes.empresas?.length || searchRes.productos?.length);

  return (
    <header className="topbar" ref={wrapperRef}>
      <div className="crumb">
        {crumbs.map((c, i) => (
          <React.Fragment key={i}>
            {i > 0 && <span style={{ color: 'var(--ink-7)' }}>/</span>}
            {i === crumbs.length - 1 ? <b>{c}</b> : <span>{c}</span>}
          </React.Fragment>
        ))}
      </div>

      <div className="topbar__search" style={{ position: 'relative', cursor: 'text' }}
        onClick={() => { const el = document.getElementById('topbar-search-input'); if (el) el.focus(); setSearchOpen(true); }}>
        {Icon.search}
        <input id="topbar-search-input" value={searchQ} onChange={e => onSearchChange(e.target.value)}
          onFocus={() => setSearchOpen(true)}
          placeholder="Buscar solicitud, cliente, producto…"
          style={{ border: 0, background: 'transparent', outline: 'none', flex: 1, fontSize: 13, color: 'var(--ink-1)', padding: 0, fontFamily: 'inherit' }}/>
        {!searchQ && <kbd>⌘K</kbd>}
        {searchOpen && (searchQ.trim().length >= 2) && (
          <div style={{ position: 'absolute', top: 'calc(100% + 4px)', left: 0, right: 0, background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 8, boxShadow: '0 4px 20px rgba(0,0,0,.14)', zIndex: 400, maxHeight: 420, overflowY: 'auto' }}>
            {searchLoad && <div style={{ padding: 14, fontSize: 12, color: 'var(--ink-5)' }}>Buscando…</div>}
            {!searchLoad && !hasResults && (
              <div style={{ padding: 14, fontSize: 12, color: 'var(--ink-5)' }}>Sin resultados para "{searchQ}"</div>
            )}
            {searchRes?.solicitudes?.length > 0 && (
              <div>
                <div style={{ padding: '8px 14px 4px', fontSize: 10, color: 'var(--ink-5)', fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase' }}>Solicitudes</div>
                {searchRes.solicitudes.map(s => (
                  <div key={'s'+s.id} className="menu-item" onClick={() => openSolicitud(s.id)}>
                    {Icon.ticket}
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12, fontWeight: 600 }}>
                        {s.proyecto ? `${s.proyecto} · ${s.ticket}` : `${s.ticket} · ${s.cliente_nombre}`}
                      </div>
                      <div style={{ fontSize: 11, color: 'var(--ink-5)' }}>
                        {s.proyecto ? `${s.cliente_nombre} · ` : ''}{fmtNum(s.volumen)} {s.unidad} {s.producto_nombre}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            )}
            {searchRes?.empresas?.length > 0 && (
              <div>
                <div style={{ padding: '8px 14px 4px', fontSize: 10, color: 'var(--ink-5)', fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase', borderTop: '1px solid var(--line)' }}>Empresas</div>
                {searchRes.empresas.map(e => (
                  <div key={'e'+e.id} className="menu-item" onClick={() => openCliente(e.id)}>
                    {Icon.users}
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12, fontWeight: 600 }}>{e.razon_social}</div>
                      <div style={{ fontSize: 11, color: 'var(--ink-5)' }}>RUC {e.ruc}</div>
                    </div>
                  </div>
                ))}
              </div>
            )}
            {searchRes?.productos?.length > 0 && (
              <div>
                <div style={{ padding: '8px 14px 4px', fontSize: 10, color: 'var(--ink-5)', fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase', borderTop: '1px solid var(--line)' }}>Productos</div>
                {searchRes.productos.map(p => (
                  <div key={'p'+p.id} className="menu-item" onClick={() => openProducto(p.id)}>
                    {Icon.beaker}
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12, fontWeight: 600 }}>{p.nombre}</div>
                      <div style={{ fontSize: 11, color: 'var(--ink-5)' }}>{p.codigo} · S/ {Number(p.precio_base).toLocaleString('es-PE')}/{p.unidad}</div>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}
      </div>

      <div className="icon-btn" onClick={() => { setNotifOpen(o => !o); setSearchOpen(false); if (!notifOpen) loadNotifs(); }}
        style={{ position: 'relative' }} title="Notificaciones">
        {Icon.bell}
        {notifs.length > 0 && <span className="dot"></span>}
        {notifOpen && (
          <div onClick={e => e.stopPropagation()} style={{ position: 'absolute', top: 'calc(100% + 6px)', right: 0, width: 360, background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 8, boxShadow: '0 8px 28px rgba(0,0,0,.18)', zIndex: 400, maxHeight: 480, overflowY: 'auto' }}>
            <div style={{ padding: '10px 14px', borderBottom: '1px solid var(--line)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <span style={{ fontSize: 13, fontWeight: 600 }}>Notificaciones</span>
              <span style={{ fontSize: 11, color: 'var(--ink-5)' }}>{notifs.length} pendientes</span>
            </div>
            {notifLoad && <div style={{ padding: 16, fontSize: 12, color: 'var(--ink-5)' }}>Cargando…</div>}
            {!notifLoad && notifs.length === 0 && (
              <div style={{ padding: '24px 16px', fontSize: 12, color: 'var(--ink-5)', textAlign: 'center' }}>
                Sin notificaciones pendientes.
              </div>
            )}
            {!notifLoad && notifs.map((n, i) => (
              <div key={i} className="menu-item" onClick={() => clickNotif(n)}
                style={{ padding: '10px 14px', borderBottom: i < notifs.length - 1 ? '1px solid var(--line)' : 0, alignItems: 'flex-start' }}>
                <div style={{ flexShrink: 0, color: 'var(--ink-5)', marginTop: 2 }}>{tipoIcon[n.tipo] || Icon.bell}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-1)' }}>{n.titulo}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-4)' }}>{n.mensaje}</div>
                  <div style={{ fontSize: 10, color: 'var(--ink-5)', marginTop: 2 }}>{fmtTime(n.fecha)}</div>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      <div className="icon-btn" onClick={() => navigate(isCliente ? 'ayuda' : 'ayuda')} title="Centro de ayuda">{Icon.help}</div>

      {cta || (
        !isCliente && DesasfAPI.hasPerm('solicitudes.crear') ? (
          <button className="btn btn--accent" onClick={() => openModal('nueva-solicitud')}>
            {Icon.plus}<span>Nueva solicitud</span>
          </button>
        ) : null
      )}
    </header>
  );
}

function Pill({ kind, children }) {
  return <span className={`pill pill--${kind}`}>{children}</span>;
}

Object.assign(window, { Icon, DesasfLogo, Sidebar, CliSidebar, AppSidebar, Topbar, Pill, navigate, openModal, logout, exportCSV, solicitudTitulo, solicitudSubtitulo, fmtNum, fmtMoney });
