// Org Chart screen — interactive expandable tree of the firm.
// Top: David Harvey. Below: 12 branch leads as collapsible cards. Click a person to drill.

const F_org = window.VAULT_FIRM;
const { useState: useOrgState, useMemo: useOrgMemo } = React;

function OrgChartScreen({ scope, isAdmin }) {
  const tree = F_org.ORG_TREE;
  const president = F_org.PEOPLE_BY_ID[tree.presidentId];

  // Mutable branch order kept in component state so admin drag-reorder persists for the session.
  const [branchOrder, setBranchOrder] = useOrgState(() => tree.branches.map(b => b.id));
  const branchLeads = branchOrder.map(id => F_org.PEOPLE_BY_ID[id]).filter(Boolean);

  const [expanded, setExpanded] = useOrgState(() => new Set(branchLeads.slice(0, 4).map(p => p.id)));
  const [focus, setFocus] = useOrgState(null);
  const [filter, setFilter] = useOrgState("");
  const [editingPerson, setEditingPerson] = useOrgState(null); // id of person being edited
  const [addingPerson, setAddingPerson] = useOrgState(false);
  const [dragId, setDragId] = useOrgState(null);
  const [dragOverId, setDragOverId] = useOrgState(null);
  const [orgTick, forceOrg] = React.useReducer(x => x + 1, 0);

  // Build children map — re-derives whenever forceOrg() ticks (add/edit employee).
  const childrenOf = useOrgMemo(() => {
    const m = {};
    F_org.PEOPLE.forEach(p => {
      if (p.supId) (m[p.supId] = m[p.supId] || []).push(p);
    });
    Object.values(m).forEach(arr => arr.sort((a, b) => {
      const order = { MD: 0, VP: 1, Associate: 2, Analyst: 3 };
      return (order[a.role] ?? 9) - (order[b.role] ?? 9) || a.name.localeCompare(b.name);
    }));
    return m;
  }, [orgTick]);

  // Filter
  const lc = filter.trim().toLowerCase();
  const matchesFilter = lc ? (p) => (p.name + " " + p.title).toLowerCase().includes(lc) : null;

  // When a filter is active, build the set of matching ids + every ancestor of a match.
  // BranchCard / TreeNode use this to (a) auto-expand the path down to matches and
  // (b) hide siblings that aren't on a match path. This is what makes the search bar
  // actually return visible results.
  const { matchSet, ancestorSet } = useOrgMemo(() => {
    if (!matchesFilter) return { matchSet: null, ancestorSet: null };
    const matches = new Set();
    const ancestors = new Set();
    F_org.PEOPLE.forEach(p => { if (matchesFilter(p)) matches.add(p.id); });
    // Walk parent chain for every match
    matches.forEach(id => {
      let cur = F_org.PEOPLE_BY_ID[id]?.supId;
      const guard = new Set();
      while (cur && !guard.has(cur)) {
        ancestors.add(cur);
        guard.add(cur);
        cur = F_org.PEOPLE_BY_ID[cur]?.supId;
      }
    });
    return { matchSet: matches, ancestorSet: ancestors };
  }, [lc, orgTick]);

  function toggle(id) {
    const next = new Set(expanded);
    if (next.has(id)) next.delete(id); else next.add(id);
    setExpanded(next);
  }
  function expandAll() { setExpanded(new Set(F_org.PEOPLE.map(p => p.id))); }
  function collapseAll() { setExpanded(new Set()); }

  return (
    <div style={{ display: "grid", gridTemplateColumns: focus ? "1fr 360px" : "1fr", gap: 20 }}>
      <div className="col" style={{ gap: 18 }}>
        {/* Toolbar */}
        <div className="card card-pad" style={{ padding: "14px 18px" }}>
          <div className="row" style={{ gap: 12, flexWrap: "wrap" }}>
            <div style={{ flex: 1, minWidth: 220, position: "relative" }}>
              <span style={{ position: "absolute", left: 10, top: 9, color: "var(--muted)" }}><Icon.search/></span>
              <input
                value={filter}
                onChange={e => setFilter(e.target.value)}
                placeholder="Filter by name or title…"
                style={{
                  width: "100%", padding: "7px 10px 7px 30px",
                  border: "1px solid var(--line)", borderRadius: 8,
                  background: "var(--surface)", color: "var(--ink)",
                  fontSize: 12.5,
                }}
              />
            </div>
            <div className="row" style={{ gap: 6 }}>
              <button className="btn sm" onClick={expandAll}>Expand all</button>
              <button className="btn sm" onClick={collapseAll}>Collapse all</button>
              {isAdmin && (
                <button className="btn primary sm" onClick={() => setAddingPerson(true)} title="Add a new employee to the org">
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
                    <svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M6 1.5v9M1.5 6h9" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
                    Add employee
                  </span>
                </button>
              )}
            </div>
            <div className="row" style={{ gap: 18, marginLeft: "auto" }}>
              <Stat label="People" value={F_org.PEOPLE.length}/>
              <Stat label="Branches" value={branchLeads.length}/>
              <Stat label="Avg span" value={(F_org.PEOPLE.length / Math.max(1, branchLeads.length)).toFixed(1)}/>
            </div>
          </div>
        </div>

        {/* President */}
        <div style={{ display: "flex", justifyContent: "center", paddingTop: 6 }}>
          <PersonCard
            person={president}
            big
            onClick={() => setFocus(president.id)}
            highlighted={focus === president.id}
            descCount={F_org.PEOPLE.length - 1}
          />
        </div>

        {/* Connector down */}
        <div style={{ display: "flex", justifyContent: "center", height: 24, position: "relative" }}>
          <div style={{ width: 2, background: "var(--line)" }}/>
        </div>

        {/* Branches */}
        <div style={{
          display: "grid",
          gridTemplateColumns: "repeat(auto-fill, minmax(320px, 1fr))",
          gap: 14,
        }}>
          {branchLeads.map(lead => {
            const branch = tree.branches.find(b => b.id === lead.id);
            const hasMatchUnder = ancestorSet ? ancestorSet.has(lead.id) || (matchSet && matchSet.has(lead.id)) : false;
            // Auto-expand branch when filtering and it contains a match.
            const isOpen = (matchesFilter ? hasMatchUnder : expanded.has(lead.id));
            // When filtering with no match in this branch, hide it entirely.
            if (matchesFilter && !hasMatchUnder) return null;
            return (
              <div
                key={lead.id}
                draggable={isAdmin}
                onDragStart={(e) => { if (!isAdmin) return; setDragId(lead.id); e.dataTransfer.effectAllowed = "move"; }}
                onDragOver={(e) => { if (!isAdmin) return; e.preventDefault(); setDragOverId(lead.id); }}
                onDragLeave={() => setDragOverId(null)}
                onDrop={(e) => {
                  if (!isAdmin || !dragId || dragId === lead.id) return;
                  e.preventDefault();
                  const next = branchOrder.filter(id => id !== dragId);
                  const idx = next.indexOf(lead.id);
                  next.splice(idx, 0, dragId);
                  setBranchOrder(next);
                  setDragId(null); setDragOverId(null);
                }}
                onDragEnd={() => { setDragId(null); setDragOverId(null); }}
                style={{
                  opacity: dragId === lead.id ? 0.4 : 1,
                  outline: dragOverId === lead.id && dragId !== lead.id ? "2px dashed var(--accent)" : "none",
                  outlineOffset: 2, borderRadius: 14,
                  transition: "opacity .15s, outline-color .12s",
                }}
              >
                <BranchCard
                  lead={lead}
                  branchTitle={branch.title}
                  count={branch.count}
                  expanded={isOpen}
                  onToggle={() => toggle(lead.id)}
                  onPickPerson={(id) => setFocus(id)}
                  focusedId={focus}
                  childrenOf={childrenOf}
                  expandedSet={expanded}
                  toggleNode={toggle}
                  filtered={!!matchesFilter}
                  matchSet={matchSet}
                  ancestorSet={ancestorSet}
                  isAdmin={isAdmin}
                  onEditPerson={(id) => setEditingPerson(id)}
                />
              </div>
            );
          })}
        </div>
      </div>

      {focus && (
        <PersonDetail
          personId={focus}
          onClose={() => setFocus(null)}
          childrenOf={childrenOf}
          isAdmin={isAdmin}
          onEdit={() => setEditingPerson(focus)}
        />
      )}

      {editingPerson && (
        <EditPersonModal
          personId={editingPerson}
          onClose={() => setEditingPerson(null)}
          onSaved={() => { setEditingPerson(null); forceOrg(); }}
        />
      )}

      {addingPerson && (
        <AddPersonModal
          onClose={() => setAddingPerson(false)}
          onSaved={(newId) => {
            setAddingPerson(false);
            // Walk the new person's manager chain and expand every ancestor so the
            // tree shows them slotted into the right place — not just the branch lead,
            // but every intermediate node up to it.
            const next = new Set(expanded);
            let cur = F_org.PEOPLE_BY_ID[newId]?.supId;
            const guard = new Set();
            while (cur && !guard.has(cur)) {
              guard.add(cur);
              next.add(cur);
              cur = F_org.PEOPLE_BY_ID[cur]?.supId;
            }
            const branchId = F_org.ORG_TREE.branchOf[newId];
            if (branchId) next.add(branchId);
            setExpanded(next);
            // If this added a brand-new branch lead, append to branch order.
            if (!branchOrder.includes(newId) && F_org.ORG_TREE.branches.some(b => b.id === newId)) {
              setBranchOrder([...branchOrder, newId]);
            }
            setFocus(newId);
            forceOrg();
          }}
        />
      )}
    </div>
  );
}

function collectDescendants(rootId, childrenOf) {
  const out = [];
  const stack = [rootId];
  const seen = new Set();
  while (stack.length) {
    const id = stack.shift();
    if (seen.has(id)) continue; seen.add(id);
    const kids = childrenOf[id] || [];
    for (const k of kids) { out.push(k); stack.push(k.id); }
  }
  return out;
}

function Stat({ label, value }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 2, lineHeight: 1.1 }}>
      <span className="micro">{label}</span>
      <span className="display" style={{ fontSize: 18 }}>{value}</span>
    </div>
  );
}

function PersonCard({ person, big, onClick, highlighted, descCount, role }) {
  if (!person) return null;
  const size = big ? "xl" : "lg";
  return (
    <button onClick={onClick} style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: big ? "14px 18px" : "10px 12px",
      background: highlighted ? "var(--accent-soft)" : "var(--surface)",
      border: "1px solid " + (highlighted ? "var(--accent)" : "var(--line)"),
      borderRadius: 12,
      minWidth: big ? 280 : 0,
      textAlign: "left",
      transition: "border-color .12s, background .12s",
    }}>
      <Avatar id={person.id} size={size}/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: big ? 15 : 13, fontWeight: 600, color: "var(--ink)" }}>{person.name}</div>
        <div className="muted" style={{ fontSize: big ? 12 : 11, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{person.title}</div>
      </div>
      {descCount != null && descCount > 0 && (
        <span className="pill accent" style={{ fontSize: 10 }}>
          <span className="dot"/>{descCount} reports
        </span>
      )}
    </button>
  );
}

function BranchCard({ lead, branchTitle, count, expanded, onToggle, onPickPerson, focusedId, childrenOf, expandedSet, toggleNode, filtered, matchSet, ancestorSet, isAdmin, onEditPerson }) {
  const directReports = (childrenOf[lead.id] || []).filter(c => {
    if (!filtered) return true;
    return (matchSet && matchSet.has(c.id)) || (ancestorSet && ancestorSet.has(c.id));
  });
  return (
    <div className="card" style={{ padding: 14, display: "flex", flexDirection: "column", gap: 10 }}>
      <div className="row" style={{ gap: 10 }}>
        {isAdmin && (
          <span title="Drag to reorder" style={{ cursor: "grab", color: "var(--muted-2)", padding: "0 2px", display: "inline-flex", alignItems: "center" }}>
            <svg width="10" height="14" viewBox="0 0 10 14" fill="currentColor"><circle cx="3" cy="3" r="1"/><circle cx="7" cy="3" r="1"/><circle cx="3" cy="7" r="1"/><circle cx="7" cy="7" r="1"/><circle cx="3" cy="11" r="1"/><circle cx="7" cy="11" r="1"/></svg>
          </span>
        )}
        <Avatar id={lead.id} size="lg"/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="row" style={{ gap: 6 }}>
            <span style={{ fontSize: 13.5, fontWeight: 600 }}>{lead.name}</span>
            {isAdmin && (
              <button className="btn ghost sm" onClick={(e) => { e.stopPropagation(); onEditPerson(lead.id); }} style={{ padding: 2, color: "var(--muted)" }} title="Edit">
                <svg width="11" height="11" viewBox="0 0 16 16" fill="none"><path d="M11 2l3 3-8 8H3v-3z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/></svg>
              </button>
            )}
          </div>
          <div className="muted" style={{ fontSize: 11 }}>{branchTitle}</div>
        </div>
        <span className="tag" title="Branch headcount">{count}</span>
        <button className="btn ghost sm" onClick={onToggle} style={{ padding: 4 }} title={expanded ? "Collapse" : "Expand"}>
          <span style={{ display: "inline-flex", transform: expanded ? "rotate(90deg)" : "rotate(0deg)", transition: "transform .15s" }}>
            <Icon.chevron/>
          </span>
        </button>
      </div>

      {expanded && (
        <div style={{ borderTop: "1px solid var(--line-2)", paddingTop: 8 }}>
          {directReports.length === 0 && <div className="muted small" style={{ padding: "6px 4px" }}>No direct reports</div>}
          {directReports.map(child => (
            <TreeNode
              key={child.id}
              person={child}
              depth={0}
              childrenOf={childrenOf}
              expandedSet={expandedSet}
              toggleNode={toggleNode}
              onPick={onPickPerson}
              focusedId={focusedId}
              isAdmin={isAdmin}
              onEditPerson={onEditPerson}
              filtered={filtered}
              matchSet={matchSet}
              ancestorSet={ancestorSet}
            />
          ))}
        </div>
      )}
    </div>
  );
}

function TreeNode({ person, depth, childrenOf, expandedSet, toggleNode, onPick, focusedId, isAdmin, onEditPerson, filtered, matchSet, ancestorSet }) {
  const allKids = childrenOf[person.id] || [];
  const kids = filtered
    ? allKids.filter(k => (matchSet && matchSet.has(k.id)) || (ancestorSet && ancestorSet.has(k.id)))
    : allKids;
  // Auto-open when filtering and this node is an ancestor of a match.
  const open = filtered ? (ancestorSet && ancestorSet.has(person.id)) : expandedSet.has(person.id);
  const isMatch = filtered && matchSet && matchSet.has(person.id);
  return (
    <div>
      <div
        onClick={() => onPick(person.id)}
        style={{
          display: "flex", alignItems: "center", gap: 8,
          padding: "5px 6px",
          paddingLeft: 6 + depth * 18,
          borderRadius: 6,
          background: focusedId === person.id ? "var(--accent-soft)" : (isMatch ? "var(--accent-soft)" : "transparent"),
          cursor: "pointer",
          fontSize: 12.5,
        }}
        onMouseEnter={e => focusedId !== person.id && (e.currentTarget.style.background = "var(--canvas)")}
        onMouseLeave={e => focusedId !== person.id && (e.currentTarget.style.background = "transparent")}
      >
        {kids.length > 0 ? (
          <button onClick={(e) => { e.stopPropagation(); toggleNode(person.id); }}
            style={{
              border: 0, background: "transparent", padding: 0,
              width: 14, height: 14, display: "inline-flex", alignItems: "center", justifyContent: "center",
              color: "var(--muted)",
              transform: open ? "rotate(90deg)" : "rotate(0deg)", transition: "transform .12s",
            }}>
            <Icon.chevron/>
          </button>
        ) : (
          <span style={{ width: 14, display: "inline-block" }}/>
        )}
        <Avatar id={person.id}/>
        <span style={{ flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: "var(--ink)", fontWeight: focusedId === person.id ? 600 : 500 }}>
          {person.name}
        </span>
        <span className="muted" title={person.title} style={{ fontSize: 10.5, maxWidth: 130, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flexShrink: 0 }}>{person.title}</span>
        {isAdmin && (
          <button className="btn ghost sm" onClick={(e) => { e.stopPropagation(); onEditPerson(person.id); }} style={{ padding: 2, color: "var(--muted-2)" }} title="Edit">
            <svg width="10" height="10" viewBox="0 0 16 16" fill="none"><path d="M11 2l3 3-8 8H3v-3z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/></svg>
          </button>
        )}
      </div>
      {open && kids.map(k => (
        <TreeNode key={k.id} person={k} depth={depth + 1}
          childrenOf={childrenOf} expandedSet={expandedSet} toggleNode={toggleNode}
          onPick={onPick} focusedId={focusedId}
          isAdmin={isAdmin} onEditPerson={onEditPerson}
          filtered={filtered} matchSet={matchSet} ancestorSet={ancestorSet}
        />
      ))}
    </div>
  );
}

function PersonDetail({ personId, onClose, childrenOf, isAdmin, onEdit }) {
  const p = F_org.PEOPLE_BY_ID[personId];
  if (!p) return null;

  // Manager chain up
  const chain = [];
  let cur = p;
  while (cur && cur.supId) {
    const m = F_org.PEOPLE_BY_ID[cur.supId];
    if (!m) break;
    chain.push(m);
    cur = m;
  }

  // Direct reports
  const reports = childrenOf[p.id] || [];

  // Activity totals (last 12 weeks)
  const acts = F_org.ACTIVITY.filter(a => a.personId === p.id);
  const sum = acts.reduce((a, x) => ({
    calls:   a.calls   + x.calls,
    visits:  a.visits  + x.visits,
    cc:      a.cc      + x.confCalls,
    leads:   a.leads   + x.leads,
    offers:  a.offers  + x.offers,
    lois:    a.lois    + x.signedLOIs,
  }), { calls:0, visits:0, cc:0, leads:0, offers:0, lois:0 });

  return (
    <div className="card" style={{
      padding: 18, position: "sticky", top: 76,
      alignSelf: "start",
      maxHeight: "calc(100vh - 96px)", overflowY: "auto",
    }}>
      <div className="row" style={{ alignItems: "flex-start", marginBottom: 12 }}>
        <Avatar id={p.id} size="xl"/>
        <div style={{ flex: 1, marginLeft: 12, minWidth: 0 }}>
          <div className="display" style={{ fontSize: 18, lineHeight: 1.2 }}>{p.name}</div>
          <div className="muted small">{p.title}</div>
        </div>
        {isAdmin && (
          <button className="btn sm" onClick={onEdit} style={{ padding: "4px 8px", marginRight: 6 }} title="Edit employee">
            <svg width="11" height="11" viewBox="0 0 16 16" fill="none"><path d="M11 2l3 3-8 8H3v-3z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/></svg>
            Edit
          </button>
        )}
        <button className="btn ghost sm" onClick={onClose} title="Close" style={{ padding: 4 }}>
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3l8 8M11 3l-8 8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
        </button>
      </div>

      {chain.length > 0 && (
        <div style={{ marginBottom: 18 }}>
          <div className="micro" style={{ marginBottom: 8 }}>Reports up to</div>
          <div className="col" style={{ gap: 6 }}>
            {chain.slice().reverse().map((m, i) => (
              <div key={m.id} className="row" style={{ gap: 8, paddingLeft: i * 12, fontSize: 12 }}>
                <span style={{ color: "var(--muted-2)", fontSize: 10 }}>↳</span>
                <Avatar id={m.id}/>
                <span style={{ flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{m.name}</span>
                <span className="muted small" title={m.title} style={{ maxWidth: 110, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{m.title}</span>
              </div>
            ))}
          </div>
        </div>
      )}

      <div style={{ marginBottom: 18 }}>
        <div className="micro" style={{ marginBottom: 8 }}>Direct reports · {reports.length}</div>
        {reports.length === 0 ? (
          <div className="muted small" style={{ padding: "4px 0" }}>None</div>
        ) : (
          <div className="col" style={{ gap: 6 }}>
            {reports.map(r => (
              <div key={r.id} className="row" style={{ gap: 8, fontSize: 12 }}>
                <Avatar id={r.id}/>
                <span style={{ flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{r.name}</span>
                <span className="muted small">{r.title}</span>
              </div>
            ))}
          </div>
        )}
      </div>

      <div>
        <div className="micro" style={{ marginBottom: 8 }}>Last 12 weeks</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8 }}>
          <DetailStat label="Calls"    value={sum.calls}/>
          <DetailStat label="Conf calls"value={sum.cc}/>
          <DetailStat label="Visits"   value={sum.visits}/>
          <DetailStat label="Leads"    value={sum.leads}/>
          <DetailStat label="Offers"   value={sum.offers}/>
          <DetailStat label="LOIs"     value={sum.lois}/>
        </div>
      </div>
    </div>
  );
}

function DetailStat({ label, value }) {
  return (
    <div style={{
      padding: "10px 11px",
      background: "var(--canvas)",
      border: "1px solid var(--line-2)",
      borderRadius: 8,
    }}>
      <div className="micro" style={{ fontSize: 9.5, marginBottom: 2 }}>{label}</div>
      <div className="display num" style={{ fontSize: 18 }}>{(value || 0).toLocaleString()}</div>
    </div>
  );
}

// Admin: edit-person modal — name/title/role/team/sub-team/supervisor + email
function EditPersonModal({ personId, onClose, onSaved }) {
  const p = F_org.PEOPLE_BY_ID[personId];
  if (!p) return null;
  const [name, setName]   = React.useState(p.name);
  const [title, setTitle] = React.useState(p.title || "");
  const [role, setRole]   = React.useState(p.role || "");
  const [email, setEmail] = React.useState(p.email || `${p.id.replace("p_","")}@harveyllc.com`);
  const [supId, setSupId] = React.useState(p.supId || "");
  const [subteam, setSubteam] = React.useState(p.subteamId || p.subTeam || "");
  const [moduleId, setModuleId] = React.useState(p.moduleId || "");

  const save = () => {
    p.name = name; p.title = title; p.role = role; p.email = email;
    p.supId = supId || null; p.subteamId = subteam; p.moduleId = moduleId;
    p.initials = name.split(" ").map(s => s[0]).join("").slice(0,2).toUpperCase();
    onSaved && onSaved();
  };

  const allPeople = F_org.PEOPLE.filter(x => x.id !== p.id);
  const subteams = (F_org.SUBTEAMS || []);
  const modules  = (F_org.MODULES  || []);

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 60,
      background: "rgba(20,19,15,.4)",
      display: "flex", alignItems: "center", justifyContent: "center",
    }}>
      <div onClick={e => e.stopPropagation()} className="card" style={{
        width: 540, maxWidth: "92vw", maxHeight: "86vh", overflow: "auto",
      }}>
        <div className="row" style={{ padding: "14px 18px", borderBottom: "1px solid var(--line)" }}>
          <Avatar id={p.id} size="lg"/>
          <div style={{ flex: 1, marginLeft: 10 }}>
            <div className="micro">Edit employee · admin</div>
            <div className="display" style={{ fontSize: 18, marginTop: 1 }}>{p.name}</div>
          </div>
          <button className="btn ghost sm" onClick={onClose} style={{ padding: 4 }}>
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3l8 8M11 3l-8 8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
          </button>
        </div>
        <div style={{ padding: 18, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <EditField label="Full name" value={name} onChange={setName} colSpan={2}/>
          <EditField label="Title" value={title} onChange={setTitle} colSpan={2}/>
          <EditField label="Role"  value={role}  onChange={setRole}/>
          <EditField label="Email" value={email} onChange={setEmail}/>
          <EditSelect label="Supervisor" value={supId} onChange={setSupId} options={[{value:"",label:"— none —"}, ...allPeople.map(x => ({value:x.id,label:`${x.name} · ${x.role}`}))]}/>
          <EditSelect label="Module" value={moduleId} onChange={setModuleId} options={[{value:"",label:"— none —"}, ...modules.map(m => ({value:m.id,label:m.label||m.name||m.id}))]}/>
          <EditSelect label="Sub-Team" value={subteam} onChange={setSubteam} colSpan={2} options={[{value:"",label:"— none —"}, ...subteams.map(s => ({value:s.id,label:(s.label||s.name||s.id).replace(/^.*— /,"")}))]}/>
        </div>
        <div className="row" style={{ padding: "12px 18px", borderTop: "1px solid var(--line)", gap: 8 }}>
          <div style={{ flex: 1 }}/>
          <button className="btn sm" onClick={onClose}>Cancel</button>
          <button className="btn primary sm" onClick={save}>Save changes</button>
        </div>
      </div>
    </div>
  );
}

function EditField({ label, value, onChange, colSpan }) {
  return (
    <label style={{ gridColumn: colSpan ? `span ${colSpan}` : "auto" }}>
      <div className="micro" style={{ marginBottom: 4 }}>{label}</div>
      <input value={value} onChange={e => onChange(e.target.value)} style={{
        width: "100%", padding: "7px 10px", fontSize: 13,
        border: "1px solid var(--line)", borderRadius: 6,
        background: "var(--surface)", color: "var(--ink)",
      }}/>
    </label>
  );
}
function EditSelect({ label, value, onChange, options, colSpan }) {
  return (
    <label style={{ gridColumn: colSpan ? `span ${colSpan}` : "auto" }}>
      <div className="micro" style={{ marginBottom: 4 }}>{label}</div>
      <select value={value} onChange={e => onChange(e.target.value)} style={{
        width: "100%", padding: "7px 10px", fontSize: 13,
        border: "1px solid var(--line)", borderRadius: 6,
        background: "var(--surface)", color: "var(--ink)",
      }}>
        {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
    </label>
  );
}

window.OrgChartScreen = OrgChartScreen;

// Admin: add-person modal — creates a new employee and slots them into the org tree.
function AddPersonModal({ onClose, onSaved }) {
  const [name, setName]   = React.useState("");
  const [title, setTitle] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [supId, setSupId] = React.useState("");
  const [error, setError] = React.useState("");

  const subteams = F_org.SUBTEAMS || [];
  // Default sub-team derived from supervisor — admin can override.
  const supSubteam = supId ? (F_org.PEOPLE_BY_ID[supId]?.subteam || "") : "";
  const [subteam, setSubteam] = React.useState("");
  const effectiveSubteam = subteam || supSubteam;

  const allPeople = F_org.PEOPLE.slice().sort((a, b) => a.name.localeCompare(b.name));

  // Same bucketing as data-firm.js roleFor (mirrored locally).
  function bucketRole(t) {
    const s = (t || "").toLowerCase();
    if (s.includes("executive vice president") || s.includes("evp")) return "MD";
    if (s.includes("vice president") || s === "vp") return "VP";
    if (s === "president" || s.includes("ceo")) return "MD";
    if (s.includes("managing director")) return "MD";
    if (s.includes("director")) return "MD";
    if (s.includes("cfo") || s.includes("chief")) return "MD";
    if (s.includes("associate")) return "Associate";
    if (s.includes("analyst")) return "Analyst";
    if (s.includes("manager")) return "VP";
    if (s.includes("coordinator") || s.includes("specialist") || s.includes("admin") || s.includes("recruiter") || s.includes("designer")) return "Associate";
    return "Associate";
  }

  function genId(fullName) {
    const parts = fullName.trim().split(/\s+/);
    if (!parts.length) return "";
    const base = (parts[0][0] + parts[parts.length - 1]).toLowerCase().replace(/[^a-z0-9]/g, "");
    let id = base, i = 2;
    while (F_org.PEOPLE_BY_ID[id]) { id = base + i; i++; }
    return id;
  }

  // Walk up sup chain until we hit a registered branch lead (or president).
  function findBranchOwner(sId) {
    const branchIds = new Set((F_org.ORG_TREE.branches || []).map(b => b.id));
    let cur = sId;
    const guard = new Set();
    while (cur && !guard.has(cur)) {
      guard.add(cur);
      if (branchIds.has(cur)) return cur;
      if (cur === F_org.ORG_TREE.presidentId) return null; // reports to top → becomes a new branch
      cur = F_org.PEOPLE_BY_ID[cur]?.supId;
    }
    return null;
  }

  const save = () => {
    if (!name.trim())  return setError("Name is required.");
    if (!title.trim()) return setError("Title is required.");
    if (!supId)        return setError("Pick a supervisor — drives team & sub-team.");

    const id = genId(name);
    const role = bucketRole(title);
    const initials = name.split(/\s+/).map(s => s[0]).join("").slice(0, 2).toUpperCase();
    const tones = ["a","b","c","d","e"];
    let h = 0; for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) | 0;
    const tone = tones[Math.abs(h) % tones.length];

    const branchOwner = findBranchOwner(supId);
    const subteamId = effectiveSubteam || (branchOwner ? "st-" + branchOwner : "st-" + id);

    const newPerson = {
      id, name: name.trim(), initials, role, title: title.trim(),
      subteam: subteamId, synth: false, tone,
      supId: supId || null,
      email: email.trim() || `${id}@harveyllc.com`,
    };

    F_org.PEOPLE.push(newPerson);
    F_org.PEOPLE_BY_ID[id] = newPerson;

    if (branchOwner) {
      // Slots into an existing branch.
      F_org.ORG_TREE.branchOf[id] = branchOwner;
      const b = F_org.ORG_TREE.branches.find(x => x.id === branchOwner);
      if (b) b.count = (b.count || 0) + 1;
    } else {
      // Reports to the president → becomes a new branch lead.
      F_org.ORG_TREE.branchOf[id] = id;
      F_org.ORG_TREE.branches.push({ id, name: newPerson.name, title: newPerson.title, count: 1 });
      // Make sure a sub-team exists for the new branch.
      if (!subteams.find(s => s.id === "st-" + id)) {
        subteams.push({
          id: "st-" + id, moduleId: "deals",
          label: newPerson.name.split(" ").pop(),
          synth: false, lead: id, leadTitle: newPerson.title, headcount: 1,
        });
      }
    }

    onSaved && onSaved(id);
  };

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 60,
      background: "rgba(20,19,15,.4)",
      display: "flex", alignItems: "center", justifyContent: "center",
    }}>
      <div onClick={e => e.stopPropagation()} className="card" style={{
        width: 560, maxWidth: "92vw", maxHeight: "86vh", overflow: "auto",
      }}>
        <div className="row" style={{ padding: "14px 18px", borderBottom: "1px solid var(--line)" }}>
          <div style={{ flex: 1 }}>
            <div className="micro">Admin</div>
            <div className="display" style={{ fontSize: 18, marginTop: 1 }}>Add employee</div>
          </div>
          <button className="btn ghost sm" onClick={onClose} style={{ padding: 4 }}>
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3l8 8M11 3l-8 8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
          </button>
        </div>
        <div style={{ padding: 18, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <EditField label="Full name" value={name}  onChange={(v) => { setName(v); setError(""); }} colSpan={2}/>
          <EditSelect
            label="Title"
            value={title}
            onChange={(v) => { setTitle(v); setError(""); }}
            colSpan={2}
            options={[
              { value: "", label: "— pick a title —" },
              ...Array.from(new Set(F_org.PEOPLE.map(p => p.title).filter(Boolean)))
                .sort((a, b) => a.localeCompare(b))
                .map(t => ({ value: t, label: t })),
            ]}
          />
          <EditField label="Email"     value={email} onChange={setEmail} colSpan={2}/>
          <EditSelect
            label="Supervisor (drives team & sub-team)"
            value={supId}
            onChange={(v) => { setSupId(v); setSubteam(""); setError(""); }}
            colSpan={2}
            options={[{value: "", label: "— pick a supervisor —"}, ...allPeople.map(x => ({value: x.id, label: `${x.name} · ${x.title || x.role}`}))]}
          />
          <EditSelect
            label="Sub-Team override"
            value={subteam}
            onChange={setSubteam}
            colSpan={2}
            options={[
              { value: "", label: supSubteam ? `(inherit from supervisor → ${subteams.find(s => s.id === supSubteam)?.label || supSubteam})` : "(pick supervisor first)" },
              ...subteams.map(s => ({ value: s.id, label: (s.label || s.name || s.id).replace(/^.*— /, "") })),
            ]}
          />
          {error && (
            <div style={{
              gridColumn: "span 2",
              padding: "8px 10px",
              fontSize: 12,
              background: "color-mix(in oklab, var(--accent) 12%, transparent)",
              color: "var(--accent)",
              border: "1px solid color-mix(in oklab, var(--accent) 30%, transparent)",
              borderRadius: 6,
            }}>{error}</div>
          )}
        </div>
        <div className="row" style={{ padding: "12px 18px", borderTop: "1px solid var(--line)", gap: 8 }}>
          <div className="muted small" style={{ flex: 1 }}>
            Bucketed role: <strong>{title ? bucketRole(title) : "—"}</strong>
          </div>
          <button className="btn sm" onClick={onClose}>Cancel</button>
          <button className="btn primary sm" onClick={save}>Add to org</button>
        </div>
      </div>
    </div>
  );
}
