// T2 Falcon Admin — Contact Groups page (orchestrator)
// List + Details reuse Hierarchy/Contracts chrome (.content-panel / .content-body /
// .node-header / .table-panel / .users-table / TablePagination / .info-panel) so the
// page matches the "Contracts & Cost" screen exactly — same header, table and behavior.
// Contact-Groups structure + information (columns, contacts, sharing) are preserved.

const { useState: useStateCG, useMemo: useMemoCG, useEffect: useEffectCG } = React;

// ===== Avatar chip ======
const cgChipPalette = ['#0d3f44', '#15803d', '#a16207', '#7c3aed', '#0369a1', '#b91c1c', '#9333ea'];
const cgInitials = (name) => (name || '').split(/\s+/).map(w => w[0]).filter(Boolean).slice(0, 2).join('').toUpperCase();
const cgChipBg = (name) => cgChipPalette[((name || '').charCodeAt(0) || 0) % cgChipPalette.length];

const CgSharedChips = ({ list = [], max = 2, t = {} }) => {
  const [open, setOpen] = useStateCG(false);
  const [pos, setPos] = useStateCG(null);
  const wrapRef = React.useRef(null);
  const popRef = React.useRef(null);
  const head = list.slice(0, max);
  const more = list.slice(max);
  const rest = more.length;

  // Open a fixed-positioned popup anchored to the +N chip (flips above when there
  // isn't enough room below). Fixed positioning keeps it clear of the table's scroll.
  const toggle = (e) => {
    e.stopPropagation();
    if (open) { setOpen(false); return; }
    const r = e.currentTarget.getBoundingClientRect();
    const spaceBelow = window.innerHeight - r.bottom;
    const POP = 320;
    let top, maxH;
    if (spaceBelow < 220 && r.top > spaceBelow) {
      maxH = Math.min(POP, r.top - 16);
      top = r.top - maxH - 6;
    } else {
      maxH = Math.min(POP, spaceBelow - 16);
      top = r.bottom + 6;
    }
    setPos({ top, left: Math.max(8, Math.min(r.left, window.innerWidth - 308)), maxH });
    setOpen(true);
  };

  useEffectCG(() => {
    if (!open) return;
    const onDown = (e) => {
      if (popRef.current && popRef.current.contains(e.target)) return;
      if (wrapRef.current && wrapRef.current.contains(e.target)) return;
      setOpen(false);
    };
    const close = () => setOpen(false);
    document.addEventListener('mousedown', onDown);
    window.addEventListener('scroll', close, true);
    window.addEventListener('resize', close);
    return () => {
      document.removeEventListener('mousedown', onDown);
      window.removeEventListener('scroll', close, true);
      window.removeEventListener('resize', close);
    };
  }, [open]);

  return (
    <div className="cg-shared-chips" ref={wrapRef}>
      {head.map((n, i) => (
        <span key={i} className="cg-shared-chip" title={n}>{n}</span>
      ))}
      {rest > 0 && (
        <button
          type="button"
          className={`cg-shared-more ${open ? 'on' : ''}`}
          onClick={toggle}
          title={more.join(', ')}
        >+{rest}</button>
      )}
      {open && pos && ReactDOM.createPortal(
        <div
          ref={popRef}
          className="cg-shared-pop"
          style={{ position: 'fixed', top: pos.top, left: pos.left, maxHeight: pos.maxH }}
        >
          <div className="cg-shared-pop-head">{t.cgSharedWithMore || 'Shared with more'}</div>
          <div className="cg-shared-pop-list">
            {more.map((n, i) => (
              <div key={i} className="cg-shared-pop-item">
                <span className="cg-shared-pop-check"><IcCheck size={11} stroke={3} /></span>
                <span className="cg-shared-pop-name">{n}</span>
              </div>
            ))}
          </div>
        </div>,
        document.body
      )}
    </div>
  );
};
window.CgSharedChips = CgSharedChips;

// ===== Scope logo for internal-page topbars =====
// Shows the scoped node's own image — the client's brand logo or an org node's
// initial avatar (same look as the page header) — never the generic Falcon mark.
// Falcon is only used for the actual root scope. Defaults to 32px.
const CgScopeLogo = ({ node, size = 32 }) => {
  const isRoot = node && (node.id === 'falcon' || node.type === 'root');
  if (!node || isRoot) {
    return (
      <span className="cg-scope-logo cg-scope-falcon" style={{ width: size, height: size }}>
        <IcFalcon size={Math.round(size * 0.56)} />
      </span>
    );
  }
  if (node.type === 'client') return <BrandLogo brand={node.brand} size={size} />;
  return (
    <span className="cg-scope-logo cg-scope-node" style={{ width: size, height: size, fontSize: Math.round(size * 0.375) }}>
      {(node.name || 'N').slice(0, 1).toUpperCase()}
    </span>
  );
};
window.CgScopeLogo = CgScopeLogo;

// ===== Editable "Shared with" picker (Share action) — removable chips + add dropdown =====
const CgShareEditor = ({ value = [], onChange, t = {} }) => {
  const pool = window.seedShareUsers || [];
  const [open, setOpen] = useStateCG(false);
  const [q, setQ] = useStateCG('');
  const wrapRef = React.useRef(null);
  useEffectCG(() => {
    if (!open) return;
    const onDown = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDown);
    return () => document.removeEventListener('mousedown', onDown);
  }, [open]);
  const available = pool.filter((n) => !value.includes(n) && n.toLowerCase().includes(q.trim().toLowerCase()));
  const remove = (n) => onChange(value.filter((x) => x !== n));
  const add = (n) => { onChange([...value, n]); setQ(''); };
  return (
    <div className="cg-share-edit">
      <div className="cg-share-edit-chips">
        {value.length === 0 && <span className="cg-share-edit-empty">{t.cgShareNone || 'No users selected yet.'}</span>}
        {value.map((n, i) => (
          <span key={i} className="cg-share-edit-chip">
            <span className="nm">{n}</span>
            <button type="button" className="x" title="Remove" onClick={() => remove(n)}>
              <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
            </button>
          </span>
        ))}
      </div>
      <div className="cg-share-edit-combo" ref={wrapRef}>
        <button type="button" className="cg-share-edit-add" onClick={() => setOpen((o) => !o)}>
          <IcUserPlus size={14} stroke={1.8} /> {t.cgShareAdd || 'Add users'}
        </button>
        {open && (
          <div className="cg-share-edit-pop">
            <div className="cg-share-edit-search">
              <IcSearch size={13} stroke={1.8} />
              <input placeholder={t.search || 'Search'} value={q} onChange={(e) => setQ(e.target.value)} autoFocus />
            </div>
            <div className="cg-share-edit-list">
              {available.length === 0 ? (
                <div className="cg-share-edit-noopt">{t.cgShareNoUsers || 'No more users'}</div>
              ) : available.map((n, i) => (
                <button type="button" key={i} className="cg-share-edit-opt" onClick={() => add(n)}>{n}</button>
              ))}
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

// ===== Delete confirmation dialog (portal) =====
const CgConfirmDelete = ({ row, t = {}, onCancel, onConfirm }) => {
  if (!row) return null;
  return ReactDOM.createPortal(
    <div className="cg-confirm-overlay" onMouseDown={onCancel}>
      <div className="cg-confirm" onMouseDown={(e) => e.stopPropagation()}>
        <div className="cg-confirm-icon"><IcTrash size={20} stroke={1.8} /></div>
        <div className="cg-confirm-title">{t.cgDeleteTitle || 'Delete contact group?'}</div>
        <div className="cg-confirm-body">
          {(t.cgDeleteBody || 'This will remove "{name}" from your list. This action cannot be undone.').replace('{name}', row.name)}
        </div>
        <div className="cg-confirm-actions">
          <button className="btn btn-secondary" onClick={onCancel}>{t.cancel || 'Cancel'}</button>
          <button className="btn cg-confirm-del" onClick={onConfirm}>{t.cgDelete || 'Delete'}</button>
        </div>
      </div>
    </div>,
    document.body
  );
};

// ===== Status badge (reuses Hierarchy's .status-badge dot style, keeps CG labels) =====
// The Status column only ever shows "Completed" or "In Progress" — a deleted record keeps
// its real status here and is marked separately by the `deleted` flag (grey row).
const CgStatusPill = ({ status, t }) => {
  const completed = status === 'completed';
  return (
    <span className={`status-badge ${completed ? 'active' : 'pending'}`}>
      <span className="dot"></span>{completed ? (t.cgStatusCompleted || 'Completed') : (t.cgStatusInProgress || 'In Progress')}
    </span>
  );
};

// ===== Falcon / Client perspective picker (same pattern as Templates / Contracts) =====
const CgViewPicker = ({ t, onPick }) => (
  <div className="tpl-picker-page">
    <div className="tpl-picker-card">
      <div className="tpl-picker-head">
        <div>
          <h2>{t.cgPickerTitle}</h2>
          <p>{t.cgPickerSubtitle}</p>
        </div>
      </div>
      <div className="tpl-picker-grid">
        <button className="tpl-picker-tile falcon" onClick={() => onPick('falcon')}>
          <span className="ic-wrap"><T2Mark size={28} color="white" /></span>
          <span className="ttl">{t.cgShowAsFalcon}</span>
          <span className="dsc">{t.cgShowAsFalconDesc}</span>
          <span className="cta">{t.cgShowAsFalcon} <IcChevronRight size={14} stroke={2} /></span>
        </button>
        <button className="tpl-picker-tile client" onClick={() => onPick('client')}>
          <span className="ic-wrap"><IcBuildingS size={26} stroke={1.7} /></span>
          <span className="ttl">{t.cgShowAsClient}</span>
          <span className="dsc">{t.cgShowAsClientDesc}</span>
          <span className="cta">{t.cgShowAsClient} <IcChevronRight size={14} stroke={2} /></span>
        </button>
      </div>
    </div>
  </div>
);

// ===== "Viewing as" role selector (visual only — mirrors the Wallet header chip) =====
const CgViewingAs = ({ role, setRole, t }) => (
  <div className="wb-tb-viewing cg-viewing-as">
    <span className="wb-tb-viewing-label">{(t.wbViewingAs || 'VIEWING AS').toUpperCase()}</span>
    <div className="wb-role-chip wb-tb-viewing-chip">
      <select className="wb-role-chip-select" value={role} onChange={(e) => setRole(e.target.value)}>
        <option value="account-owner">{t.wbRoleOwner || 'Account Owner'}</option>
        <option value="node-admin">{t.wbRoleNodeAdmin || 'Node Admin'}</option>
        <option value="normal-user">{t.wbRoleNormalUser || 'Normal User'}</option>
      </select>
    </div>
  </div>
);

// ===== Row menu (reuses Hierarchy's .row-menu / .row-menu-item) =====
const CgRowMenu = ({ open, onMore, onShare, onEdit, onDelete, canShare, canEdit, canDelete, t }) => {
  if (!open) return null;
  return (
    <div className="row-menu" onClick={(e) => e.stopPropagation()}>
      <button className="row-menu-item" onClick={onMore}>
        <IcInfo size={14} stroke={1.8} /> <span>{t.moreDetails || 'More Details'}</span>
      </button>
      {canShare && (
        <button className="row-menu-item" onClick={onShare}>
          <IcUserPlus size={14} stroke={1.8} /> <span>{t.cgShare || 'Share'}</span>
        </button>
      )}
      {canEdit && (
        <button className="row-menu-item" onClick={onEdit}>
          <IcEdit size={14} stroke={1.8} /> <span>{t.cgEditGroup || 'Edit Group'}</span>
        </button>
      )}
      {canDelete && (
        <button className="row-menu-item cg-danger-item" onClick={onDelete}>
          <IcTrash size={14} stroke={1.8} /> <span>{t.cgDelete || 'Delete'}</span>
        </button>
      )}
    </div>
  );
};

// ===== List view (reuses .table-panel / .users-table / TablePagination) =====
const CgList = ({ rows, t, title, onView, onShare, onEdit, onDelete, canShare, canEdit, canDelete, openMenuId, setOpenMenuId, page, pageSize, setPage, setPageSize }) => {
  const pageRows = rows.slice((page - 1) * pageSize, page * pageSize);
  // Reuse the Templates list "Shared with" chip (first name + "+N" pill with a click
  // tooltip) so both lists share the exact same layout.
  const SharedChip = window.TplSharedWithChip;
  return (
    <div className="table-panel">
      <div className="table-head-bar">
        <div className="table-head-title">{title || t.contactGroups}</div>
      </div>
      <div className="table-scroll">
        <table className="users-table cg-users-table">
          <thead>
            <tr>
              <th>{t.cgColId}</th>
              <th>{t.cgColName}</th>
              <th>{t.cgColRefId}</th>
              <th>{t.cgColCreatedBy}</th>
              <th>{t.cgColCreated}</th>
              <th>{t.cgColUploaded}</th>
              <th>{t.cgColStatus}</th>
              <th>{t.cgColShared}</th>
              <th className="col-actions">{t.cgColActions}</th>
            </tr>
          </thead>
          <tbody>
            {pageRows.map((r, i) => {
              const idx = (page - 1) * pageSize + i;
              const isOpen = openMenuId === idx;
              const isDeleted = !!r.deleted;
              return (
                <tr
                  key={idx}
                  className={isDeleted ? 'deleted' : ''}
                >
                  <td className="col-username">{r.id}</td>
                  <td>{r.name}</td>
                  <td>{r.referenceId}</td>
                  <td>
                    <div className="cg-creator">
                      <span className="nm">{r.createdBy.name}</span>
                      <span className="em">{r.createdBy.email}</span>
                    </div>
                  </td>
                  <td className="cg-multi">{r.createdAt.split('|').map((s, j) => <div key={j}>{s.trim()}</div>)}</td>
                  <td>{r.uploaded}</td>
                  <td><CgStatusPill status={r.status} t={t} /></td>
                  <td>{SharedChip
                    ? <SharedChip list={r.sharedWith} extra={(r.sharedWith || []).length - 1} t={t} />
                    : <CgSharedChips list={r.sharedWith} max={1} t={t} />}</td>
                  <td className="col-actions" style={{ position: 'relative' }} onClick={(e) => e.stopPropagation()}>
                    <button
                      className={`row-action-btn ${isOpen ? 'open' : ''}`}
                      aria-label="actions"
                      onClick={(e) => { e.stopPropagation(); setOpenMenuId(isOpen ? null : idx); }}
                    >
                      <IcMore size={16} />
                    </button>
                    <CgRowMenu
                      open={isOpen}
                      t={t}
                      canShare={canShare && !isDeleted}
                      canEdit={canEdit && !isDeleted}
                      canDelete={canDelete && !isDeleted}
                      onMore={() => { setOpenMenuId(null); onView(r); }}
                      onShare={() => { setOpenMenuId(null); onShare && onShare(r); }}
                      onEdit={() => { setOpenMenuId(null); onEdit && onEdit(r); }}
                      onDelete={() => { setOpenMenuId(null); onDelete && onDelete(r); }}
                    />
                  </td>
                </tr>
              );
            })}
            {rows.length === 0 && (
              <tr><td colSpan={9} style={{ textAlign: 'center', padding: 40, color: 'var(--text-muted)' }}>
                {t.cgEmpty || 'No contact groups for this scope.'}
              </td></tr>
            )}
          </tbody>
        </table>
      </div>
      <TablePagination
        total={rows.length}
        page={page}
        pageSize={pageSize}
        onPageChange={setPage}
        onPageSizeChange={(n) => { setPageSize(n); setPage(1); }}
        t={t}
      />
    </div>
  );
};

// ===== Details view (info-panel for group details + table-panel for contacts) =====
const CgDetails = ({ row, t, cPage, cPageSize, setCPage, setCPageSize, shareMode, shareDraft, setShareDraft }) => {
  if (!row) return null;
  const showDeletedDate = !!row.deleted;
  const allRows = window.seedContactGroupRows || [];
  const pageRows = allRows.slice((cPage - 1) * cPageSize, cPage * cPageSize);
  return (
    <>
      {/* Group details — same card style as the Templates "Template Details" card. */}
      <div className="tpl-details-card cg-group-details">
        <div className="hd">{t.cgDetailsTitle}</div>
        <div className="tpl-details-grid">
          <div className="tpl-d-field"><span className="lab">{t.cgFldName}</span><span className="val">{row.name}</span></div>
          <div className="tpl-d-field"><span className="lab">{t.cgFldRefId}</span><span className="val">{row.referenceId}</span></div>
          <div className="tpl-d-field"><span className="lab">{t.cgFldContactId}</span><span className="val">{row.contactId}</span></div>
          <div className="tpl-d-field"><span className="lab">{t.cgFldUploaded}</span><span className="val">{row.uploaded}</span></div>
          <div className="tpl-d-field"><span className="lab">{t.cgFldCreatedAt}</span><span className="val">{row.createdAt}</span></div>
          <div className="tpl-d-field"><span className="lab">{t.cgFldCreatedBy}</span><span className="val">{row.createdBy.name}<span className="cg-info-sub">{row.createdBy.email}</span></span></div>
          <div className="tpl-d-field"><span className="lab">{t.cgFldStatus}</span><div className="pill-row"><CgStatusPill status={row.status} t={t} /></div></div>
          {showDeletedDate && (
            <>
              <div className="tpl-d-field"><span className="lab">{t.cgFldDeletedBy || 'Deleted by'}</span><span className="val">{(row.deletedBy && row.deletedBy.name) || '—'}{row.deletedBy && row.deletedBy.email && <span className="cg-info-sub">{row.deletedBy.email}</span>}</span></div>
              <div className="tpl-d-field"><span className="lab">{t.cgFldDeletionDate}</span><span className="val cg-danger">{row.deletedAt || (row.createdAt || '').split('|')[0].trim()}</span></div>
            </>
          )}
          <div className={`tpl-d-field full ${shareMode ? 'cg-d-share-edit' : ''}`}>
            <span className="lab">{t.cgFldSharedWith}{shareMode && <span className="opt"> {t.multiSelectHint || '(Multiple Select)'}</span>}</span>
            {shareMode
              ? <CgShareCombo value={shareDraft || []} onChange={setShareDraft} t={t} />
              : <div className="pill-row">{(row.sharedWith && row.sharedWith.length) ? <CgSharedChips list={row.sharedWith} max={3} t={t} /> : <span className="val">—</span>}</div>}
          </div>
        </div>
      </div>

      {/* Contacts table — reuses .table-panel / .users-table / TablePagination */}
      <div className="table-panel cg-contacts-panel">
        <div className="table-head-bar">
          <div className="table-head-title">{t.cgContactGroup}</div>
          <div className="cg-th-actions">
            <button className="btn cg-th-btn">
              <IcDownload size={15} stroke={1.8} /> {t.cgDownloadOriginal}
            </button>
            <button className="btn cg-th-btn is-primary">
              <IcDownload size={15} stroke={1.8} /> {t.cgDownloadGroup}
            </button>
          </div>
        </div>
        <div className="table-scroll">
          <table className="users-table cg-contacts-table">
            <thead>
              <tr>
                <th className="cg-num">#</th>
                <th>{t.cgFirstName}</th>
                <th>{t.cgLastName}</th>
                <th>{t.cgEmail}</th>
                <th>{t.cgMobile}</th>
                <th>{t.cgCompany}</th>
                <th>{t.cgNotes}</th>
              </tr>
            </thead>
            <tbody>
              {pageRows.map((c, i) => (
                <tr key={i}>
                  <td className="cg-num">{(cPage - 1) * cPageSize + i + 1}</td>
                  <td>{c.first}</td>
                  <td>{c.last}</td>
                  <td className="col-email">{c.email}</td>
                  <td className="col-phone">{c.mobile}</td>
                  <td>{c.company}</td>
                  <td>{c.notes}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <TablePagination
          total={allRows.length}
          page={cPage}
          pageSize={cPageSize}
          onPageChange={setCPage}
          onPageSizeChange={(n) => { setCPageSize(n); setCPage(1); }}
          t={t}
        />
      </div>
    </>
  );
};

// ===== "Shared With" multi-select — mirrors the Edit Template picker (TplShareMulti):
// a "Select…/N Items Selected" trigger + a portaled "Select All" + checkbox dropdown.
// Reuses the `.tpl-share-multi-*` classes so it looks identical to the template screen. =====
const CgShareCombo = ({ value = [], onChange, t = {} }) => {
  const pool = window.seedShareUsers || [];
  const [open, setOpen] = useStateCG(false);
  const [pos, setPos] = useStateCG(null);
  const ref = React.useRef(null);
  const popRef = React.useRef(null);
  useEffectCG(() => {
    if (!open) return;
    const onDown = (e) => {
      if (ref.current && ref.current.contains(e.target)) return;
      if (popRef.current && popRef.current.contains(e.target)) return;
      setOpen(false);
    };
    const close = () => setOpen(false);
    document.addEventListener('mousedown', onDown);
    window.addEventListener('scroll', close, true);
    window.addEventListener('resize', close);
    return () => { document.removeEventListener('mousedown', onDown); window.removeEventListener('scroll', close, true); window.removeEventListener('resize', close); };
  }, [open]);
  const openMenu = () => {
    if (open) { setOpen(false); return; }
    const trig = ref.current && ref.current.querySelector('.tpl-share-multi-trigger');
    if (trig) {
      const r = trig.getBoundingClientRect();
      const spaceBelow = window.innerHeight - r.bottom;
      let top, maxH;
      if (spaceBelow < 200 && r.top > spaceBelow) { maxH = Math.min(280, r.top - 16); top = r.top - maxH - 6; }
      else { maxH = Math.min(280, spaceBelow - 16); top = r.bottom + 4; }
      setPos({ top, left: r.left, width: r.width, maxH });
    }
    setOpen(true);
  };
  const toggle = (n) => onChange(value.includes(n) ? value.filter((x) => x !== n) : [...value, n]);
  const allSelected = pool.length > 0 && pool.every((n) => value.includes(n));
  const toggleAll = () => onChange(allSelected ? [] : [...pool]);
  const label = allSelected ? (t.allSelected || 'All selected')
              : value.length ? `${value.length} ${t.itemsSelected || 'Items Selected'}`
              : (t.selectPlaceholder || 'Select…');
  return (
    <div className="tpl-share-multi-wrap" ref={ref}>
      <button type="button" className={`tpl-field-input tpl-share-multi-trigger ${open ? 'open' : ''}`} onClick={openMenu}>
        <span className={value.length ? '' : 'ph'}>{label}</span>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
      </button>
      {open && pos && ReactDOM.createPortal(
        <div className="tpl-share-multi-pop" ref={popRef} style={{ position: 'fixed', top: pos.top, left: pos.left, width: pos.width, right: 'auto', maxHeight: pos.maxH }}>
          {pool.length > 0 && (
            <>
              <div className={`tpl-share-multi-opt all ${allSelected ? 'on' : ''}`} onClick={toggleAll}>
                <span className="cb">{allSelected && <IcCheck size={10} stroke={3} />}</span>
                <span className="nm"><strong>{t.selectAll || 'Select All'}</strong></span>
              </div>
              <div className="tpl-share-multi-sep" />
            </>
          )}
          {pool.map((n, i) => (
            <div key={i} className={`tpl-share-multi-opt ${value.includes(n) ? 'on' : ''}`} onClick={() => toggle(n)}>
              <span className="cb">{value.includes(n) && <IcCheck size={10} stroke={3} />}</span>
              <span className="nm">{n}</span>
            </div>
          ))}
        </div>,
        document.body
      )}
    </div>
  );
};
window.CgShareCombo = CgShareCombo;

// ===== Single-screen "Edit Contact Group" (replaces the wizard for Edit) =====
const CgEditForm = ({ row, t, scopeNode, onCancel, onSave }) => {
  const [name, setName] = useStateCG(row.name || '');
  const [refId, setRefId] = useStateCG(row.referenceId || '');
  const [shared, setShared] = useStateCG([...(row.sharedWith || [])]);
  const [cPage, setCPage] = useStateCG(1);
  const [cPageSize, setCPageSize] = useStateCG(10);
  const allRows = window.seedContactGroupRows || [];
  const pageRows = allRows.slice((cPage - 1) * cPageSize, cPage * cPageSize);
  const creationDate = (row.createdAt || '').split('|')[0].trim();
  return (
    <div className="ac-page acg-page cg-edit-page">
      <div className="ac-topbar">
        <div className="ac-topbar-brand cw-topbar-brand">
          <CgScopeLogo node={scopeNode} size={32} />
          <span className="ac-brand-name cw-brand-name">{scopeNode?.name || 'Falcon'}</span>
        </div>
        <div className="ac-topbar-actions">
          <button className="btn btn-secondary" type="button" onClick={onCancel}>{t.cancel || 'Cancel'}</button>
          <button className="btn btn-primary" type="button" onClick={() => onSave({ name, referenceId: refId, sharedWith: shared })}>{t.cgShareSave || 'Save'}</button>
        </div>
      </div>
      <div className="ac-body">
        <div className="ac-card">
          <div className="ac-card-head">
            <div className="ac-card-title">{t.cgEditFlowTitle || 'Edit Contact Group'}</div>
          </div>
          <div className="ac-card-body cg-edit-body">
            <div className="ac-field-grid ac-grid-4 cg-edit-grid">
              <div className="ac-field">
                <label className="ac-label">{t.acgNameLabel || 'Contact Group Name'} <span className="req">*</span></label>
                <input className="ac-input" value={name} onChange={(e) => setName(e.target.value)} />
              </div>
              <div className="ac-field">
                <label className="ac-label">{t.cgFldRefId || 'Reference ID'}</label>
                <input className="ac-input" value={refId} onChange={(e) => setRefId(e.target.value)} />
              </div>
              <div className="ac-field">
                <label className="ac-label">{t.cgFldContactId || 'Contact ID'}</label>
                <input className="ac-input is-locked" value={row.contactId || ''} readOnly title={t.fieldLocked || 'This field cannot be changed'} />
              </div>
              <div className="ac-field">
                <label className="ac-label">{t.cgCreationDate || 'Creation Date'}</label>
                <input className="ac-input is-locked" value={creationDate} readOnly title={t.fieldLocked || 'This field cannot be changed'} />
              </div>
              <div className="ac-field wide cg-edit-shared-field">
                <label className="ac-label">{t.cgFldSharedWith || 'Shared With'} <span className="opt">{t.multiSelectHint || '(Multiple Select)'}</span></label>
                <CgShareCombo value={shared} onChange={setShared} t={t} />
              </div>
            </div>

            <div className="table-panel cg-contacts-panel cg-edit-contacts">
              <div className="table-head-bar">
                <div className="table-head-title">{t.cgContactGroup}</div>
                <div className="cg-th-actions">
                  <button className="btn cg-th-btn"><IcDownload size={15} stroke={1.8} /> {t.cgDownloadOriginal}</button>
                  <button className="btn cg-th-btn is-primary"><IcDownload size={15} stroke={1.8} /> {t.cgDownloadGroup}</button>
                </div>
              </div>
              <div className="table-scroll">
                <table className="users-table cg-contacts-table">
                  <thead>
                    <tr>
                      <th className="cg-num">#</th>
                      <th>{t.cgFirstName}</th>
                      <th>{t.cgLastName}</th>
                      <th>{t.cgEmail}</th>
                      <th>{t.cgMobile}</th>
                      <th>{t.cgCompany}</th>
                      <th>{t.cgNotes}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {pageRows.map((c, i) => (
                      <tr key={i}>
                        <td className="cg-num">{(cPage - 1) * cPageSize + i + 1}</td>
                        <td>{c.first}</td>
                        <td>{c.last}</td>
                        <td className="col-email">{c.email}</td>
                        <td className="col-phone">{c.mobile}</td>
                        <td>{c.company}</td>
                        <td>{c.notes}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <TablePagination total={allRows.length} page={cPage} pageSize={cPageSize} onPageChange={setCPage} onPageSizeChange={(n) => { setCPageSize(n); setCPage(1); }} t={t} />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

// ===== Page =====
const ContactGroupsPage = ({ tree, selected, selectNode, expanded, toggleExpand, lang, t, pushToast }) => {
  const [viewAs, setViewAs] = useStateCG(null); // null | 'falcon' | 'client'
  const [mode, setMode] = useStateCG('list'); // 'list' | 'details' | 'create' | 'edit'
  const [activeRow, setActiveRow] = useStateCG(null);
  const [openMenuId, setOpenMenuId] = useStateCG(null);
  const [role, setRole] = useStateCG('account-owner'); // "Viewing as" — drives the Client-view experience
  const [cgTab, setCgTab] = useStateCG('groups'); // Normal-User tabs: 'groups' | 'shared'
  const [shareMode, setShareMode] = useStateCG(false); // Share action → editable "Shared with" in details
  const [shareDraft, setShareDraft] = useStateCG([]);
  const [deleteRow, setDeleteRow] = useStateCG(null); // pending delete confirmation
  const [removedIds, setRemovedIds] = useStateCG(() => new Set()); // session-deleted (by contactId)
  // List pagination (mirrors Contracts' table footer)
  const [page, setPage] = useStateCG(1);
  const [pageSize, setPageSize] = useStateCG(10);
  // Contacts (details) pagination
  const [cPage, setCPage] = useStateCG(1);
  const [cPageSize, setCPageSize] = useStateCG(10);

  const findInTree = (node, id) => {
    if (!node) return null;
    if (node.id === id) return node;
    for (const c of (node.children || [])) {
      const r = findInTree(c, id);
      if (r) return r;
    }
    return null;
  };

  const scopedTree = useMemoCG(() => {
    if (viewAs === 'client') {
      const aramco = findInTree(tree, 'aramco');
      return aramco || tree;
    }
    return tree;
  }, [tree, viewAs]);

  useEffectCG(() => {
    if (viewAs === 'client') {
      const stillValid = findInTree(scopedTree, selected);
      if (!stillValid) selectNode('aramco');
    }
  }, [viewAs]); // eslint-disable-line

  const scopeNode = findInTree(scopedTree, selected) || scopedTree;

  // Close kebab menu on outside click
  useEffectCG(() => {
    const onDoc = () => setOpenMenuId(null);
    document.addEventListener('click', onDoc);
    return () => document.removeEventListener('click', onDoc);
  }, []);

  if (viewAs === null) {
    return <CgViewPicker t={t} onPick={(v) => { setViewAs(v); setMode('list'); }} />;
  }

  const isFalcon = viewAs === 'falcon';

  // ---- Role-driven Client-view behavior ----
  const isOwnerAdmin = !isFalcon && (role === 'account-owner' || role === 'node-admin');
  const isNormalUser = !isFalcon && role === 'normal-user';
  const showTree = isFalcon || isOwnerAdmin;             // hierarchy tree for Falcon + owner/admin
  const onSharedTab = isNormalUser && cgTab === 'shared';

  // Changing the previewed role resets transient state.
  const changeRole = (r) => {
    setRole(r); setMode('list'); setShareMode(false); setActiveRow(null);
    setCgTab('groups'); setOpenMenuId(null); setPage(1);
  };

  // Rows for the current role/tab, minus deleted (client) + session-removed.
  const baseRows = onSharedTab ? (window.seedSharedGroups || []) : (window.seedContactGroups || []);
  const listRows = baseRows.filter(r => (isFalcon || onSharedTab || !r.deleted) && !removedIds.has(r.contactId));

  // Per-row capabilities. "Everything is mine" → Edit/Delete on every row (not Falcon, not Shared tab).
  const canShareRows = isOwnerAdmin;
  const canEditRows = !isFalcon && !onSharedTab;
  const canDeleteRows = !isFalcon && !onSharedTab;

  const openShare = (r) => {
    setActiveRow(r); setShareDraft([...(r.sharedWith || [])]); setShareMode(true);
    setMode('details'); setOpenMenuId(null); setCPage(1);
  };
  const saveShare = () => {
    if (activeRow) activeRow.sharedWith = [...shareDraft];
    pushToast && pushToast(t.cgSharedToast || 'Sharing updated ✓');
    setShareMode(false); setMode('list'); setActiveRow(null);
  };
  const cancelShare = () => { setShareMode(false); setMode('list'); setActiveRow(null); };
  const confirmDelete = () => {
    if (deleteRow) {
      setRemovedIds(prev => { const n = new Set(prev); n.add(deleteRow.contactId); return n; });
      pushToast && pushToast(t.cgDeletedToast || 'Contact group deleted ✓');
    }
    setDeleteRow(null);
  };

  const isRootScope = scopeNode && (scopeNode.id === 'falcon' || scopeNode.type === 'root');
  // Header avatar — mirrors Hierarchy/Contracts: Falcon icon for root, BrandLogo
  // for client nodes, initial-avatar for inner org nodes.
  const ScopeAvatar = () => {
    if (!scopeNode) return null;
    if (isRootScope) return <span className="node-avatar"><IcFalcon size={18} /></span>;
    if (scopeNode.type === 'client') return <BrandLogo brand={scopeNode.brand} size={32} />;
    return (
      <span className="node-avatar" style={{ background: '#0d3f44', color: 'white' }}>
        <span style={{ fontSize: 12, fontWeight: 700 }}>{(scopeNode.name || 'N').slice(0, 1)}</span>
      </span>
    );
  };

  return (
    <div className={`templates-page cg-page ${showTree ? 'with-tree' : 'no-tree'}`}>
      {/* Hierarchy tree — Falcon view + Account Owner / Node Admin (Client view). */}
      {showTree && (
        <TplOrgTree
          tree={scopedTree}
          selected={selected}
          selectNode={selectNode}
          expanded={expanded}
          toggleExpand={toggleExpand}
          t={t}
          rootClickable={!isFalcon}
          hideSectionLabel={!isFalcon}
          hideMenus={true}
        />
      )}

      <div className="content-panel">
        {(mode === 'list' || mode === 'details') && (
        <div className="content-body">
          {/* Hierarchy-style node header — avatar + name on the left, "Viewing as"
              role selector + perspective/create actions on the right. */}
          <div className="node-header">
            <div className={`node-title ${isRootScope ? 'falcon' : ''}`}>
              <ScopeAvatar />
              <span>{scopeNode ? scopeNode.name : t.contactGroups}</span>
            </div>
            <div className="node-actions">
              {/* "Viewing as" role selector — Client list view only. */}
              {!isFalcon && mode === 'list' && <CgViewingAs role={role} setRole={changeRole} t={t} />}
              {mode === 'details' ? (
                shareMode ? (
                  <>
                    <button className="btn btn-secondary" onClick={cancelShare}>{t.cancel || 'Cancel'}</button>
                    <button className="btn btn-primary" onClick={saveShare}>{t.cgShareSave || 'Save'}</button>
                  </>
                ) : (
                  <button
                    className="btn btn-secondary"
                    onClick={() => { setMode('list'); setActiveRow(null); }}
                  >
                    <IcArrowLeft size={12} stroke={1.7} /> {t.cgBackToList || 'Back to list'}
                  </button>
                )
              ) : (
                <button
                  className="btn btn-secondary"
                  onClick={() => { setViewAs(null); setMode('list'); selectNode('falcon'); }}
                >
                  <IcArrowLeft size={12} stroke={1.7} /> {t.tplBackToPicker || 'Switch perspective'}
                </button>
              )}
              {mode === 'list' && !isFalcon && !onSharedTab && (
                <button className="btn btn-primary" onClick={() => { setActiveRow(null); setMode('create'); }}>
                  <IcPlus size={15} stroke={2} /> {t.cgCreateGroup || 'Create Contact Group'}
                </button>
              )}
            </div>
          </div>

          {/* Normal-User tabs: Contact Groups / Shared Groups */}
          {isNormalUser && mode === 'list' && (
            <div className="tabs-bar cg-tabs">
              <button className={`tab ${cgTab === 'groups' ? 'active' : ''}`} onClick={() => { setCgTab('groups'); setPage(1); setOpenMenuId(null); }}>{t.cgTabGroups || 'Contact Groups'}</button>
              <button className={`tab ${cgTab === 'shared' ? 'active' : ''}`} onClick={() => { setCgTab('shared'); setPage(1); setOpenMenuId(null); }}>{t.cgTabShared || 'Shared Groups'}</button>
            </div>
          )}

          {mode === 'list' && (
            <CgList
              rows={listRows}
              t={t}
              title={onSharedTab ? (t.cgTabShared || 'Shared Groups') : (t.contactGroups || 'Contact Groups')}
              canShare={canShareRows}
              canEdit={canEditRows}
              canDelete={canDeleteRows}
              onView={(r) => { setActiveRow(r); setMode('details'); setShareMode(false); setOpenMenuId(null); setCPage(1); }}
              onShare={openShare}
              onEdit={(r) => { setActiveRow(r); setMode('edit'); setOpenMenuId(null); }}
              onDelete={(r) => { setDeleteRow(r); setOpenMenuId(null); }}
              openMenuId={openMenuId}
              setOpenMenuId={setOpenMenuId}
              page={page}
              pageSize={pageSize}
              setPage={setPage}
              setPageSize={setPageSize}
            />
          )}

          {mode === 'details' && (
            <CgDetails
              row={activeRow}
              t={t}
              cPage={cPage}
              cPageSize={cPageSize}
              setCPage={setCPage}
              setCPageSize={setCPageSize}
              shareMode={shareMode}
              shareDraft={shareDraft}
              setShareDraft={setShareDraft}
            />
          )}
        </div>
        )}

        {/* Create wizard — rendered inside .content-panel so it sits within the page
            chrome (like Add New Contract), not as a full-screen takeover. */}
        {mode === 'create' && (
          <AddContactGroupFlow
            scopeNode={scopeNode}
            scopedTree={scopedTree}
            selected={selected}
            selectNode={selectNode}
            expanded={expanded}
            toggleExpand={toggleExpand}
            initial={null}
            t={t}
            pushToast={pushToast}
            onClose={() => { setMode('list'); setActiveRow(null); }}
          />
        )}

        {/* Edit — single-screen form (not the wizard). */}
        {mode === 'edit' && activeRow && (
          <CgEditForm
            row={activeRow}
            t={t}
            scopeNode={scopeNode}
            onCancel={() => { setMode('list'); setActiveRow(null); }}
            onSave={(patch) => {
              if (activeRow) { activeRow.name = patch.name; activeRow.referenceId = patch.referenceId; activeRow.sharedWith = [...patch.sharedWith]; }
              pushToast && pushToast(t.cgUpdatedToast || 'Contact group updated ✓');
              setMode('list'); setActiveRow(null);
            }}
          />
        )}
      </div>

      <CgConfirmDelete row={deleteRow} t={t} onCancel={() => setDeleteRow(null)} onConfirm={confirmDelete} />
    </div>
  );
};

window.ContactGroupsPage = ContactGroupsPage;
