// T2 Falcon Admin — Add / Edit Contact Group flow

const { useState: useStateACG, useRef: useRefACG, useMemo: useMemoACG, useEffect: useEffectACG } = React;

// ===== Steps =====
const ACG_STEPS = [
  { id: 'upload',  label: 'Upload & Group details' },
  { id: 'preview', label: 'Preview & Configure' },
  { id: 'share',   label: 'Share group' },
  { id: 'review',  label: 'Review & create' },
];

// ===== Sample parsed file (used to seed Step 2 after "upload") =====
const ACG_SAMPLE_HEADERS = ['First Name', 'Last Name', 'Email', 'Mobile', 'Company', 'Notes'];
const ACG_SAMPLE_ROWS = [
  ['Ahmad', 'Hassan',    'ahmad@aramco.sa', '0528726398', 'Aramco', 'VIP Clients'],
  ['Sara',  'Mohammad',  'sara@aramco.sa',  '0528726398', 'Aramco', '---'],
  ['Ali',   'Al-Rashid', 'ali@aramco.sa',   '0528726398', 'Aramco', 'Follow Up'],
  ['Lina',  'Ibrahim',   '---',             '0528726398', 'Aramco', 'New Lead'],
  ['Omar',  'Ahmad',     'omar@aramco.sa',  '0528726398', '---',    'Referral'],
  ['Hala',  'Saleh',     'hala@aramco.sa',  '0528726398', 'Aramco', 'VIP Clients'],
  ['Yousef','Nasser',    'yousef@aramco.sa','0528726398', 'Aramco', '---'],
  ['Mona',  'Ghazi',     'mona@aramco.sa',  '0528726398', 'Aramco', 'Follow Up'],
  ['Faisal','Otaibi',    '---',             '0528726398', 'Aramco', 'New Lead'],
  ['Reem',  'Khalid',    'reem@aramco.sa',  '0528726398', '---',    'Referral'],
];

// ===== People you can share with =====
const ACG_SHARE_USERS = [
  { id: 'u1', name: 'testpthnew testpthnew', role: 'Normal User', email: 'testpthnewtestpthnew' },
  { id: 'u2', name: 'Sara Ahmad',     role: 'Admin',    email: 's.ahmad@aramco.sa' },
  { id: 'u3', name: 'Omar Hassan',    role: 'Manager',  email: 'o.hassan@aramco.sa' },
  { id: 'u4', name: 'Lian Ali',       role: 'Operator', email: 'l.ali@aramco.sa' },
  { id: 'u5', name: 'Mohammad Saad',  role: 'Operator', email: 'm.saad@aramco.sa' },
  { id: 'u6', name: 'Leen Khaled',    role: 'Viewer',   email: 'l.khaled@aramco.sa' },
  { id: 'u7', name: 'Ali Mohammad',   role: 'Manager',  email: 'a.mohammad@aramco.sa' },
  { id: 'u8', name: 'Noor Joudeh',    role: 'Admin',    email: 'n.joudeh@aramco.sa' },
];

// ===== Column-name validation rules (each is an independent toggleable check) =====
const ACG_RULES = [
  { id: 'required', label: 'Name is required',                              test: (v) => v.trim().length > 0 },
  { id: 'alnum',    label: 'Allow only letters (A-Z) and numbers (0-9)',    test: (v) => /^[A-Za-z0-9_]*$/.test(v) },
  { id: 'start',    label: 'Must start with a letter',                      test: (v) => /^[A-Za-z]/.test(v) },
  { id: 'unique',   label: 'Unique column names',                           test: (v, all, idx) => !all.some((c, i) => i !== idx && !c.hidden && c.name && c.name === v) },
  { id: 'symbols',  label: 'No special characters or symbols',              test: (v) => /^[A-Za-z0-9_]*$/.test(v) },
  { id: 'trim',     label: 'No leading or trailing spaces',                 test: (v) => v === v.trim() },
  { id: 'length',   label: 'Character length (2–32)',                       test: (v) => v.trim().length >= 2 && v.trim().length <= 32 },
];

const acgNormalizeCol = (raw) => (raw || '').replace(/\s+/g, '_');

// Returns { failed: ['ruleId',...] } for a column, ignoring its disabledRules.
const acgEvalCol = (col, all, idx) => {
  if (col.hidden) return { failed: [] };
  const failed = [];
  for (const r of ACG_RULES) {
    if (col.disabledRules && col.disabledRules.includes(r.id)) continue;
    if (!r.test(col.name || '', all, idx)) failed.push(r.id);
  }
  return { failed };
};

// ===== Stepper (reuses .ac-stepper styles) =====
const ACGStepBar = ({ current, onJump }) => {
  const pct = (current / (ACG_STEPS.length - 1)) * 100;
  return (
    <div className="ac-stepper">
      <div className="ac-stepper-track">
        <div className="ac-stepper-fill" style={{ width: `${pct}%` }} />
        {ACG_STEPS.map((s, i) => {
          const state = i < current ? 'done' : i === current ? 'active' : 'idle';
          return (
            <button
              key={s.id}
              className={`ac-stepper-dot ${state}`}
              style={{ left: `${(i / (ACG_STEPS.length - 1)) * 100}%` }}
              onClick={() => onJump && i <= current && onJump(i)}
              type="button"
              aria-label={s.label}
            >
              {state === 'done' ? (
                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>
              ) : state === 'active' ? <span className="ac-stepper-dot-pulse" /> : null}
            </button>
          );
        })}
      </div>
      <div className="ac-stepper-labels">
        {ACG_STEPS.map((s, i) => (
          <span
            key={s.id}
            className={`ac-step-label ${i === current ? 'active' : ''} ${i < current ? 'done' : ''}`}
            style={{ left: `${(i / (ACG_STEPS.length - 1)) * 100}%` }}
          >
            {s.label}
          </span>
        ))}
      </div>
    </div>
  );
};

// ===== Step 1 — Upload =====
const ACGStep1 = ({ data, onChange, errors }) => {
  const ref = useRefACG(null);
  const [drag, setDrag] = useStateACG(false);
  const accept = (file) => {
    if (!file) return;
    onChange('file', { name: file.name, size: file.size });
    onChange('columns', ACG_SAMPLE_HEADERS.map((h) => ({ name: h, hidden: false, disabledRules: /\s/.test(h) ? ['alnum', 'symbols'] : [] })));
    onChange('rows', ACG_SAMPLE_ROWS);
    onChange('firstRowHeader', true);
  };
  const fmtSize = (b) => b > 1024 * 1024 ? (b / 1024 / 1024).toFixed(1) + ' MB' : (b / 1024).toFixed(1) + ' KB';

  return (
    <div className="ac-step-pane">
      <div className="ac-field-grid ac-grid-4">
        <div className="ac-field wide">
          <label className="ac-label">Contact Group Name <span className="req">*</span></label>
          <input
            className={`ac-input ${errors.name ? 'error' : ''}`}
            placeholder="e.g. NewlyJoining (max 30 characters)"
            value={data.name}
            onChange={(e) => onChange('name', e.target.value)}
          />
          {errors.name && <span className="ac-error-msg">{errors.name}</span>}
        </div>
        <div className="ac-field">
          <label className="ac-label">Reference ID</label>
          <input
            className="ac-input"
            placeholder="e.g. 111222"
            value={data.referenceId}
            onChange={(e) => onChange('referenceId', e.target.value)}
          />
        </div>
      </div>

      {/* Contact File field + drop zone */}
      <div className="acg-file-field">
        <label className="ac-label">Contact File <span className="req">*</span></label>
        <div
          className={`acg-drop ${drag ? 'drag-over' : ''} ${data.file ? 'has-file' : ''} ${errors.file ? 'error' : ''}`}
          onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
          onDragLeave={() => setDrag(false)}
          onDrop={(e) => { e.preventDefault(); setDrag(false); accept(e.dataTransfer.files[0]); }}
          onClick={() => !data.file && ref.current?.click()}
        >
          {!data.file ? (
            <>
              <span className="acg-drop-icon">
                <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                  <polyline points="17 8 12 3 7 8" />
                  <line x1="12" y1="3" x2="12" y2="15" />
                </svg>
              </span>
              <div className="acg-drop-title">Drop your file here or click to browse</div>
              <div className="acg-drop-sub">supports .xlsx .xls .csv files / max size 20MB</div>
            </>
          ) : (
            <div className="acg-file-chip">
              <span className="acg-file-icon sheet">
                <svg width="52" height="52" viewBox="0 0 24 24" fill="none">
                  <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" fill="#0f9d58" stroke="#0f9d58" strokeLinejoin="round"/>
                  <path d="M14 2v6h6" fill="#5fbb86" stroke="white" strokeWidth="0.5"/>
                  <rect x="7" y="11" width="10" height="8" fill="white"/>
                  <path d="M7 13h10M7 15h10M7 17h10M10 11v8M14 11v8" stroke="#0f9d58" strokeWidth="0.7"/>
                </svg>
              </span>
              <div className="acg-file-meta">
                <strong>{data.file.name}</strong>
                <span>{fmtSize(data.file.size)}</span>
              </div>
              <button
                type="button"
                className="acg-file-remove"
                title="Remove file"
                onClick={(e) => { e.stopPropagation(); onChange('file', null); onChange('columns', []); onChange('rows', []); }}
              >
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
              </button>
            </div>
          )}
          <input ref={ref} type="file" accept=".csv,.xlsx,.xls" style={{ display: 'none' }} onChange={(e) => accept(e.target.files[0])} />
        </div>
        {errors.file && <span className="ac-error-msg">{errors.file}</span>}
      </div>

      <div className="acg-hint">
        <IcInfo size={14} stroke={1.8} />
        First row of the file is treated as column names. You'll review and rename them in the next step.
      </div>
    </div>
  );
};

// ===== Validation popover (portal — fixed position so it never gets clipped) =====
const ACGRulePopover = ({ col, all, idx, anchorEl, onToggleRule, onClose }) => {
  const { failed } = acgEvalCol(col, all, idx);
  const ref = useRefACG(null);
  const [pos, setPos] = useStateACG({ top: 0, left: 0 });
  useEffectACG(() => {
    const reposition = () => {
      if (!anchorEl) return;
      const r = anchorEl.getBoundingClientRect();
      setPos({ top: r.bottom + 6, left: r.left });
    };
    reposition();
    window.addEventListener('scroll', reposition, true);
    window.addEventListener('resize', reposition);
    return () => {
      window.removeEventListener('scroll', reposition, true);
      window.removeEventListener('resize', reposition);
    };
  }, [anchorEl]);
  useEffectACG(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target) && anchorEl && !anchorEl.contains(e.target)) onClose(); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [anchorEl]);
  return ReactDOM.createPortal(
    <div className="acg-rule-pop" ref={ref} style={{ top: pos.top, left: pos.left }}>
      {ACG_RULES.map((r) => {
        const disabled = (col.disabledRules || []).includes(r.id);
        if (disabled) return null;
        const isFail = failed.includes(r.id);
        return (
          <div key={r.id} className={`acg-rule ${isFail ? 'fail' : 'ok'}`}>
            {isFail ? (
              <span className="acg-rule-ic warn">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><circle cx="12" cy="17" r="0.7" fill="currentColor"/></svg>
              </span>
            ) : (
              <span className="acg-rule-ic ok">
                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>
              </span>
            )}
            <span className="acg-rule-label">{r.label}</span>
            <button
              type="button"
              className="acg-rule-x"
              title="Disable this rule"
              onClick={(e) => { e.stopPropagation(); onToggleRule(r.id); }}
            >
              <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
            </button>
          </div>
        );
      })}
      {(col.disabledRules || []).length > 0 && (
        <div className="acg-rule-disabled-wrap">
          <span className="acg-rule-disabled-label">Disabled</span>
          {(col.disabledRules || []).map((rid) => {
            const r = ACG_RULES.find(x => x.id === rid);
            if (!r) return null;
            return (
              <button
                key={rid}
                type="button"
                className="acg-rule-restore"
                onClick={(e) => { e.stopPropagation(); onToggleRule(rid); }}
              >
                {r.label} <span className="plus">+</span>
              </button>
            );
          })}
        </div>
      )}
    </div>,
    document.body
  );
};

// ===== Header cell with editable input + eye toggle + validation popover =====
// Eye icons (single source of truth)
const ACGEyeOn = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12Z"/><circle cx="12" cy="12" r="3"/></svg>
);
const ACGEyeOff = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
);

const ACGHeaderCell = ({ col, all, idx, openIdx, setOpenIdx, onChangeName, onToggleHidden, onToggleRule }) => {
  const open = openIdx === idx;
  const { failed } = acgEvalCol(col, all, idx);
  const isInvalid = !col.hidden && failed.length > 0;
  const wrapRef = useRefACG(null);
  return (
    <div ref={wrapRef} className={`acg-hdr-cell ${col.hidden ? 'is-hidden' : ''} ${isInvalid ? 'is-invalid' : ''}`}>
      <input
        className="acg-hdr-input"
        value={col.name}
        maxLength={32}
        disabled={col.hidden}
        onFocus={() => setOpenIdx(idx)}
        onClick={() => setOpenIdx(idx)}
        onChange={(e) => onChangeName(idx, acgNormalizeCol(e.target.value).slice(0, 32))}
        placeholder="Column name"
      />
      {open && !col.hidden && (
        <ACGRulePopover
          col={col}
          all={all}
          idx={idx}
          anchorEl={wrapRef.current}
          onToggleRule={(rid) => onToggleRule(idx, rid)}
          onClose={() => setOpenIdx(null)}
        />
      )}
    </div>
  );
};

// ===== Step 2 — Preview & validate columns =====
const ACGStep2 = ({ data, onChange, t = {} }) => {
  const [openIdx, setOpenIdx] = useStateACG(null);
  const [pPage, setPPage] = useStateACG(1);
  const [pPageSize, setPPageSize] = useStateACG(10);
  const cols = data.columns;

  const setColName = (i, val) => {
    const next = cols.map((c, k) => k === i ? { ...c, name: val } : c);
    onChange('columns', next);
  };
  const toggleHidden = (i) => {
    const next = cols.map((c, k) => k === i ? { ...c, hidden: !c.hidden } : c);
    onChange('columns', next);
  };
  const toggleRule = (i, rid) => {
    const next = cols.map((c, k) => {
      if (k !== i) return c;
      const dis = c.disabledRules || [];
      return { ...c, disabledRules: dis.includes(rid) ? dis.filter(x => x !== rid) : [...dis, rid] };
    });
    onChange('columns', next);
  };
  const toggleColCheck = (i) => toggleHidden(i); // checkbox above table = "uncheck to ignore"

  if (!cols.length) {
    return (
      <div className="ac-step-pane">
        <div className="acg-empty">
          <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#a8b0b8" strokeWidth="1.4"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></svg>
          <div>No file uploaded yet — go back to Step 1.</div>
        </div>
      </div>
    );
  }

  const visibleCols = cols.map((c, i) => ({ ...c, _i: i })).filter(c => !c.hidden);

  return (
    <div className="ac-step-pane" onClick={() => setOpenIdx(null)}>
      {/* First row is header toggle — checking it derives the column names from the
         first row; unchecking treats the first row as data and clears the names so
         the user must label each column manually before continuing. */}
      <label className="acg-first-row-toggle">
        <input
          type="checkbox"
          checked={!!data.firstRowHeader}
          onChange={(e) => {
            const checked = e.target.checked;
            onChange('firstRowHeader', checked);
            onChange('columns', cols.map((c, i) => {
              const h = ACG_SAMPLE_HEADERS[i] || '';
              return checked
                ? { ...c, name: h, disabledRules: /\s/.test(h) ? ['alnum', 'symbols'] : [] }
                : { ...c, name: '', disabledRules: [] };
            }));
          }}
        />
        <span className="acg-cb-mark">{data.firstRowHeader && <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>}</span>
        The first row is the header
      </label>

      {/* Column toggle chips */}
      <div className="acg-cols-section">
        <div className="acg-cols-section-head">
          <span className="acg-cols-title">Columns</span>
          <span className="acg-cols-hint">(Uncheck To Ignore)</span>
        </div>
        <div className="acg-col-chips">
          {cols.every((c) => !(c.name || '').trim()) ? (
            <span className="acg-cols-none">None</span>
          ) : cols.map((c, i) => (c.name || '').trim() ? (
            <button
              type="button"
              key={i}
              className={`acg-col-chip-tog ${!c.hidden ? 'on' : 'off'}`}
              onClick={() => toggleColCheck(i)}
              title={c.hidden ? 'Show column' : 'Hide column'}
            >
              <span className="acg-col-chip-eye">{c.hidden ? <ACGEyeOff size={13} /> : <ACGEyeOn size={13} />}</span>
              <span>{c.name}</span>
            </button>
          ) : null)}
        </div>
      </div>

      {/* Data preview with editable header */}
      <div className="acg-cols-section">
        <div className="acg-cols-section-head">
          <span className="acg-cols-title">Data Preview</span>
          <span className="acg-spaces-note">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><circle cx="12" cy="16" r="0.6" fill="currentColor"/></svg>
            Spaces will be replaced with underscores ( _ )
          </span>
        </div>

        <div className="acg-preview-panel" onClick={(e) => e.stopPropagation()}>
          <div className="acg-preview-wrap">
            <table className="acg-preview-tbl">
              <thead>
                <tr>
                  <th className="num">#</th>
                  {visibleCols.map((c) => (
                    <th key={c._i}>
                      <ACGHeaderCell
                        col={c}
                        all={cols}
                        idx={c._i}
                        openIdx={openIdx}
                        setOpenIdx={setOpenIdx}
                        onChangeName={setColName}
                        onToggleHidden={toggleHidden}
                        onToggleRule={toggleRule}
                      />
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {data.rows.slice((pPage - 1) * pPageSize, pPage * pPageSize).map((r, ri) => {
                  const rowNo = (pPage - 1) * pPageSize + ri + 1;
                  return (
                    <tr key={rowNo}>
                      <td className="num">{rowNo}</td>
                      {visibleCols.map((c) => (
                        <td key={c._i} className="muted">{r[c._i] != null ? r[c._i] : '—'}</td>
                      ))}
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          {window.TablePagination && (
            <window.TablePagination
              total={data.rows.length}
              page={pPage}
              pageSize={pPageSize}
              onPageChange={setPPage}
              onPageSizeChange={(n) => { setPPageSize(n); setPPage(1); }}
              t={t}
            />
          )}
        </div>
      </div>
    </div>
  );
};

// ===== Step 3 — Share =====
const ACGStep3 = ({ data, onChange }) => {
  const [open, setOpen] = useStateACG(false);
  const [q, setQ] = useStateACG('');
  const wrapRef = useRefACG(null);

  useEffectACG(() => {
    const onDoc = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, []);

  const filtered = useMemoACG(() => {
    const ql = q.trim().toLowerCase();
    if (!ql) return ACG_SHARE_USERS;
    return ACG_SHARE_USERS.filter(u =>
      u.name.toLowerCase().includes(ql) || u.email.toLowerCase().includes(ql) || u.role.toLowerCase().includes(ql)
    );
  }, [q]);

  const toggle = (id) => {
    const set = new Set(data.shared);
    set.has(id) ? set.delete(id) : set.add(id);
    onChange('shared', Array.from(set));
  };
  const allOn = ACG_SHARE_USERS.every(u => data.shared.includes(u.id));
  const toggleAll = () => onChange('shared', allOn ? [] : ACG_SHARE_USERS.map(u => u.id));

  const selected = ACG_SHARE_USERS.filter(u => data.shared.includes(u.id));
  const visibleChips = selected.slice(0, 3);
  const overflow = Math.max(0, selected.length - 3);

  return (
    <div className="ac-step-pane">
      <div className="acg-share-grid">
        {/* LEFT — searcher with chips */}
        <div className="acg-share-left">
          <div className="acg-share-label">
            Shared With <span className="muted">Normal User (Multiple Select)</span>
          </div>
          <div className={`acg-combo ${open ? 'open' : ''}`} ref={wrapRef}>
            <button
              type="button"
              className="acg-combo-control"
              onClick={() => setOpen(o => !o)}
            >
              <span className="acg-combo-chips">
                {selected.length === 0 && <span className="acg-combo-placeholder">Select users…</span>}
                {visibleChips.map((u) => (
                  <span key={u.id} className="acg-combo-chip" onClick={(e) => { e.stopPropagation(); toggle(u.id); }}>
                    {u.name}
                    <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
                  </span>
                ))}
                {overflow > 0 && <span className="acg-combo-chip more">+{overflow} more</span>}
              </span>
              <svg className="acg-combo-caret" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
            </button>

            {open && (
              <div className="acg-combo-pop">
                <div className="acg-combo-search">
                  <IcSearch size={13} stroke={1.8} />
                  <input
                    placeholder="Search"
                    value={q}
                    onChange={(e) => setQ(e.target.value)}
                    autoFocus
                  />
                </div>
                <label className={`acg-combo-row all ${allOn ? 'on' : ''}`}>
                  <input type="checkbox" checked={allOn} onChange={toggleAll} />
                  <span className="acg-cb-mark">{allOn && <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>}</span>
                  <span className="acg-combo-row-name">All Users</span>
                </label>
                <div className="acg-combo-list">
                  {filtered.length === 0 ? (
                    <div className="acg-combo-empty">No users match "{q}"</div>
                  ) : filtered.map((u) => {
                    const on = data.shared.includes(u.id);
                    return (
                      <label key={u.id} className={`acg-combo-row ${on ? 'on' : ''}`}>
                        <input type="checkbox" checked={on} onChange={() => toggle(u.id)} />
                        <span className="acg-cb-mark">{on && <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>}</span>
                        <div className="acg-combo-row-meta">
                          <span className="acg-combo-row-name">{u.name}</span>
                          <span className="acg-combo-row-sub">{u.email}</span>
                        </div>
                      </label>
                    );
                  })}
                </div>
              </div>
            )}
          </div>
        </div>

        {/* RIGHT — Selected users panel */}
        <div className="acg-share-right">
          <div className="acg-share-right-head">
            <span className="acg-share-label">Selected Users</span>
            <button
              type="button"
              className="acg-unselect"
              onClick={() => onChange('shared', selected.length > 0 ? [] : ACG_SHARE_USERS.map(u => u.id))}
            >
              <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
              {selected.length > 0 ? 'Unselect All' : 'Select All'}
            </button>
          </div>

          {selected.length === 0 ? (
            <div className="acg-share-right-empty">No users selected yet.</div>
          ) : (
            <div className="acg-share-right-list">
              {selected.map((u) => (
                <div key={u.id} className="acg-share-right-item">
                  <div className="acg-share-right-meta">
                    <strong>{u.name}</strong>
                    <span>{u.email}</span>
                  </div>
                  <button type="button" className="acg-share-right-x" onClick={() => toggle(u.id)}>
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
                  </button>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

// ===== Step 4 — Review =====
const ACGStep4 = ({ data, onChange, t = {} }) => {
  const SharedChips = window.CgSharedChips;
  const sharedUsers = ACG_SHARE_USERS.filter(u => data.shared.includes(u.id));
  const visibleCols = data.columns.map((c, i) => ({ ...c, _i: i })).filter(c => !c.hidden);
  const fmtSize = (b) => b > 1024 * 1024 ? (b / 1024 / 1024).toFixed(1) + ' MB' : (b / 1024).toFixed(1) + ' KB';
  const [pPage, setPPage] = useStateACG(1);
  const [pPageSize, setPPageSize] = useStateACG(10);

  return (
    <div className="ac-step-pane">
      <div className="acg-r4">
        <div className="acg-r4-grid">
          <div className="acg-r4-field acg-r4-pos-name">
            <label>Contact Group Name</label>
            <div className="val">{data.name || '—'}</div>
          </div>
          <div className="acg-r4-field acg-r4-pos-ref">
            <label>Reference ID</label>
            <div className="val">{data.referenceId || '—'}</div>
          </div>
          <div className="acg-r4-field acg-r4-pos-file">
            <label>Original Contact file</label>
            {data.file ? (
              <div className="acg-r4-file">
                <span className="acg-r4-file-icon">
                  <svg width="34" height="34" viewBox="0 0 24 24" fill="none">
                    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" fill="#0f9d58" stroke="#0f9d58" strokeLinejoin="round"/>
                    <path d="M14 2v6h6" fill="#5fbb86" stroke="white" strokeWidth="0.5"/>
                    <rect x="7" y="11" width="10" height="8" fill="white"/>
                    <path d="M7 13h10M7 15h10M7 17h10M10 11v8M14 11v8" stroke="#0f9d58" strokeWidth="0.7"/>
                  </svg>
                </span>
                <div className="acg-r4-file-meta">
                  <strong>{data.file.name.length > 32 ? data.file.name.slice(0, 30) + '...' : data.file.name}</strong>
                  <span>{fmtSize(data.file.size)}</span>
                </div>
              </div>
            ) : <div className="val">—</div>}
          </div>
          <div className="acg-r4-field acg-r4-pos-num">
            <label>Number of uploaded contact</label>
            <div className="val">{data.rows.length || '—'}</div>
          </div>
          <div className="acg-r4-field acg-r4-shared-cell acg-r4-pos-shared">
            <label>Shared with</label>
            {sharedUsers.length === 0 ? (
              <div className="val">—</div>
            ) : SharedChips ? (
              <SharedChips list={sharedUsers.map(u => u.name)} max={3} t={t} />
            ) : (
              <div className="acg-r4-shared">
                {sharedUsers.slice(0, 3).map(u => (
                  <span key={u.id} className="acg-r4-share-chip">{u.name}</span>
                ))}
                {sharedUsers.length > 3 && <span className="acg-r4-share-chip more">+{sharedUsers.length - 3} more</span>}
              </div>
            )}
          </div>
        </div>

        <div className="acg-r4-preview-head">
          <span className="acg-cols-title">Data Preview</span>
        </div>
        <div className="acg-preview-panel">
          <div className="acg-preview-wrap">
            <table className="acg-preview-tbl r4">
              <thead>
                <tr>
                  <th className="num">#</th>
                  {visibleCols.map((c) => (
                    <th key={c._i} className="r4-h">{c.name}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {data.rows.slice((pPage - 1) * pPageSize, pPage * pPageSize).map((r, ri) => {
                  const rowNo = (pPage - 1) * pPageSize + ri + 1;
                  return (
                    <tr key={rowNo}>
                      <td className="num">{rowNo}</td>
                      {visibleCols.map((c) => (
                        <td key={c._i}>{r[c._i] != null ? r[c._i] : '—'}</td>
                      ))}
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          {window.TablePagination && (
            <window.TablePagination
              total={data.rows.length}
              page={pPage}
              pageSize={pPageSize}
              onPageChange={setPPage}
              onPageSizeChange={(n) => { setPPageSize(n); setPPage(1); }}
              t={t}
            />
          )}
        </div>
      </div>
    </div>
  );
};

// ===== Main flow =====
const AddContactGroupFlow = ({ onClose, t, pushToast, scopeNode, scopedTree, selected, selectNode, expanded, toggleExpand, initial }) => {
  const editing = !!initial;
  const [step, setStep] = useStateACG(0);
  const [direction, setDirection] = useStateACG(1);
  const [errors, setErrors] = useStateACG({});
  const [form, setForm] = useStateACG({
    name: initial?.name || '',
    referenceId: initial?.referenceId || '',
    file: initial ? { name: initial.fileName || `${initial.name}.csv`, size: 24 * 1024 } : null,
    columns: initial ? ACG_SAMPLE_HEADERS.map((h) => ({ name: h, hidden: false, disabledRules: /\s/.test(h) ? ['alnum', 'symbols'] : [] })) : [],
    rows: initial ? ACG_SAMPLE_ROWS : [],
    firstRowHeader: true,
    shared: initial ? [] : [],
  });
  const update = (k, v) => {
    setForm(f => ({ ...f, [k]: v }));
    if (errors[k]) setErrors(e => ({ ...e, [k]: undefined }));
  };

  const validateStep = (s) => {
    const errs = {};
    if (s === 0) {
      if (!form.name.trim()) errs.name = '*Required';
      else if (form.name.trim().length > 30) errs.name = 'Max 30 characters';
      if (!form.file) errs.file = 'Please upload a file';
    }
    if (s === 1) {
      const anyInvalid = form.columns.some((c, i) => !c.hidden && acgEvalCol(c, form.columns, i).failed.length > 0);
      if (anyInvalid) errs.columns = 'Fix invalid columns';
    }
    setErrors(errs);
    return Object.keys(errs).length === 0;
  };

  const isLast = step === ACG_STEPS.length - 1;

  // Live step-validity (used to disable Next / Create without committing errors)
  const stepIsValid = (s) => {
    if (s === 0) {
      if (!form.name.trim() || form.name.trim().length > 30) return false;
      if (!form.file) return false;
      return true;
    }
    if (s === 1) {
      return !form.columns.some((c, i) => !c.hidden && acgEvalCol(c, form.columns, i).failed.length > 0);
    }
    return true;
  };
  const nextDisabled = !stepIsValid(step);

  const handleNext = () => {
    if (!validateStep(step)) return;
    if (isLast) {
      pushToast(editing ? 'Contact group updated ✓' : 'Contact group created ✓');
      onClose();
      return;
    }
    setDirection(1);
    setStep(s => s + 1);
  };
  const handlePrev = () => { if (step > 0) { setDirection(-1); setStep(s => s - 1); } };

  return (
    <div className="ac-page acg-page">
      {/* Top bar — same chrome as Add New Contract */}
      <div className="ac-topbar">
        <div className="ac-topbar-brand cw-topbar-brand">
          {window.CgScopeLogo
            ? <window.CgScopeLogo node={scopeNode} size={32} />
            : <BrandLogo brand={scopeNode?.brand} 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={onClose}>Cancel</button>
          <button className="btn btn-secondary" type="button" onClick={handlePrev} disabled={step === 0}>Previous</button>
          <button
            className="btn btn-primary"
            type="button"
            onClick={handleNext}
            disabled={nextDisabled}
          >
            {isLast ? (editing ? 'Save Changes' : 'Create') : 'Next'}
          </button>
        </div>
      </div>

      {/* Body */}
      <div className="ac-body">
        <div className="ac-card">
          <div className="ac-card-head">
            <div className="ac-card-title">{editing ? 'Edit Contact Group' : 'New Contact Group'}</div>
            <div className="ac-step-counter">step <strong>{step + 1}/{ACG_STEPS.length}</strong></div>
          </div>

          <ACGStepBar current={step} onJump={(i) => { setDirection(i > step ? 1 : -1); setStep(i); }} />

          <div className="ac-card-body">
            <div key={step} className={`ac-anim-pane ${direction > 0 ? 'in-right' : 'in-left'}`}>
              {step === 0 && <ACGStep1 data={form} onChange={update} errors={errors} />}
              {step === 1 && <ACGStep2 data={form} onChange={update} t={t} />}
              {step === 2 && <ACGStep3 data={form} onChange={update} />}
              {step === 3 && <ACGStep4 data={form} onChange={update} t={t} />}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

window.AddContactGroupFlow = AddContactGroupFlow;
