// Sidebar, Topbar, Command palette, Notifications, generic UI bits

const ROLE_SHORT = {
  socio_admin: 'Sócio Admin', socio: 'Sócio', advogado: 'Advogado(a)', paralegal: 'Paralegal', cliente_externo: 'Cliente',
};

const Sidebar = ({ view, onView, counts, user, open, onClose }) => {
  const nav = [
    // Dashboard antigo saiu da sidebar — Meu Painel é a tela principal
    // (o view 'dash' segue acessível em /dashboard e pelo ⌘K durante a validação)
    { key: 'painel', icon: 'home', label: 'Meu Painel' },
    { key: 'tasks', icon: 'kanban', label: 'Tarefas', count: counts.tasks },
    { key: 'clients', icon: 'users', label: 'Clientes', count: counts.clients },
    { key: 'cases', icon: 'briefcase', label: 'Casos', count: counts.cases },
    { key: 'andamentos', icon: 'bell', label: 'Andamentos', count: counts.andamentos },
    { key: 'processos', icon: 'search', label: 'Consulta processual' },
    { key: 'calendar', icon: 'calendar', label: 'Calendário' },
    { key: 'reports', icon: 'fileText', label: 'Relatórios' },
    { key: 'publicacoes', icon: 'fileText', label: 'Publicações DJen' },
  ];
  const tools = [
    { key: 'propostas', icon: 'fileText', label: 'Propostas' },
    { key: 'contratos-revisao', icon: 'fileText', label: 'Revisão de Contratos' },
    { key: 'contratos-honorarios', icon: 'fileText', label: 'Contratos de Honorários' },
    { key: 'documentos', icon: 'fileText', label: 'Elaboração de documentos' },
    { key: 'assinaturas', icon: 'pen', label: 'Assinatura Eletrônica' },
    { key: 'library', icon: 'sparkles', label: 'Biblioteca IA' },
    { key: 'pdf-studio', icon: 'fileText', label: 'PDF Studio' },
    { key: 'upload', icon: 'upload', label: 'Upload inteligente' },
    { key: 'ai', icon: 'sparkles', label: 'Assistente IA' },
  ];
  const showFinanceiro = user?.can_financeiro !== false;
  const initials = user?.initials || user?.name?.split(' ').map(w => w[0]).join('').slice(0, 2).toUpperCase() || '?';
  const color = user?.color || 'var(--octale-navy)';
  const orgName = user?.organization?.name || 'Minha organização';
  const orgLogo = user?.organization?.logo_url;

  const navigate = (key) => { onView(key); onClose?.(); };

  return (
    <>
      {/* Overlay para fechar o drawer no mobile */}
      {open && (
        <div
          onClick={onClose}
          style={{
            position: 'fixed', inset: 0,
            background: 'rgba(26,10,46,.5)',
            zIndex: 299,
            animation: 'fade 180ms',
          }}
        />
      )}
      <aside className={`sb${open ? ' open' : ''}`}>
        <div className="sb-brand">
          {orgLogo ? (
            <img src={orgLogo} alt={orgName} style={{ maxHeight: 36, maxWidth: '100%', objectFit: 'contain' }} />
          ) : (
            <svg viewBox="0 0 520 120" width="130" height="30" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ display: 'block' }}>
              <g stroke="#8A9A5B" strokeWidth="4" strokeLinecap="round">
                <path d="M60 50 Q60 33 71 34" />
                <path d="M60 50 Q60 33 71 34" transform="rotate(45 60 60)" />
                <path d="M60 50 Q60 33 71 34" transform="rotate(90 60 60)" />
                <path d="M60 50 Q60 33 71 34" transform="rotate(135 60 60)" />
                <path d="M60 50 Q60 33 71 34" transform="rotate(180 60 60)" />
                <path d="M60 50 Q60 33 71 34" transform="rotate(225 60 60)" />
                <path d="M60 50 Q60 33 71 34" transform="rotate(270 60 60)" />
                <path d="M60 50 Q60 33 71 34" transform="rotate(315 60 60)" />
              </g>
              <circle cx="60" cy="60" r="6.9" fill="#8A9A5B" />
              <text x="136" y="72" fontFamily="DM Sans, Helvetica, sans-serif" fontSize="60" fontWeight="500" letterSpacing="-2.7" fill="#FFFFFF">octale</text>
              <text x="137" y="100" fontFamily="DM Mono, monospace" fontSize="18" letterSpacing="5" fill="#8A9A5B">legal</text>
            </svg>
          )}
        </div>
        <div className="sb-nav">
          <div className="sb-section">Trabalho</div>
          {nav.map(n => (
            <div key={n.key} className={`sb-item ${view === n.key ? 'active' : ''}`} onClick={() => navigate(n.key)}>
              <Icon name={n.icon} size={16} className="ic" />
              <span>{n.label}</span>
              {n.count != null && <span className="count">{n.count}</span>}
            </div>
          ))}
          <div className="sb-section">Ferramentas</div>
          {tools.map(n => (
            <div key={n.key} className={`sb-item ${view === n.key ? 'active' : ''}`} onClick={() => navigate(n.key)}>
              <Icon name={n.icon} size={16} className="ic" />
              <span>{n.label}</span>
              {n.count != null && n.count > 0 && <span className="count">{n.count}</span>}
            </div>
          ))}
          <div className="sb-section">Escritório</div>
          <div className={`sb-item ${view === 'team' ? 'active' : ''}`} onClick={() => navigate('team')}>
            <Icon name="building" size={16} className="ic" />
            <span>{orgName}</span>
          </div>
          {showFinanceiro && (
            <div className={`sb-item ${view === 'financeiro' ? 'active' : ''}`} onClick={() => navigate('financeiro')}>
              <Icon name="trendingUp" size={16} className="ic" />
              <span>Financeiro</span>
            </div>
          )}
          {(user?.org_role === 'owner' || user?.org_role === 'admin') && (
            <div className={`sb-item ${view === 'gestor-dash' ? 'active' : ''}`} onClick={() => navigate('gestor-dash')}>
              <Icon name="trendingUp" size={16} className="ic" />
              <span>Dashboard Gestor</span>
            </div>
          )}
          {(user?.org_role === 'owner' || user?.org_role === 'admin') && (
            <div className={`sb-item ${view === 'credits' ? 'active' : ''}`} onClick={() => navigate('credits')}>
              <Icon name="creditCard" size={16} className="ic" />
              <span>Créditos</span>
            </div>
          )}
          {(user?.org_role === 'owner' || user?.org_role === 'admin') && (
            <div className={`sb-item ${view === 'org-admin' ? 'active' : ''}`} onClick={() => navigate('org-admin')}>
              <Icon name="settings" size={16} className="ic" />
              <span>Organização</span>
            </div>
          )}
        </div>
        <div className="sb-foot">
          <div className="av" style={{ background: color, flexShrink: 0 }}>{initials}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="name" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{user?.name || 'Usuário'}</div>
            <div className="role">{ROLE_SHORT[user?.role] || user?.role || ''}</div>
          </div>
          <button
            onClick={() => window.OctaleApi.auth.logout()}
            title="Sair"
            style={{
              flexShrink: 0,
              width: 30, height: 30,
              borderRadius: 7,
              border: 'none',
              background: 'transparent',
              cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: 'rgba(255,255,255,.4)',
              transition: 'background .15s, color .15s',
            }}
            onMouseEnter={e => { e.currentTarget.style.background = 'rgba(255,255,255,.08)'; e.currentTarget.style.color = 'rgba(255,255,255,.85)'; }}
            onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'rgba(255,255,255,.4)'; }}
          >
            <Icon name="logOut" size={15} />
          </button>
        </div>
      </aside>
    </>
  );
};

const crumbFor = (view) => {
  const m = {
    dash: ['Visão geral', 'Dashboard executivo'],
    painel: ['Visão geral', 'Meu Painel'],
    tasks: ['Tarefas', 'Kanban operacional'],
    propostas: ['Propostas', 'Pipeline comercial'],
    library: ['Biblioteca', 'Skills · Prompts · Scripts'],
    clients: ['CRM', 'Clientes ativos'],
    cases: ['Casos', 'Gestão de casos'],
    calendar: ['Agenda', 'Calendário'],
    reports: ['Relatórios', 'Novo relatório'],
    publicacoes: ['Publicações DJen', 'Comunica API PJe/CNJ'],
    team: ['Escritório', 'Equipe'],
    'org-admin':   ['Escritório', 'Organização'],
    'gestor-dash': ['Escritório', 'Dashboard Gestor'],
    credits: ['Créditos', 'Saldo · Franquia · Consumo'],
    ai: ['Assistente IA', 'Assistente'],
    financeiro: ['Financeiro', 'Receitas · Despesas · Consolidação'],
  };
  return m[view] || ['Plataforma', ''];
};

const Topbar = ({ view, onOpenCmd, onOpenUpload, onOpenNotif, notifOpen, notifCount, onMenuOpen }) => {
  const [a, b] = crumbFor(view);
  return (
    <header className="tb">
      {/* Hamburger — visível apenas no mobile via CSS */}
      <button className="tb-ic-btn tb-hamburger" onClick={onMenuOpen} title="Menu">
        <Icon name="menu" size={20} />
      </button>

      <div className="tb-crumb">
        <span>{a}</span>
        <Icon name="chevronRight" size={12} />
        <b>{b}</b>
      </div>
      <button className="tb-search" onClick={onOpenCmd}>
        <Icon name="search" size={14} />
        <span>Buscar clientes, casos, documentos…</span>
        <kbd>⌘K</kbd>
      </button>
      <div className="tb-actions">
        <button className="tb-ic-btn" onClick={onOpenUpload} title="Upload inteligente">
          <Icon name="upload" size={17} />
        </button>
        <button className="tb-ic-btn" onClick={onOpenNotif} title="Notificações">
          <Icon name="bell" size={17} />
          {notifCount > 0 && <span className="dot" />}
        </button>
        <button className="tb-ic-btn" title="Configurações">
          <Icon name="settings" size={17} />
        </button>
      </div>
    </header>
  );
};

// ============ Notifications popover (dados reais) ============
const notifRelTime = (ts) => {
  const diff = Date.now() - new Date(ts).getTime();
  const min = Math.floor(diff / 60000);
  if (min < 1) return 'agora';
  if (min < 60) return `${min} min`;
  const h = Math.floor(min / 60);
  if (h < 24) return `${h} h`;
  const d = Math.floor(h / 24);
  return d === 1 ? 'ontem' : `${d} dias`;
};

// Texto por tipo — payload gravado pelo backend (notificationService)
const notifText = (n) => {
  const p = n.payload || {};
  const actor = n.actor?.name || 'Alguém';
  const cols = {
    novo: 'Novo', analise: 'Em análise', cliente: 'Aguardando cliente',
    redacao: 'Em redação', revisao: 'Em revisão', externos: 'Aguardando externos', concluido: 'Concluído',
  };
  switch (n.type) {
    case 'tarefa_atribuida':
      return <><b>{actor}</b> atribuiu a tarefa <b>{p.task_title || '—'}</b> a você</>;
    case 'tarefa_revisor':
      return <><b>{actor}</b> definiu você como revisor de <b>{p.task_title || '—'}</b></>;
    case 'subtarefa_atribuida':
      return <><b>{actor}</b> atribuiu a subtarefa <b>{p.task_title || '—'}</b>{p.parent_title ? <> (em <b>{p.parent_title}</b>)</> : null} a você</>;
    case 'tarefa_movida':
      return <><b>{actor}</b> moveu <b>{p.task_title || '—'}</b> de {cols[p.de] || p.de || '—'} para <b>{cols[p.para] || p.para || '—'}</b></>;
    case 'proposta_aceita':
      return <>🎉 Proposta <b>{p.proposal_number || ''}</b> aceita{p.client_name ? <> por <b>{p.client_name}</b></> : null}</>;
    case 'artigo_pendente':
      return <>Novo artigo <b>{p.artigo_titulo || '—'}</b>{p.area ? <> ({p.area})</> : null} aguardando sua aprovação</>;
    case 'artigo_erro_publicacao':
      return <>⚠ Falha ao publicar o artigo <b>{p.artigo_titulo || '—'}</b> no site</>;
    default:
      return <>{n.type}</>;
  }
};

// View de destino ao clicar na notificação
const notifTarget = (n) => {
  if (n.type === 'proposta_aceita') return 'propostas';
  if (n.type === 'artigo_pendente' || n.type === 'artigo_erro_publicacao') return 'artigos';
  return 'tasks';
};

const NotifPop = ({ onClose, onJump, onRead }) => {
  const [items, setItems] = React.useState(null); // null = carregando

  const load = () => {
    window.OctaleApi.notifications.list()
      .then(({ notifications }) => setItems(notifications || []))
      .catch(() => setItems([]));
  };
  React.useEffect(load, []);

  const markAll = async () => {
    try {
      await window.OctaleApi.notifications.markAllRead();
      setItems(prev => (prev || []).map(n => ({ ...n, read_at: n.read_at || new Date().toISOString() })));
      onRead?.();
    } catch {}
  };

  const open = async (n) => {
    if (!n.read_at) {
      window.OctaleApi.notifications.markRead(n.id).catch(() => {});
      onRead?.();
    }
    onClose();
    onJump?.(notifTarget(n));
  };

  const unreadCount = (items || []).filter(n => !n.read_at).length;

  return (
    <div className="notif-pop" onClick={(e) => e.stopPropagation()}>
      <div className="head">
        <h4>Notificações</h4>
        {unreadCount > 0 && (
          <button className="btn ghost sm" style={{ height: 24, padding: '0 8px', fontSize: 11 }} onClick={markAll}>
            Marcar como lidas
          </button>
        )}
      </div>
      {items === null ? (
        <div style={{ padding: '20px 16px', fontSize: 12, color: 'var(--fg-muted)', display: 'flex', alignItems: 'center', gap: 8 }}>
          <span className="spinner" style={{ width: 12, height: 12 }} /> Carregando…
        </div>
      ) : items.length === 0 ? (
        <div style={{ padding: '24px 16px', fontSize: 12.5, color: 'var(--fg-muted)', textAlign: 'center' }}>
          Nenhuma notificação ainda.<br />
          <span style={{ fontSize: 11.5 }}>Você será avisado sobre tarefas atribuídas a você, mudanças de coluna e propostas aceitas.</span>
        </div>
      ) : items.map((n) => (
        <div key={n.id} className={`notif-item ${!n.read_at ? 'unread' : ''}`} onClick={() => open(n)} style={{ cursor: 'pointer' }}>
          <div className="av sm" style={{ background: n.actor?.color || 'var(--octale-dark-purple)' }}>
            {n.actor?.initials || (n.type === 'proposta_aceita' ? '🎉' : 'PAC')}
          </div>
          <div style={{ flex: 1 }}>
            <div className="ttl">{notifText(n)}</div>
            <div className="ts">{notifRelTime(n.created_at)}</div>
          </div>
        </div>
      ))}
    </div>
  );
};

// ============ Command palette (⌘K) ============
const CommandPalette = ({ open, onClose, onJump, user }) => {
  const [q, setQ] = React.useState('');
  const [sel, setSel] = React.useState(0);
  const [dbData, setDbData] = React.useState({ clients: [], cases: [], tasks: [] });
  const [dbLoading, setDbLoading] = React.useState(false);
  const inputRef = React.useRef(null);

  // Carrega dados reais da plataforma ao abrir
  React.useEffect(() => {
    if (!open) return;
    setQ(''); setSel(0);
    setTimeout(() => inputRef.current?.focus(), 30);
    setDbLoading(true);
    Promise.all([
      window.OctaleApi.clients.list().catch(() => []),
      window.OctaleApi.cases.list().catch(() => []),
      window.OctaleApi.tasks.list().catch(() => []),
    ]).then(([clients, cases, tasks]) => {
      setDbData({ clients, cases, tasks });
    }).finally(() => setDbLoading(false));
  }, [open]);

  const groups = React.useMemo(() => {
    const ql = q.toLowerCase().trim();
    const match = (it) => !ql || (it.label + ' ' + (it.hint || '')).toLowerCase().includes(ql);

    const actions = [
      { kind: 'action', label: 'Nova tarefa', icon: 'plus', view: 'tasks' },
      { kind: 'action', label: 'Novo caso', icon: 'briefcase', view: 'cases' },
      { kind: 'action', label: 'Novo cliente', icon: 'users', view: 'clients' },
      { kind: 'action', label: 'Upload de documentos', icon: 'upload', view: '__upload' },
      { kind: 'action', label: 'Gerar relatório', icon: 'fileText', view: 'reports' },
    ];
    const navigate = [
      { kind: 'nav', label: 'Meu Painel', icon: 'home', view: 'painel' },
      { kind: 'nav', label: 'Dashboard (antigo)', icon: 'home', view: 'dash' },
      { kind: 'nav', label: 'Tarefas (Kanban)', icon: 'kanban', view: 'tasks' },
      { kind: 'nav', label: 'Clientes', icon: 'users', view: 'clients' },
      { kind: 'nav', label: 'Casos', icon: 'briefcase', view: 'cases' },
      { kind: 'nav', label: 'Calendário', icon: 'calendar', view: 'calendar' },
      // Artigos é módulo por organização (enabled_modules.artigos). Fica oculto na
      // versão padrão do Octale Legal — recurso específico de quem publica em site próprio.
      ...(user?.organization?.enabled_modules?.artigos ? [{ kind: 'nav', label: 'Artigos', icon: 'fileText', view: 'artigos' }] : []),
      { kind: 'nav', label: 'Publicações Astrea', icon: 'bell', view: 'publicacoes-astrea' },
      { kind: 'nav', label: 'Publicações DJen', icon: 'bell', view: 'publicacoes' },
      { kind: 'nav', label: 'Relatórios', icon: 'fileText', view: 'reports' },
      { kind: 'nav', label: 'Equipe', icon: 'users', view: 'team' },
    ];

    // Resultados reais do banco — só exibe quando há query
    const clients = dbData.clients.map(c => ({
      kind: 'client', id: c.id, view: 'clients',
      label: c.name,
      hint: [c.short_name, c.sector, c.city].filter(Boolean).join(' · '),
      icon: 'users',
      badge: c.tier,
    }));
    const cases = dbData.cases.map(c => ({
      kind: 'case', id: c.id, view: 'cases',
      label: c.title,
      hint: [c.number, c.area, c.clients?.name].filter(Boolean).join(' · '),
      icon: 'briefcase',
      badge: c.status,
    }));
    const tasks = dbData.tasks
      .filter(t => t.kanban_column !== 'concluido')
      .map(t => ({
        kind: 'task', id: t.id, view: 'tasks',
        label: t.title,
        hint: [t.cases?.title || t.cases?.number, t.priority].filter(Boolean).join(' · '),
        icon: 'checkSquare',
      }));

    if (ql) {
      // Com query: mostra resultados filtrados + IA
      return [
        { lbl: 'Clientes', items: clients.filter(match).slice(0, 5) },
        { lbl: 'Casos', items: cases.filter(match).slice(0, 5) },
        { lbl: 'Tarefas', items: tasks.filter(match).slice(0, 3) },
        { lbl: 'Navegação', items: navigate.filter(match) },
        { lbl: 'Ações', items: actions.filter(match) },
        { lbl: 'IA', items: [{ kind: 'ai', label: `Perguntar à Octale.AI`, icon: 'sparkles' }] },
      ].filter(g => g.items.length > 0);
    }
    // Sem query: atalhos e navegação
    return [
      { lbl: 'Ações rápidas', items: actions },
      { lbl: 'Ir para', items: navigate },
    ];
  }, [q, dbData]);

  const flat = groups.flatMap(g => g.items);

  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowDown') { e.preventDefault(); setSel(s => Math.min(s + 1, flat.length - 1)); }
      if (e.key === 'ArrowUp')   { e.preventDefault(); setSel(s => Math.max(s - 1, 0)); }
      if (e.key === 'Enter') {
        const it = flat[sel];
        if (it) { handleSelect(it); }
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, sel, flat]);

  const handleSelect = (it) => {
    if (it.kind === 'ai') { onJump('__ai', { query: q }); onClose(); return; }
    onJump(it.view, it);
    onClose();
  };

  if (!open) return null;
  let idx = -1;
  return (
    <div className="scrim" onClick={onClose}>
      <div className="cmdk" onClick={(e) => e.stopPropagation()}>
        <div className="cmdk-input">
          <Icon name="search" size={18} style={{ color: 'var(--fg-muted)' }} />
          <input
            ref={inputRef}
            value={q}
            onChange={(e) => { setQ(e.target.value); setSel(0); }}
            placeholder="Buscar cliente, caso, tarefa ou executar ação…"
          />
          {dbLoading
            ? <span className="spinner" style={{ width: 12, height: 12, borderColor: 'rgba(23,23,15,.15)', borderTopColor: 'var(--octale-navy)', flexShrink: 0 }} />
            : <kbd style={{ fontSize: 10, color: 'var(--fg-muted)', border: '1px solid var(--border)', padding: '1px 6px', borderRadius: 3, flexShrink: 0 }}>ESC</kbd>
          }
        </div>
        <div className="cmdk-list">
          {groups.map(g => (
            <React.Fragment key={g.lbl}>
              <div className="cmdk-group-lbl">{g.lbl}</div>
              {g.items.map((it, i) => {
                idx++;
                const isSel = idx === sel;
                if (it.kind === 'ai') {
                  return (
                    <div key={i} className={`cmdk-ai ${isSel ? 'sel' : ''}`} onClick={() => handleSelect(it)}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--octale-navy)', fontWeight: 600, marginBottom: 4 }}>
                        <Icon name="sparkles" size={14} /> Perguntar à Octale.AI
                      </div>
                      <div style={{ color: 'var(--octale-black)' }}>"{q}"</div>
                      <div style={{ fontSize: 11, color: 'var(--fg-muted)', marginTop: 4 }}>
                        Busca e analisa dados internos do escritório.
                      </div>
                    </div>
                  );
                }
                // Badge de status/tier
                const badge = it.badge ? (
                  <span style={{
                    fontSize: 9, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.05em',
                    padding: '2px 6px', borderRadius: 4,
                    background: 'var(--octale-neon)', color: 'var(--octale-navy)',
                    opacity: .8, flexShrink: 0,
                  }}>{it.badge}</span>
                ) : null;
                return (
                  <div key={i} className={`cmdk-item ${isSel ? 'sel' : ''}`} onClick={() => handleSelect(it)}>
                    <Icon name={it.icon} size={16} className="ic" />
                    <div className="grow" style={{ minWidth: 0 }}>
                      <div style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{it.label}</div>
                      {it.hint && <div style={{ fontSize: 11, color: 'var(--fg-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{it.hint}</div>}
                    </div>
                    {badge}
                    {isSel && <span className="kbd">↵</span>}
                  </div>
                );
              })}
            </React.Fragment>
          ))}
          {flat.length === 0 && q && (
            <div style={{ padding: '24px', textAlign: 'center', color: 'var(--fg-muted)', fontSize: 12 }}>
              Nenhum resultado para "{q}".
            </div>
          )}
        </div>
        <div className="cmdk-foot">
          <span><kbd>↑</kbd> <kbd>↓</kbd> navegar</span>
          <span><kbd>↵</kbd> selecionar</span>
          <span><kbd>esc</kbd> fechar</span>
          <span style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 6 }}>
            <Icon name="sparkles" size={11} /> Octale.AI
          </span>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { Sidebar, Topbar, NotifPop, CommandPalette, crumbFor });
