/* SISTEMA · Organograma — Diretório + Árvore visual + Editor DnD */

// ── Utilitários partilhados ────────────────────────────────────────────────

const _OrgAvatar = ({ nome, email, size = 36 }) => {
  const [imgOk, setImgOk] = React.useState(!!email);
  const initials = (nome || '?').split(' ').filter(Boolean).slice(0, 2).map(w => w[0].toUpperCase()).join('');
  const colors   = ['#3b82f6','#8b5cf6','#10b981','#f59e0b','#ef4444','#06b6d4','#ec4899'];
  const color    = colors[(nome || '').charCodeAt(0) % colors.length];
  if (email && imgOk) {
    return (
      <img
        src={`/photos/${encodeURIComponent(email)}.jpg`}
        onError={() => setImgOk(false)}
        alt={nome || email}
        style={{ width: size, height: size, borderRadius: '50%', objectFit: 'cover', flexShrink: 0, display: 'block' }}
      />
    );
  }
  return (
    <div style={{
      width: size, height: size, borderRadius: '50%', background: color,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontSize: size * 0.38, fontWeight: 700, color: '#fff', flexShrink: 0,
      fontFamily: 'var(--font-mono)',
    }}>{initials}</div>
  );
};

const _orgCard = { background: 'var(--bg-card)', border: '1px solid var(--border)', borderRadius: 8, overflow: 'hidden' };
const _orgHdr  = { padding: '10px 14px', background: 'var(--bg-sunken)', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' };
const _orgLbl  = { fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--text-dim)' };


// ── Painel lateral de detalhe ──────────────────────────────────────────────

const _OrgDetailPanel = ({ email, byEmail, onClose, isHidden, onToggleHide, isAdmin, load, pessoas }) => {
  if (!email) return null;
  const p = byEmail[email];
  if (!p) return null;

  const [editMode, setEditMode] = React.useState(false);
  const [form,     setForm]     = React.useState({});
  const [saving,   setSaving]   = React.useState(false);
  const [saveErr,  setSaveErr]  = React.useState(null);

  const startEdit = () => {
    setForm({
      nome_apresentar:     p.nome_apresentar     || '',
      nome_completo:       p.nome_completo       || '',
      empresa:             p.empresa             || '',
      departamento:        p.departamento        || '',
      perfil_cargo:        p.perfil_cargo        || '',
      telemovel:           p.telemovel           || '',
      telefone_escritorio: p.telefone_escritorio || '',
      office:              p.office              || '',
      manager_email:       p.manager_email       || '',
    });
    setSaveErr(null);
    setEditMode(true);
  };

  const save = async () => {
    setSaving(true); setSaveErr(null);
    try {
      const r = await fetch('/api/organograma/colaborador', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: p.email_profissional, ...form }),
      });
      if (!r.ok) { const e = await r.json(); throw new Error(e.error || r.statusText); }
      setEditMode(false);
      load();
    } catch (e) { setSaveErr(e.message); }
    finally { setSaving(false); }
  };

  const inputStyle = {
    width: '100%', padding: '6px 8px', fontSize: 13, borderRadius: 5,
    border: '1px solid var(--border)', background: 'var(--bg-sunken)',
    color: 'var(--text)', fontFamily: 'var(--font-body)', boxSizing: 'border-box',
    outline: 'none',
  };
  const lbl = (t) => (
    <div style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 3 }}>{t}</div>
  );

  const viewFields = [
    ['Email',      p.email_profissional],
    ['Empresa',    p.empresa],
    ['Dept.',      p.departamento],
    ['Cargo',      p.perfil_cargo],
    ['Telemovel',  p.telemovel],
    ['Telefone',   p.telefone_escritorio],
    ['Office',     p.office],
  ].filter(([, v]) => v);

  const outrasOptions = (pessoas || [])
    .filter(x => x.email_profissional !== p.email_profissional)
    .sort((a, b) => (a.nome_apresentar || a.nome_completo || '').localeCompare(b.nome_apresentar || b.nome_completo || ''));

  return (
    <>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(17,41,84,0.18)', zIndex: 200 }} />
      <div style={{
        position: 'fixed', top: 0, right: 0, bottom: 0, width: 300,
        background: 'var(--bg-elev, #fff)', borderLeft: '1px solid var(--border)',
        zIndex: 201, display: 'flex', flexDirection: 'column',
        boxShadow: '-6px 0 32px rgba(17,41,84,0.18)',
        animation: 'slideInRight 0.18s ease',
      }}>
        {/* Header */}
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span style={_orgLbl}>{editMode ? 'Editar colaborador' : 'Colaborador'}</span>
          <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
            {isAdmin && !editMode && (
              <button onClick={startEdit} style={{ background: 'none', border: '1px solid var(--border)', borderRadius: 5, color: 'var(--text-dim)', cursor: 'pointer', fontSize: 12, padding: '2px 10px', fontFamily: 'var(--font-body)' }}>Editar</button>
            )}
            {editMode && (
              <button onClick={() => setEditMode(false)} style={{ background: 'none', border: 'none', color: 'var(--text-dim)', cursor: 'pointer', fontSize: 12, padding: '2px 6px', fontFamily: 'var(--font-body)' }}>Cancelar</button>
            )}
            <button onClick={onClose} style={{ background: 'none', border: 'none', color: 'var(--text-dim)', cursor: 'pointer', fontSize: 20, lineHeight: 1, padding: '0 2px' }}>×</button>
          </div>
        </div>

        {/* Body */}
        <div style={{ flex: 1, overflowY: 'auto', padding: '20px 18px', display: 'flex', flexDirection: 'column', gap: 14 }}>

          {!editMode ? (
            <>
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
                <_OrgAvatar nome={p.nome_completo || p.nome_apresentar} email={p.email_profissional} size={64} />
                <div style={{ textAlign: 'center' }}>
                  <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--text)', lineHeight: 1.3 }}>{p.nome_completo || p.nome_apresentar || email}</div>
                  {p.perfil_cargo && <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 3 }}>{p.perfil_cargo}</div>}
                  {p.empresa && (
                    <div style={{ marginTop: 6, fontSize: 9, color: 'rgba(255,255,255,0.88)', background: '#1e3a5f', borderRadius: 3, padding: '2px 8px', display: 'inline-block', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>
                      {p.empresa}
                    </div>
                  )}
                </div>
              </div>
              {viewFields.length > 0 && (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                  {viewFields.map(([label, value]) => (
                    <div key={label}>
                      <div style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 3 }}>{label}</div>
                      <div style={{ fontSize: 13, color: 'var(--text)', wordBreak: 'break-all' }}>{value}</div>
                    </div>
                  ))}
                </div>
              )}
            </>
          ) : (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              <div>{lbl('Nome apresentar')}<input style={inputStyle} value={form.nome_apresentar} onChange={e => setForm(f => ({ ...f, nome_apresentar: e.target.value }))} /></div>
              <div>{lbl('Nome completo')}<input style={inputStyle} value={form.nome_completo} onChange={e => setForm(f => ({ ...f, nome_completo: e.target.value }))} /></div>
              <div>{lbl('Empresa')}<input style={inputStyle} value={form.empresa} onChange={e => setForm(f => ({ ...f, empresa: e.target.value }))} /></div>
              <div>{lbl('Departamento')}<input style={inputStyle} value={form.departamento} onChange={e => setForm(f => ({ ...f, departamento: e.target.value }))} /></div>
              <div>{lbl('Cargo')}<input style={inputStyle} value={form.perfil_cargo} onChange={e => setForm(f => ({ ...f, perfil_cargo: e.target.value }))} /></div>
              <div>{lbl('Telemovel')}<input style={inputStyle} value={form.telemovel} onChange={e => setForm(f => ({ ...f, telemovel: e.target.value }))} /></div>
              <div>{lbl('Telefone')}<input style={inputStyle} value={form.telefone_escritorio} onChange={e => setForm(f => ({ ...f, telefone_escritorio: e.target.value }))} /></div>
              <div>{lbl('Office')}<input style={inputStyle} value={form.office} onChange={e => setForm(f => ({ ...f, office: e.target.value }))} /></div>
              <div>
                {lbl('Superior hierárquico')}
                <select style={inputStyle} value={form.manager_email} onChange={e => setForm(f => ({ ...f, manager_email: e.target.value }))}>
                  <option value="">— Sem superior —</option>
                  {outrasOptions.map(x => (
                    <option key={x.email_profissional} value={x.email_profissional}>
                      {x.nome_apresentar || x.nome_completo} ({x.perfil_cargo || x.empresa || x.email_profissional})
                    </option>
                  ))}
                </select>
              </div>
              {saveErr && <div style={{ fontSize: 12, color: '#ef4444', padding: '6px 10px', background: 'rgba(239,68,68,0.08)', borderRadius: 5 }}>{saveErr}</div>}
            </div>
          )}
        </div>

        {/* Footer */}
        <div style={{ padding: '14px 18px', borderTop: '1px solid var(--border)', flexShrink: 0 }}>
          {editMode ? (
            <button
              onClick={save} disabled={saving}
              style={{ width: '100%', padding: '9px 16px', fontSize: 13, borderRadius: 6, border: 'none', background: saving ? '#94a3b8' : '#1e3a5f', color: '#fff', cursor: saving ? 'default' : 'pointer', fontFamily: 'var(--font-body)', fontWeight: 600 }}
            >
              {saving ? 'A guardar…' : 'Guardar alterações'}
            </button>
          ) : (
            <button
              onClick={onToggleHide}
              style={{ width: '100%', padding: '9px 16px', fontSize: 13, borderRadius: 6, border: `1px solid ${isHidden ? '#22c55e' : '#f59e0b'}`, background: isHidden ? 'rgba(34,197,94,0.08)' : 'rgba(245,158,11,0.08)', color: isHidden ? '#22c55e' : '#f59e0b', cursor: 'pointer', fontFamily: 'var(--font-body)', fontWeight: 600 }}
            >
              {isHidden ? '👁  Mostrar na árvore' : '🙈  Ocultar desta árvore'}
            </button>
          )}
        </div>
      </div>
    </>
  );
};

// ── Nó visual da árvore ────────────────────────────────────────────────────

const _OrgVisualNode = ({
  email, depth, byEmail, childrenMap,
  expanded, toggleExpand,
  editable,
  dragEmail, dropTarget,
  onDragStart, onDragOver, onDrop, hasCycle,
  edits, origMgr, q,
  onSelect, hiddenEmails,
}) => {
  const p = byEmail[email];
  if (!p) return null;
  if (hiddenEmails && hiddenEmails.has(email)) return null;

  const kids = (childrenMap[email] || [])
    .filter(c => !hiddenEmails || !hiddenEmails.has(c))
    .sort((a, b) => (byEmail[a]?.nome_completo || '').localeCompare(byEmail[b]?.nome_completo || ''));

  const defaultExp = depth < 2;
  const isExpanded  = expanded[email] !== undefined ? expanded[email] !== false : defaultExp;
  const isDragging  = editable && dragEmail === email;
  const isTarget    = editable && dropTarget === email && dragEmail && dragEmail !== email;
  const isBadTarget = isTarget && hasCycle && hasCycle(dragEmail, email);
  const hasChanged  = editable && edits && origMgr && (edits[email] || '') !== origMgr(email);
  const isMatch     = q && ((p.nome_completo || '').toLowerCase().includes(q) || (p.perfil_cargo || '').toLowerCase().includes(q));

  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>

      {/* Cartão */}
      <div
        draggable={editable || undefined}
        onDragStart={editable ? (e) => {
          e.stopPropagation();
          const ghost = document.createElement('div');
          ghost.style.cssText = 'position:fixed;top:-9999px;padding:6px 12px;background:#1e40af;color:#fff;border-radius:6px;font-size:12px;font-weight:600;white-space:nowrap;';
          ghost.textContent = p.nome_completo || p.nome_apresentar || email;
          document.body.appendChild(ghost);
          e.dataTransfer.setDragImage(ghost, 60, 12);
          requestAnimationFrame(() => document.body.removeChild(ghost));
          e.dataTransfer.effectAllowed = 'move';
          onDragStart(email);
        } : undefined}
        onDragOver={editable ? (e) => { e.preventDefault(); e.stopPropagation(); onDragOver(email); } : undefined}
        onDrop={editable ? (e) => { e.preventDefault(); e.stopPropagation(); onDrop(email); } : undefined}
        onClick={onSelect ? (e) => { e.stopPropagation(); onSelect(email); } : undefined}
        style={{
          background: 'var(--bg-elev, #fff)',
          border: isBadTarget  ? '2px solid #ef4444'
                : isTarget     ? '2px solid #3b82f6'
                : hasChanged   ? '1px solid #f59e0b'
                : isMatch      ? '1px solid rgba(59,130,246,0.55)'
                : '1px solid var(--border)',
          borderRadius: 8,
          padding: '10px 10px 8px',
          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6,
          width: 144,
          opacity: isDragging ? 0.25 : 1,
          cursor: editable ? 'grab' : (onSelect ? 'pointer' : 'default'),
          boxShadow: isTarget && !isBadTarget ? '0 0 0 4px rgba(59,130,246,0.15)' : 'none',
          transition: 'border-color 0.07s, box-shadow 0.07s, opacity 0.1s',
          userSelect: 'none',
          position: 'relative',
        }}
      >
        {hasChanged && (
          <div style={{ position: 'absolute', top: -7, right: -4, background: '#f59e0b', color: '#000', fontSize: 8, fontWeight: 700, borderRadius: 3, padding: '1px 4px', fontFamily: 'var(--font-mono)' }}>editado</div>
        )}

        <_OrgAvatar nome={p.nome_completo || p.nome_apresentar} email={p.email_profissional} size={40} />

        <div style={{ textAlign: 'center', width: '100%', overflow: 'hidden' }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', lineHeight: 1.3 }}>
            {(p.nome_completo || p.nome_apresentar || email).split(' ').slice(0, 3).join(' ')}
          </div>
          {p.perfil_cargo && (
            <div style={{ fontSize: 10, color: 'var(--text-dim)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', marginTop: 2 }}>{p.perfil_cargo}</div>
          )}
          {p.empresa && (
            <div style={{ marginTop: 5, fontSize: 8, color: 'rgba(255,255,255,0.88)', background: '#1e3a5f', borderRadius: 3, padding: '2px 6px', display: 'inline-block', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.05em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%' }}>
              {p.empresa}
            </div>
          )}
          {kids.length > 0 && (
            <div
              onClick={(e) => { e.stopPropagation(); toggleExpand(email, defaultExp); }}
              style={{ marginTop: 6, fontSize: 9, color: 'var(--text-dim)', cursor: 'pointer', fontFamily: 'var(--font-mono)' }}
            >
              {isExpanded ? '▲ recolher' : `▼ ${kids.length} directo${kids.length !== 1 ? 's' : ''}`}
            </div>
          )}
        </div>
      </div>

      {/* Filhos — agrupados por departamento */}
      {kids.length > 0 && isExpanded && (() => {
        // Agrupar filhos por departamento
        const deptMap = {};
        for (const c of kids) {
          const d = byEmail[c]?.departamento || '';
          if (!deptMap[d]) deptMap[d] = [];
          deptMap[d].push(c);
        }
        const deptGroups = Object.entries(deptMap).sort(([a], [b]) => (a || 'zzz').localeCompare(b || 'zzz'));
        const showDeptLabels = deptGroups.some(([d]) => d !== '');

        return (
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
            <div style={{ width: 1, height: 24, background: 'var(--border)' }} />
            <div style={{ display: 'flex', alignItems: 'flex-start' }}>
              {deptGroups.map(([dept, deptKids], gi) => (
                <div key={dept || '__s__'} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '0 8px', position: 'relative' }}>
                  {/* Linha horizontal entre grupos de departamento */}
                  {deptGroups.length > 1 && (
                    <div style={{ position: 'absolute', top: 0, height: 1, left: gi === 0 ? '50%' : 0, right: gi === deptGroups.length - 1 ? '50%' : 0, background: 'var(--border)' }} />
                  )}
                  <div style={{ width: 1, height: 16, background: 'var(--border)' }} />
                  {/* Cabeçalho de departamento */}
                  {showDeptLabels && dept && (
                    <div style={{
                      alignSelf: 'stretch', textAlign: 'center',
                      background: '#1e3a5f', color: '#fff',
                      padding: '5px 14px', borderRadius: 4, marginBottom: 0,
                      fontSize: 9, fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase',
                      whiteSpace: 'nowrap',
                    }}>{dept}</div>
                  )}
                  {/* Filhos dentro deste departamento */}
                  <div style={{ display: 'flex', alignItems: 'flex-start' }}>
                    {deptKids.map((childEmail, i) => (
                      <div key={childEmail} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '0 8px', position: 'relative' }}>
                        {deptKids.length > 1 && (
                          <div style={{ position: 'absolute', top: 0, height: 1, left: i === 0 ? '50%' : 0, right: i === deptKids.length - 1 ? '50%' : 0, background: 'var(--border)' }} />
                        )}
                        <div style={{ width: 1, height: 20, background: 'var(--border)' }} />
                        <_OrgVisualNode
                          email={childEmail} depth={depth + 1}
                          byEmail={byEmail} childrenMap={childrenMap}
                          expanded={expanded} toggleExpand={toggleExpand}
                          editable={editable}
                          dragEmail={dragEmail} dropTarget={dropTarget}
                          onDragStart={onDragStart} onDragOver={onDragOver} onDrop={onDrop}
                          hasCycle={hasCycle} edits={edits} origMgr={origMgr} q={q}
                          onSelect={onSelect} hiddenEmails={hiddenEmails}
                        />
                      </div>
                    ))}
                  </div>
                </div>
              ))}
            </div>
          </div>
        );
      })()}
    </div>
  );
};

// ── Tab: Organograma visual (só leitura) ───────────────────────────────────

const _OrgOrganogramaTab = ({ pessoas, q, expanded, setExpanded, zoom, hiddenEmails }) => {
  const byEmail     = {};
  const childrenMap = {};

  for (const p of pessoas) {
    byEmail[p.email_profissional] = p;
    childrenMap[p.email_profissional] = [];
  }
  for (const p of pessoas) {
    const mgr = p.manager_email;
    if (mgr && byEmail[mgr]) childrenMap[mgr].push(p.email_profissional);
  }

  const toggleExpand = (email, defaultExp) =>
    setExpanded(v => {
      const cur = v[email] !== undefined ? v[email] !== false : defaultExp;
      return { ...v, [email]: !cur };
    });

  const roots = pessoas
    .filter(p => !hiddenEmails?.has(p.email_profissional))
    .filter(p => !p.manager_email || !byEmail[p.manager_email] || hiddenEmails?.has(p.manager_email))
    .map(p => p.email_profissional)
    .sort((a, b) => (byEmail[a]?.nome_completo || '').localeCompare(byEmail[b]?.nome_completo || ''));

  if (roots.length === 0) return (
    <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-dim)', fontSize: 13 }}>
      Sem dados. Define a hierarquia no separador «Editar hierarquia».
    </div>
  );

  return (
    <div style={{ overflowX: 'auto', paddingBottom: 24 }}>
      <div style={{ zoom, display: 'flex', gap: 40, padding: '24px 24px', minWidth: 'max-content', justifyContent: 'center' }}>
        {roots.map(email => (
          <_OrgVisualNode
            key={email} email={email} depth={0}
            byEmail={byEmail} childrenMap={childrenMap}
            expanded={expanded} toggleExpand={toggleExpand}
            editable={false} q={q} hiddenEmails={hiddenEmails}
          />
        ))}
      </div>
    </div>
  );
};

// ── Tab: Ocultos ───────────────────────────────────────────────────────────

const _OrgOcultosTab = ({ hiddenEmails, setHiddenEmails, byEmail }) => {
  if (hiddenEmails.size === 0) return (
    <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-dim)', fontSize: 13 }}>
      Nenhuma pessoa oculta. No separador «Editar hierarquia» clica num cartão para ocultar alguém.
    </div>
  );

  const show = (email) => {
    setHiddenEmails(prev => { const s = new Set(prev); s.delete(email); return s; });
    fetch('/api/organograma/oculto', {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, oculto: false }),
    }).catch(() => {});
  };

  const showAll = (emails) => {
    setHiddenEmails(new Set());
    Promise.all([...emails].map(email =>
      fetch('/api/organograma/oculto', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, oculto: false }),
      })
    )).catch(() => {});
  };

  return (
    <div style={_orgCard}>
      <div style={_orgHdr}>
        <span style={_orgLbl}>Ocultos da árvore ({hiddenEmails.size})</span>
        <button
          onClick={() => showAll(hiddenEmails)}
          style={{ fontSize: 11, color: 'var(--text-dim)', background: 'none', border: '1px solid var(--border)', borderRadius: 4, padding: '2px 8px', cursor: 'pointer' }}
        >
          Mostrar todos
        </button>
      </div>
      {[...hiddenEmails].map(email => {
        const p = byEmail[email];
        if (!p) return null;
        return (
          <div key={email} style={{ padding: '10px 16px', borderBottom: '1px solid var(--border)', display: 'flex', gap: 12, alignItems: 'center' }}>
            <_OrgAvatar nome={p.nome_completo || p.nome_apresentar} email={p.email_profissional} size={32} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                {p.nome_completo || p.nome_apresentar || email}
              </div>
              <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>
                {p.perfil_cargo || '—'}{p.empresa ? ` · ${p.empresa}` : ''}
              </div>
            </div>
            <button
              onClick={() => show(email)}
              style={{ fontSize: 12, padding: '5px 12px', borderRadius: 5, border: '1px solid #22c55e', background: 'rgba(34,197,94,0.08)', color: '#22c55e', cursor: 'pointer', flexShrink: 0 }}
            >
              👁 Mostrar
            </button>
          </div>
        );
      })}
    </div>
  );
};

// ── Tab: Editor drag-and-drop visual ──────────────────────────────────────

const _OrgEditorTab = ({ pessoas, load, q, hiddenEmails, setHiddenEmails, selectedEmail, setSelectedEmail, zoom, expanded, setExpanded }) => {
  const [edits,      setEdits]      = React.useState({});
  const [dragEmail,  setDragEmail]  = React.useState(null);
  const [dropTarget, setDropTarget] = React.useState(null);
  const [saving,     setSaving]     = React.useState(false);
  const [saveMsg,    setSaveMsg]    = React.useState(null);

  React.useEffect(() => {
    const init = {};
    for (const p of pessoas) init[p.email_profissional] = p.manager_email || '';
    setEdits(init);
  }, [pessoas.length]);

  const byEmail = {};
  for (const p of pessoas) byEmail[p.email_profissional] = p;

  const childrenMap = {};
  for (const p of pessoas) childrenMap[p.email_profissional] = [];
  for (const [email, mgr] of Object.entries(edits)) {
    if (mgr && childrenMap[mgr] && !hiddenEmails.has(email)) childrenMap[mgr].push(email);
  }

  const origMgr = (email) => byEmail[email]?.manager_email || '';

  const hasCycle = (dragged, target) => {
    if (!dragged || !target) return false;
    let cur = target; let d = 0;
    while (cur && d < 60) {
      if (cur === dragged) return true;
      cur = edits[cur] || ''; d++;
    }
    return false;
  };

  const toggleExpand = React.useCallback((email, defaultExp) => {
    setExpanded(v => {
      const cur = v[email] !== undefined ? v[email] !== false : defaultExp;
      return { ...v, [email]: !cur };
    });
  }, []);

  const onDragStart = React.useCallback(email => setDragEmail(email), []);
  const onDragOver  = React.useCallback(email => setDropTarget(email), []);

  const onDrop = (targetEmail) => {
    const dragged = dragEmail;
    setDragEmail(null); setDropTarget(null);
    if (!dragged || dragged === targetEmail) return;
    const newMgr = targetEmail === '__root__' ? '' : targetEmail;
    if (newMgr && hasCycle(dragged, newMgr)) return;
    setEdits(prev => ({ ...prev, [dragged]: newMgr }));
  };

  const onSelect = React.useCallback(email => setSelectedEmail(e => e === email ? null : email), []);

  const roots = Object.entries(edits)
    .filter(([email, mgr]) => !hiddenEmails.has(email) && (!mgr || hiddenEmails.has(mgr) || !byEmail[mgr]))
    .map(([email]) => email)
    .filter(email => byEmail[email])
    .sort((a, b) => (byEmail[a]?.nome_completo || '').localeCompare(byEmail[b]?.nome_completo || ''));

  const pendingChanges = Object.entries(edits)
    .filter(([email, mgr]) => (mgr || '') !== origMgr(email)).length;

  const saveHierarquia = async () => {
    setSaving(true); setSaveMsg(null);
    try {
      const payload = Object.entries(edits).map(([email, manager_email]) => ({
        email, manager_email: manager_email || null,
      }));
      const r = await fetch('/api/organograma/hierarquia', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      const data = await r.json();
      if (!r.ok) throw new Error(data.error || r.statusText);
      setSaveMsg({ ok: true, msg: `${data.updated} registos guardados.` });
      load();
    } catch (e) {
      setSaveMsg({ ok: false, msg: e.message });
    } finally { setSaving(false); }
  };

  const isRootTarget = dropTarget === '__root__' && !!dragEmail;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>

      {/* Toolbar */}
      <div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
        <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>
          Arrasta cartões para reorganizar. Clica num cartão para ver detalhes e ocultar.
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 8, alignItems: 'center', flexShrink: 0 }}>
          {pendingChanges > 0 && (
            <span style={{ fontSize: 12, color: '#f59e0b', fontFamily: 'var(--font-mono)' }}>
              {pendingChanges} alteraç{pendingChanges !== 1 ? 'ões' : 'ão'} pendente{pendingChanges !== 1 ? 's' : ''}
            </span>
          )}
          {saveMsg && <span style={{ fontSize: 12, color: saveMsg.ok ? '#22c55e' : '#ef4444' }}>{saveMsg.msg}</span>}
          <button
            className="btn btn-primary btn-sm"
            onClick={saveHierarquia}
            disabled={saving || pendingChanges === 0}
            style={{ display: 'flex', alignItems: 'center', gap: 6 }}
          >
            {saving
              ? <><span style={{ display:'inline-block', width:11, height:11, border:'2px solid rgba(255,255,255,0.3)', borderTopColor:'#fff', borderRadius:'50%', animation:'spin 0.7s linear infinite' }} /> A guardar…</>
              : `↓ Guardar${pendingChanges > 0 ? ` (${pendingChanges})` : ''}`
            }
          </button>
        </div>
      </div>

      {/* Zona de drop para topo */}
      <div
        onDragOver={(e) => { e.preventDefault(); setDropTarget('__root__'); }}
        onDragLeave={(e) => { if (!e.currentTarget.contains(e.relatedTarget)) setDropTarget(t => t === '__root__' ? null : t); }}
        onDrop={(e) => { e.preventDefault(); onDrop('__root__'); }}
        style={{
          padding: '12px 20px', borderRadius: 8, fontSize: 12,
          border: `2px dashed ${isRootTarget ? '#3b82f6' : 'var(--border)'}`,
          background: isRootTarget ? 'rgba(59,130,246,0.08)' : 'transparent',
          color: isRootTarget ? '#3b82f6' : 'var(--text-dim)',
          textAlign: 'center', transition: 'all 0.1s', fontFamily: 'var(--font-mono)',
        }}
      >
        {isRootTarget ? '⬤  Largar aqui → sem superior (topo)' : '↑  Larga aqui para remover superior'}
      </div>

      {/* Árvore DnD */}
      <div style={{ overflowX: 'auto', paddingBottom: 24 }} onDragEnd={() => { setDragEmail(null); setDropTarget(null); }}>
        <div style={{ zoom, display: 'flex', gap: 40, padding: '24px 24px', minWidth: 'max-content', justifyContent: 'center' }}>
          {roots.map(email => (
            <_OrgVisualNode
              key={email} email={email} depth={0}
              byEmail={byEmail} childrenMap={childrenMap}
              expanded={expanded} toggleExpand={toggleExpand}
              editable={true}
              dragEmail={dragEmail} dropTarget={dropTarget}
              onDragStart={onDragStart} onDragOver={onDragOver} onDrop={onDrop}
              hasCycle={hasCycle} edits={edits} origMgr={origMgr} q={q}
              onSelect={onSelect} hiddenEmails={hiddenEmails}
            />
          ))}
        </div>
      </div>

    </div>
  );
};

// ── Componente principal ───────────────────────────────────────────────────

const SistemaOrganograma = ({ user }) => {
  const [tab,           setTab]           = React.useState('organograma');
  const [pessoas,       setPessoas]       = React.useState([]);
  const [loading,       setLoading]       = React.useState(true);
  const [error,         setError]         = React.useState(null);
  const [search,        setSearch]        = React.useState('');
  const [expanded,      setExpanded]      = React.useState({});
  const [hiddenEmails,  setHiddenEmails]  = React.useState(new Set());
  const [selectedEmail, setSelectedEmail] = React.useState(null);
  const [empresaFilter, setEmpresaFilter] = React.useState(new Set());
  const [deptFilter,    setDeptFilter]    = React.useState(new Set());
  const [filtersOpen,   setFiltersOpen]   = React.useState(false);
  const [zoom,          setZoom]          = React.useState(0.8);

  const load = React.useCallback(() => {
    setLoading(true);
    fetch('/api/organograma')
      .then(r => { if (!r.ok) throw new Error(r.statusText); return r.json(); })
      .then(data => {
        setPessoas(data);
        setHiddenEmails(new Set(data.filter(p => p.oculto_organograma).map(p => p.email_profissional)));
        setLoading(false);
      })
      .catch(e  => { setError(e.message); setLoading(false); });
  }, []);

  React.useEffect(() => { load(); }, []);

  const q = search.toLowerCase().trim();
  const byEmail = {};
  for (const p of pessoas) byEmail[p.email_profissional] = p;

  // Empresas únicas para filtros
  const empresas = [...new Set(pessoas.map(p => p.empresa).filter(Boolean))].sort();

  // empresaFilter = conjunto de empresas OCULTAS (vazio = todas visíveis)
  const toggleEmpresa = (emp) =>
    setEmpresaFilter(prev => { const s = new Set(prev); if (s.has(emp)) s.delete(emp); else s.add(emp); return s; });

  // Pessoas visíveis na árvore (exclui empresas ocultas)
  const pessoasVisuais = empresaFilter.size > 0
    ? pessoas.filter(p => p.empresa && !empresaFilter.has(p.empresa))
    : pessoas;

  // Departamentos dinâmicos — só das empresas visíveis
  const departamentos = [...new Set(pessoasVisuais.map(p => p.departamento).filter(Boolean))].sort();

  const toggleDept = (dept) =>
    setDeptFilter(prev => { const s = new Set(prev); if (s.has(dept)) s.delete(dept); else s.add(dept); return s; });

  // Limpar depts ocultos que deixaram de existir quando empresa muda
  React.useEffect(() => {
    if (deptFilter.size === 0) return;
    const validDepts = new Set(departamentos);
    setDeptFilter(prev => {
      const next = new Set([...prev].filter(d => validDepts.has(d)));
      return next.size !== prev.size ? next : prev;
    });
  }, [empresaFilter]);

  // Pessoas finais (após filtro empresa + departamento)
  const pessoasFinais = deptFilter.size > 0
    ? pessoasVisuais.filter(p => p.departamento && !deptFilter.has(p.departamento))
    : pessoasVisuais;

  const toggleHide = (email) => {
    setHiddenEmails(prev => {
      const s = new Set(prev);
      const oculto = !s.has(email);
      if (oculto) s.add(email); else s.delete(email);
      fetch('/api/organograma/oculto', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, oculto }),
      }).catch(() => {});
      return s;
    });
    setSelectedEmail(null);
  };

  const tabs = [
    { id: 'organograma', label: 'Organograma' },
    { id: 'editor',      label: 'Editar hierarquia' },
    { id: 'ocultos',     label: hiddenEmails.size > 0 ? `Ocultos (${hiddenEmails.size})` : 'Ocultos' },
  ];

  return (
    <div style={{ position: 'relative', height: '100%' }}>
    <div className="scrollbar" style={{ height: '100%', overflowY: 'auto', padding: '24px 28px 60px' }}>

      <div style={{ marginBottom: 20, display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', flexWrap: 'wrap', gap: 12 }}>
        <div>
          <div className="font-mono" style={{ fontSize: 10, color: 'var(--text-dim)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>RECURSOS HUMANOS</div>
          <h2 className="font-display" style={{ margin: '4px 0 0', fontSize: 20, fontWeight: 500 }}>Organograma</h2>
        </div>
        <input
          type="text"
          placeholder="Pesquisar nome, cargo, área…"
          value={search}
          onChange={e => setSearch(e.target.value)}
          style={{ padding: '6px 12px', fontSize: 13, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-sunken)', color: 'var(--text)', fontFamily: 'var(--font-body)', width: 240, outline: 'none' }}
        />
      </div>

      <div style={{ display: 'flex', gap: 0, marginBottom: 20, borderBottom: '1px solid var(--border)' }}>
        {tabs.map(t => (
          <button
            key={t.id}
            onClick={() => setTab(t.id)}
            style={{
              padding: '8px 20px', fontSize: 13, fontWeight: tab === t.id ? 600 : 400,
              color: t.id === 'ocultos' && hiddenEmails.size > 0
                ? (tab === t.id ? '#f59e0b' : 'rgba(245,158,11,0.7)')
                : tab === t.id ? 'var(--text)' : 'var(--text-dim)',
              background: 'none', border: 'none',
              borderBottom: tab === t.id ? `2px solid ${t.id === 'ocultos' && hiddenEmails.size > 0 ? '#f59e0b' : 'var(--accent)'}` : '2px solid transparent',
              cursor: 'pointer', marginBottom: -1,
            }}
          >{t.label}</button>
        ))}
        <span style={{ marginLeft: 'auto', fontSize: 12, color: 'var(--text-dim)', alignSelf: 'center', paddingRight: 4, fontFamily: 'var(--font-mono)' }}>
          {`${pessoas.length} colaboradores`}
        </span>
      </div>

      {/* Toolbar: expandir/recolher + zoom + toggle filtros (apenas tabs visuais) */}
      {!loading && !error && (tab === 'organograma' || tab === 'editor') && (
        <div style={{ marginBottom: filtersOpen ? 8 : 16 }}>
          {/* Barra de controlos */}
          <div style={{ display: 'flex', gap: 6, alignItems: 'center', marginBottom: filtersOpen ? 8 : 0 }}>
            <button
              onClick={() => { const e = {}; for (const p of pessoasFinais) e[p.email_profissional] = true; setExpanded(e); }}
              style={{ fontSize: 11, padding: '3px 10px', borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-sunken)', color: 'var(--text-muted)', cursor: 'pointer', whiteSpace: 'nowrap' }}
            >▼ expandir tudo</button>
            <button
              onClick={() => { const e = {}; for (const p of pessoasFinais) e[p.email_profissional] = false; setExpanded(e); }}
              style={{ fontSize: 11, padding: '3px 10px', borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-sunken)', color: 'var(--text-muted)', cursor: 'pointer', whiteSpace: 'nowrap' }}
            >▲ recolher tudo</button>
            <div style={{ width: 1, height: 18, background: 'var(--border)', margin: '0 2px' }} />
            <button onClick={() => setZoom(z => Math.max(0.3, Math.round((z - 0.1) * 10) / 10))}
              style={{ width: 26, height: 26, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-sunken)', color: 'var(--text)', cursor: 'pointer', fontSize: 16, lineHeight: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>−</button>
            <span style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', minWidth: 36, textAlign: 'center' }}>{Math.round(zoom * 100)}%</span>
            <button onClick={() => setZoom(z => Math.min(1.5, Math.round((z + 0.1) * 10) / 10))}
              style={{ width: 26, height: 26, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-sunken)', color: 'var(--text)', cursor: 'pointer', fontSize: 16, lineHeight: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>+</button>
            <div style={{ marginLeft: 'auto' }}>
              <button
                onClick={() => setFiltersOpen(v => !v)}
                style={{
                  fontSize: 11, padding: '3px 12px', borderRadius: 6, cursor: 'pointer',
                  border: `1px solid ${(empresaFilter.size + deptFilter.size) > 0 ? '#1e3a5f' : 'var(--border)'}`,
                  background: (empresaFilter.size + deptFilter.size) > 0 ? '#1e3a5f' : 'var(--bg-sunken)',
                  color: (empresaFilter.size + deptFilter.size) > 0 ? '#fff' : 'var(--text-muted)',
                  fontWeight: 500, whiteSpace: 'nowrap',
                }}
              >
                {filtersOpen ? '▲' : '▼'} Filtros{(empresaFilter.size + deptFilter.size) > 0 ? ` (${empresaFilter.size + deptFilter.size})` : ''}
              </button>
            </div>
          </div>

          {/* Acordeão de filtros */}
          {filtersOpen && (
            <div style={{ padding: '12px 16px', background: 'var(--bg-sunken)', borderRadius: 8, border: '1px solid var(--border)', display: 'flex', flexDirection: 'column', gap: 10 }}>
              {/* Linha empresa */}
              <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                <span style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.06em', flexShrink: 0, minWidth: 56 }}>Empresa:</span>
                {empresas.map(emp => {
                  const hidden = empresaFilter.has(emp);
                  return (
                    <button
                      key={emp}
                      onClick={() => toggleEmpresa(emp)}
                      title={hidden ? `Mostrar ${emp}` : `Ocultar ${emp}`}
                      style={{
                        fontSize: 11, padding: '4px 12px', borderRadius: 12, cursor: 'pointer',
                        border: `1px solid ${hidden ? '#cbd5e1' : '#1e3a5f'}`,
                        background: hidden ? '#f1f5f9' : '#1e3a5f',
                        color: hidden ? '#94a3b8' : '#fff',
                        textDecoration: hidden ? 'line-through' : 'none',
                        fontFamily: 'var(--font-body)', fontWeight: 500, transition: 'all 0.12s',
                      }}
                    >{emp}</button>
                  );
                })}
                {empresaFilter.size > 0 && (
                  <button
                    onClick={() => setEmpresaFilter(new Set())}
                    style={{ fontSize: 11, padding: '4px 10px', borderRadius: 12, cursor: 'pointer', border: '1px solid #cbd5e1', background: '#fff', color: '#64748b', fontWeight: 500 }}
                  >✕ todas</button>
                )}
              </div>
              {/* Linha departamento */}
              {departamentos.length > 1 && (
                <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                  <span style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.06em', flexShrink: 0, minWidth: 56 }}>Dept.:</span>
                  {departamentos.map(dept => {
                    const hidden = deptFilter.has(dept);
                    return (
                      <button
                        key={dept}
                        onClick={() => toggleDept(dept)}
                        title={hidden ? `Mostrar ${dept}` : `Ocultar ${dept}`}
                        style={{
                          fontSize: 11, padding: '4px 12px', borderRadius: 12, cursor: 'pointer',
                          border: `1px solid ${hidden ? '#cbd5e1' : '#475569'}`,
                          background: hidden ? '#f1f5f9' : '#475569',
                          color: hidden ? '#94a3b8' : '#fff',
                          textDecoration: hidden ? 'line-through' : 'none',
                          fontFamily: 'var(--font-body)', fontWeight: 500, transition: 'all 0.12s',
                        }}
                      >{dept}</button>
                    );
                  })}
                  {deptFilter.size > 0 && (
                    <button
                      onClick={() => setDeptFilter(new Set())}
                      style={{ fontSize: 11, padding: '4px 10px', borderRadius: 12, cursor: 'pointer', border: '1px solid #cbd5e1', background: '#fff', color: '#64748b', fontWeight: 500 }}
                    >✕ todos</button>
                  )}
                </div>
              )}
            </div>
          )}
        </div>
      )}

      {loading && <div style={{ color: 'var(--text-dim)', fontSize: 13 }}>A carregar…</div>}
      {error   && <div style={{ color: '#ef4444', fontSize: 13 }}>Erro: {error}</div>}

      {!loading && !error && tab === 'organograma' && <_OrgOrganogramaTab pessoas={pessoasFinais} q={q} expanded={expanded} setExpanded={setExpanded} zoom={zoom} hiddenEmails={hiddenEmails} />}
      {!loading && !error && tab === 'editor'      && (
        <_OrgEditorTab
          pessoas={pessoasFinais} load={load} q={q} expanded={expanded} setExpanded={setExpanded}
          hiddenEmails={hiddenEmails} setHiddenEmails={setHiddenEmails}
          selectedEmail={selectedEmail} setSelectedEmail={setSelectedEmail}
          zoom={zoom}
        />
      )}
      {!loading && !error && tab === 'ocultos'     && <_OrgOcultosTab hiddenEmails={hiddenEmails} setHiddenEmails={setHiddenEmails} byEmail={byEmail} />}

      <style>{`
        @keyframes spin { to { transform: rotate(360deg); } }
        @keyframes slideInRight { from { transform: translateX(40px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
      `}</style>
    </div>

    {/* Painel de detalhe — fora do scroll para position:fixed funcionar correctamente */}
    {selectedEmail && byEmail[selectedEmail] && (
      <_OrgDetailPanel
        email={selectedEmail}
        byEmail={byEmail}
        onClose={() => setSelectedEmail(null)}
        isHidden={hiddenEmails.has(selectedEmail)}
        onToggleHide={() => toggleHide(selectedEmail)}
        isAdmin={user?.tipo === 'admin'}
        load={load}
        pessoas={pessoas}
      />
    )}
    </div>
  );
};

window.SistemaOrganograma = SistemaOrganograma;
