/* =====================================================================
   AI-COS Essential — Users & Settings (Admin)
   Named-user management against /api/cal-auth. Plan allows 4 active users.
   ===================================================================== */
const CAL_MAX_USERS = 4;

function UsersModule() {
  // Access gate — Users & Settings (incl. email/SMTP credentials) is Admin-only.
  const isAdmin = window.CAL && CAL.user && (CAL.user.role === 'Admin' || CAL.user.role === 'Super Admin');
  if (!isAdmin) return (
    <div className="page rise">
      <div className="card card-pad" style={{ textAlign: 'center', padding: 44 }}>
        <Icon name="lock" size={30} style={{ color: 'var(--text-3)' }} />
        <div style={{ fontWeight: 750, fontSize: 15, marginTop: 10 }}>Administrator access only</div>
        <div className="faint" style={{ fontSize: 12.5, marginTop: 4 }}>Users &amp; Settings is available to Admin and Super Admin roles.</div>
      </div>
    </div>
  );
  return <UsersAdmin />;
}

function UsersAdmin() {
  const [users, setUsers] = useState(null);
  const [error, setError] = useState(null);
  const [modal, setModal] = useState(null); // {mode:'create'} | {mode:'edit', user} | {mode:'reset', user}

  const load = () => {
    calAuth({ action: 'list' }).then((r) => setUsers(r.users)).catch((e) => setError(e.message));
  };
  useEffect(() => { load(); }, []);

  const mySuper = window.CAL && CAL.user && CAL.user.role === 'Super Admin';
  const activeCount = (users || []).filter((u) => u.active && u.role !== 'Super Admin').length;
  const superCount = (users || []).filter((u) => u.role === 'Super Admin').length;

  return (
    <div className="page rise">
      <div className="row" style={{ justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 18 }}>
        <div>
          <div className="h-page">Users &amp; Settings</div>
          <div className="h-sub">{DB.company.name} · {activeCount}/{CAL_MAX_USERS} customer seats in use{superCount ? ` · ${superCount} Super Admin (vendor, not counted)` : ''}</div>
        </div>
        <Btn variant="primary" icon="plus" onClick={() => setModal({ mode: 'create' })}
          style={!mySuper && activeCount >= CAL_MAX_USERS ? { opacity: .5, pointerEvents: 'none' } : null}>Add user</Btn>
      </div>

      {error && (
        <div className="card card-pad" style={{ marginBottom: 14, borderColor: 'var(--bad-line)', background: 'var(--bad-bg)' }}>
          <span style={{ fontSize: 13, color: 'var(--bad)' }}>{error}</span>
        </div>
      )}

      <div className="card">
        <div className="card-head"><Icon name="users" size={16} style={{ color: 'var(--primary-600)' }} /><div className="h-sec">Named users</div>
          <span className="spacer" /><span className="faint" style={{ fontSize: 11.5 }}>plan: up to {CAL_MAX_USERS} active users</span></div>
        <table className="tbl">
          <thead><tr><th>User</th><th>Email</th><th>Role</th><th>Status</th><th>Created</th><th style={{ width: 200 }}></th></tr></thead>
          <tbody>
            {(users || []).map((u) => {
              const initials = u.name.split(/\s+/).map((w) => w[0]).slice(0, 2).join('').toUpperCase();
              const me = window.CAL && CAL.user && CAL.user.id === u.id;
              const superRow = u.role === 'Super Admin';
              const canManage = !superRow || mySuper;
              return (
                <tr key={u.id}>
                  <td><div className="row" style={{ gap: 8 }}>
                    <span className="avatar avatar-sm" style={{ background: superRow ? 'var(--ai, #7a5bff)' : u.active ? 'var(--primary-600)' : '#94a3b8' }}>{initials}</span>
                    <span style={{ fontSize: 13, fontWeight: 650 }}>{u.name}{me && <span className="faint" style={{ fontWeight: 400 }}> (you)</span>}</span>
                  </div></td>
                  <td className="faint" style={{ fontSize: 12.5 }}>{u.email}</td>
                  <td><Badge kind={superRow ? 'ai' : u.role === 'Admin' ? 'info' : 'neutral'}>{u.role}</Badge></td>
                  <td><Badge kind={u.active ? 'ok' : 'neutral'} dot={u.active}>{u.active ? 'Active' : 'Deactivated'}</Badge></td>
                  <td className="faint" style={{ fontSize: 12 }}>{u.created_at ? new Date(u.created_at).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) : '—'}</td>
                  <td>
                    {canManage ? (
                      <div className="row" style={{ gap: 6, justifyContent: 'flex-end' }}>
                        <Btn size="sm" variant="ghost" onClick={() => setModal({ mode: 'edit', user: u })}>Edit</Btn>
                        <Btn size="sm" variant="ghost" onClick={() => setModal({ mode: 'reset', user: u })}>Reset password</Btn>
                        {!me && (
                          <Btn size="sm" variant="ghost" style={{ color: u.active ? 'var(--bad)' : 'var(--ok)' }}
                            onClick={async () => {
                              try { await calAuth({ action: 'update', id: u.id, active: !u.active }); window.toast(u.active ? u.name + ' deactivated' : u.name + ' reactivated', 'ok'); load(); }
                              catch (e) { window.toast(e.message, 'bad'); }
                            }}>{u.active ? 'Deactivate' : 'Reactivate'}</Btn>
                        )}
                        {!me && (
                          <Btn size="sm" variant="ghost" style={{ color: 'var(--bad)' }}
                            onClick={async () => {
                              if (!window.confirm('Delete ' + u.name + ' (' + u.email + ')? This permanently removes the account.')) return;
                              try { await calAuth({ action: 'delete', id: u.id }); window.toast(u.name + ' deleted', 'ok'); load(); }
                              catch (e) { window.toast(e.message, 'bad'); }
                            }}>Delete</Btn>
                        )}
                      </div>
                    ) : (
                      <div className="row" style={{ gap: 5, justifyContent: 'flex-end', color: 'var(--text-3)', fontSize: 11.5 }}>
                        <Icon name="lock" size={12} /> Vendor account
                      </div>
                    )}
                  </td>
                </tr>
              );
            })}
            {users && users.length === 0 && (
              <tr><td colSpan={6} className="faint" style={{ textAlign: 'center', padding: 22 }}>No users yet.</td></tr>
            )}
          </tbody>
        </table>
      </div>

      <EmailSettingsCard />

      <div className="card" style={{ marginTop: 14 }}>
        <div className="card-head"><Icon name="bell" size={16} style={{ color: 'var(--primary-600)' }} /><div className="h-sec">Reminder template &amp; timing</div><span className="spacer" /><span className="faint" style={{ fontSize: 11.5 }}>used by Email Reminders</span></div>
        <div className="card-body">
          <ReminderSettings settings={window.DB.reminderSettings || { windows: [30, 15, 7], includeOverdue: true, template: { subject: '', body: '' } }} />
        </div>
      </div>

      <ChecklistsCard />

      <SettingsListsCard />

      <div className="card card-pad" style={{ marginTop: 14 }}>
        <div className="eyebrow" style={{ marginBottom: 8 }}>Plan</div>
        <div className="row" style={{ gap: 26, flexWrap: 'wrap' }}>
          {[['Product', 'AI-COS Essential'], ['Licence', 'Annual subscription'], ['Named users', `${activeCount} of ${CAL_MAX_USERS} active (Super Admins excluded)`], ['Modules', 'Calibration · Assets · Certificates · NCR/CAPA · Documents · Reminders · Reporting']].map(([k, v]) => (
            <div key={k}><div className="eyebrow" style={{ fontSize: 9 }}>{k}</div><div style={{ fontSize: 13, fontWeight: 650, marginTop: 3 }}>{v}</div></div>
          ))}
        </div>
      </div>

      {modal && <UserModal cfg={modal} onClose={() => setModal(null)} onDone={() => { setModal(null); load(); }} />}
    </div>
  );
}

function UserModal({ cfg, onClose, onDone }) {
  const editing = cfg.mode === 'edit', reset = cfg.mode === 'reset';
  const [name, setName] = useState(editing ? cfg.user.name : '');
  const [email, setEmail] = useState(editing ? cfg.user.email : '');
  const [role, setRole] = useState(editing ? cfg.user.role : 'Technician');
  const [password, setPassword] = useState('');
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState(null);

  const submit = async () => {
    setError(null); setBusy(true);
    try {
      if (cfg.mode === 'create') await calAuth({ action: 'create', name, email, role, password });
      else if (reset) await calAuth({ action: 'update', id: cfg.user.id, password });
      else await calAuth({ action: 'update', id: cfg.user.id, name, role });
      window.toast(cfg.mode === 'create' ? 'User created' : reset ? 'Password reset' : 'User updated', 'ok');
      onDone();
    } catch (e) { setError(e.message); } finally { setBusy(false); }
  };

  const F = ({ label, children }) => (
    <div style={{ marginBottom: 12 }}>
      <label className="eyebrow" style={{ fontSize: 10.5 }}>{label}</label>
      <div style={{ marginTop: 5 }}>{children}</div>
    </div>
  );
  const inp = { width: '100%', fontFamily: 'inherit', fontSize: 13.5, padding: '10px 12px', borderRadius: 10, border: '1.5px solid var(--border-2)', outline: 'none', boxSizing: 'border-box', background: 'var(--surface)' };

  return (
    <React.Fragment>
      <div className="scrim" onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(11,26,46,.42)', zIndex: 90 }} />
      <div className="modal" style={{ position: 'fixed', zIndex: 100, top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: 430, maxWidth: '94vw', background: 'var(--surface)', borderRadius: 16, boxShadow: 'var(--sh-lg)', padding: 24 }}>
        <div className="row" style={{ marginBottom: 16 }}>
          <div style={{ fontWeight: 750, fontSize: 16, flex: 1 }}>
            {cfg.mode === 'create' ? 'Add user' : reset ? 'Reset password — ' + cfg.user.name : 'Edit user'}
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={16} /></button>
        </div>
        {error && <div style={{ background: 'var(--bad-bg)', border: '1px solid var(--bad-line)', color: 'var(--bad)', borderRadius: 10, padding: '9px 12px', fontSize: 12.5, marginBottom: 12 }}>{error}</div>}
        {!reset && <F label="Full name"><input style={inp} value={name} onChange={(e) => setName(e.target.value)} /></F>}
        {cfg.mode === 'create' && <F label="Email"><input style={inp} type="email" value={email} onChange={(e) => setEmail(e.target.value)} /></F>}
        {!reset && (
          <F label="Role">
            <select style={inp} value={role} onChange={(e) => setRole(e.target.value)}>
              <option>Admin</option><option>Technician</option><option>Quality</option>
              {window.CAL && CAL.user && CAL.user.role === 'Super Admin' && <option>Super Admin</option>}
            </select>
          </F>
        )}
        {(cfg.mode === 'create' || reset) && <F label={reset ? 'New password' : 'Initial password'}><input style={inp} type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Minimum 8 characters" /></F>}
        <div className="row" style={{ gap: 10, marginTop: 18 }}>
          <Btn variant="ghost" style={{ flex: 1 }} onClick={onClose}>Cancel</Btn>
          <Btn variant="primary" style={{ flex: 2, opacity: busy ? .7 : 1 }} icon="check" onClick={busy ? undefined : submit}>
            {busy ? 'Saving…' : cfg.mode === 'create' ? 'Create user' : reset ? 'Reset password' : 'Save changes'}
          </Btn>
        </div>
      </div>
    </React.Fragment>
  );
}

/* ---- Dropdown option lists — every select in the product reads these ---- */
const SETTING_LISTS = [
  ['models', 'Instrument models', 'Asset register — make / model options'],
  ['manufacturers', 'Manufacturers', 'Asset register & dashboard manufacturer chart'],
  ['gasTypes', 'Gas types', 'Sensor configuration on assets'],
  ['jobTypes', 'Job types', 'New calibration job'],
  ['priorities', 'Job priorities', 'New calibration job'],
  ['intervals', 'Calibration intervals (months)', 'Asset calibration schedule'],
  ['suppliers', 'Gas suppliers', 'Gas cylinder register'],
  ['sectors', 'Customer sectors', 'Customer form'],
  ['agreements', 'Agreement types', 'Customer form'],
  ['ncrSources', 'NCR sources', 'Raise NCR form'],
  ['docTypes', 'Document types', 'Document control'],
  ['docLevels', 'Document levels', 'Document control'],
  ['assetHealth', 'Asset health states', 'Asset register & dashboard asset-health chart'],
  ['equipmentTypes', 'Equipment types', 'Asset register & inspection checklists'],
];

/* ---- Inspection / calibration checklists per equipment type ---- */
function ChecklistsCard() {
  const [, force] = useState(0);
  const lists = window.DB.checklists || [];
  const editForm = (rec) => {
    const e = rec || {};
    window.openForm({
      title: rec ? 'Edit checklist — ' + e.name : 'New inspection checklist', icon: 'clipboard',
      sub: 'Functional checks a technician performs at calibration for this equipment type. One item per line.',
      submitLabel: rec ? 'Save checklist' : 'Create checklist', done: rec ? 'Checklist updated' : 'Checklist created',
      fields: [
        { key: 'name', label: 'Checklist name', type: 'text', full: true, value: e.name, placeholder: 'e.g. Portable multi-gas — functional checks' },
        { key: 'type', label: 'Equipment type', type: 'select', options: window.calOpt('equipmentTypes').concat('Any'), value: e.type || window.calOpt('equipmentTypes')[0] },
        { key: 'items', label: 'Check items (one per line)', type: 'textarea', full: true, rows: 8, value: (e.items || []).join('\n'), placeholder: 'Visual Inspection\nDisplay / LCD\nAudible Alarm\nVibration Alarm\nBattery Condition' },
      ],
      onSave: (v) => {
        const items = String(v.items || '').split('\n').map((s) => s.trim()).filter(Boolean);
        if (!v.name || !v.name.trim()) { window.toast('Give the checklist a name.', 'warn'); return; }
        if (!items.length) { window.toast('Add at least one check item.', 'warn'); return; }
        if (rec) window.dbUpdate('checklists', 'id', e.id, { name: v.name.trim(), type: v.type, items });
        else window.dbAdd('checklists', { id: 'CL-' + Date.now().toString(36), name: v.name.trim(), type: v.type, items });
        force((x) => x + 1);
      },
    });
  };
  return (
    <div className="card" style={{ marginTop: 14 }}>
      <div className="card-head">
        <Icon name="clipboard" size={16} style={{ color: 'var(--primary-600)' }} />
        <div className="h-sec">Inspection &amp; calibration checklists</div>
        <span className="spacer" />
        <Btn size="sm" variant="primary" icon="plus" onClick={() => editForm()}>New checklist</Btn>
      </div>
      <div className="card-body">
        <div className="faint" style={{ fontSize: 11.5, marginBottom: 12 }}>Define the functional checks per equipment type. When a technician records a calibration worksheet, the checklist matching the instrument's equipment type is applied automatically. Without a match, the standard checks are used.</div>
        {lists.length === 0 ? (
          <div className="faint" style={{ fontSize: 12.5, padding: '4px 0' }}>No custom checklists yet — every instrument uses the standard functional checks (Visual, Display/LCD, Audible &amp; Vibration alarm, Battery). Add a checklist to tailor the checks for an equipment type.</div>
        ) : lists.map((cl) => (
          <div key={cl.id} className="row" style={{ gap: 10, padding: '9px 0', borderBottom: '1px solid var(--border)', alignItems: 'flex-start' }}>
            <span className="kpi-ico" style={{ width: 30, height: 30, background: 'var(--bg)', color: 'var(--primary-600)', flex: 'none' }}><Icon name="clipboard" size={15} /></span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div className="row" style={{ gap: 6 }}><span style={{ fontSize: 12.5, fontWeight: 650 }}>{cl.name}</span><Badge kind="info">{cl.type || 'Any'}</Badge></div>
              <div className="faint" style={{ fontSize: 11, marginTop: 2 }}>{(cl.items || []).length} check{(cl.items || []).length === 1 ? '' : 's'}: {(cl.items || []).slice(0, 5).join(', ')}{(cl.items || []).length > 5 ? '…' : ''}</div>
            </div>
            <Btn size="sm" variant="ghost" onClick={() => editForm(cl)}>Edit</Btn>
            <Btn size="sm" variant="ghost" style={{ color: 'var(--bad)' }} onClick={() => { if (window.confirm('Delete checklist "' + cl.name + '"?')) { window.dbRemove('checklists', 'id', cl.id); force((x) => x + 1); } }}>Delete</Btn>
          </div>
        ))}
      </div>
    </div>
  );
}

function SettingsListsCard() {
  const [, force] = useState(0);
  const edit = (key, label) => {
    window.openForm({
      title: 'Edit list — ' + label, icon: 'settings',
      sub: 'One option per line. These options appear in the forms across the product.',
      submitLabel: 'Save list', done: label + ' updated',
      fields: [{ key: 'items', label: 'Options', type: 'textarea', full: true, rows: 10, value: window.calOpt(key).join('\n') }],
      onSave: (v) => {
        const items = String(v.items || '').split('\n').map((s) => s.trim()).filter(Boolean);
        if (!items.length) { window.toast('The list needs at least one option', 'bad'); return; }
        const next = Object.assign({}, window.CAL_DEFAULT_SETTINGS, window.DB.settings, { [key]: items });
        dbSet('settings', next);
        force((x) => x + 1);
      },
    });
  };
  return (
    <div className="card" style={{ marginTop: 14 }}>
      <div className="card-head">
        <Icon name="settings" size={16} style={{ color: 'var(--primary-600)' }} />
        <div className="h-sec">Dropdown options</div>
        <span className="spacer" />
        <span className="faint" style={{ fontSize: 11.5 }}>every selection list in the product is managed here</span>
      </div>
      <div className="card-body settings-2col" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 22px' }}>
        {SETTING_LISTS.map(([key, label, where]) => {
          const items = window.calOpt(key);
          return (
            <div key={key} className="row" style={{ gap: 10, alignItems: 'flex-start', padding: '8px 0', borderBottom: '1px solid var(--border)' }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 12.5, fontWeight: 650 }}>{label} <span className="faint" style={{ fontWeight: 400 }}>· {items.length}</span></div>
                <div className="faint" style={{ fontSize: 11, marginTop: 2 }}>{where}</div>
                <div className="row wrap" style={{ gap: 4, marginTop: 6 }}>
                  {items.slice(0, 6).map((x) => <span key={x} className="tag" style={{ padding: '1px 7px', fontSize: 10.5 }}>{x}</span>)}
                  {items.length > 6 && <span className="faint" style={{ fontSize: 10.5 }}>+{items.length - 6} more</span>}
                </div>
              </div>
              <Btn size="sm" variant="ghost" onClick={() => edit(key, label)}>Edit</Btn>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ---- Email / SMTP delivery — credentials stay server-side (write-only) ---- */
function EmailSettingsCard() {
  const [cfg, setCfg] = useState(null);       // loaded config (no secret, has hasSecret)
  const [secret, setSecret] = useState('');   // new secret to send (blank = keep existing)
  const [touchSecret, setTouchSecret] = useState(false);
  const [busy, setBusy] = useState(false);
  const [testing, setTesting] = useState(false);
  const [msg, setMsg] = useState(null);       // { kind, text }

  const load = () => calSettings({ action: 'get' }).then((r) => setCfg(r.email)).catch((e) => setMsg({ kind: 'bad', text: e.message }));
  useEffect(() => { load(); }, []);

  const set = (k, v) => setCfg((c) => Object.assign({}, c, { [k]: v }));
  const inp = { width: '100%', fontFamily: 'inherit', fontSize: 13, padding: '9px 11px', borderRadius: 9, border: '1.5px solid var(--border-2)', outline: 'none', boxSizing: 'border-box', background: 'var(--surface)' };
  const lab = { fontSize: 10.5 };

  const save = async () => {
    setBusy(true); setMsg(null);
    try {
      const payload = { action: 'save', email: cfg };
      if (touchSecret) payload.secret = secret;            // only send when the admin edited it
      const r = await calSettings(payload);
      setCfg(r.email); setSecret(''); setTouchSecret(false);
      setMsg({ kind: 'ok', text: 'Email settings saved.' });
      window.toast('Email settings saved', 'ok');
    } catch (e) { setMsg({ kind: 'bad', text: e.message }); } finally { setBusy(false); }
  };

  const sendTest = async () => {
    const to = window.prompt('Send a test email to:', (CAL.user && CAL.user.email) || '');
    if (!to) return;
    setTesting(true); setMsg(null);
    try {
      const r = await calSettings({ action: 'test', to });
      if (r.status === 'Sent') setMsg({ kind: 'ok', text: 'Test email sent to ' + to + '.' });
      else if (r.status === 'Queued') setMsg({ kind: 'warn', text: 'No provider configured yet — save your SMTP or Resend details first.' });
      else setMsg({ kind: 'bad', text: 'Test failed: ' + (r.detail || 'unknown error') });
    } catch (e) { setMsg({ kind: 'bad', text: e.message }); } finally { setTesting(false); }
  };

  if (!cfg) return (
    <div className="card card-pad" style={{ marginTop: 14 }}><div className="faint" style={{ fontSize: 12.5 }}>Loading email settings…</div></div>
  );
  const smtp = cfg.provider !== 'resend';

  return (
    <div className="card" style={{ marginTop: 14 }}>
      <div className="card-head">
        <Icon name="bell" size={16} style={{ color: 'var(--primary-600)' }} />
        <div className="h-sec">Email delivery (SMTP)</div>
        <span className="spacer" />
        {cfg.hasSecret ? <Badge kind="ok" dot>Credentials stored</Badge> : <Badge kind="warn">Not configured</Badge>}
      </div>
      <div className="card-body">
        <div className="faint" style={{ fontSize: 11.5, marginBottom: 14 }}>
          Reminders and customer notifications are sent through this provider. The password / API key is stored
          securely on the server and is never displayed again.
        </div>
        {msg && <div style={{ background: 'var(--' + msg.kind + '-bg)', border: '1px solid var(--' + msg.kind + '-line)', color: 'var(--' + msg.kind + ')', borderRadius: 9, padding: '8px 11px', fontSize: 12.5, marginBottom: 12 }}>{msg.text}</div>}

        <div style={{ marginBottom: 12 }}>
          <label className="eyebrow" style={lab}>Provider</label>
          <select style={{ ...inp, marginTop: 5, maxWidth: 260 }} value={cfg.provider} onChange={(e) => set('provider', e.target.value)}>
            <option value="smtp">SMTP server</option>
            <option value="resend">Resend API</option>
          </select>
        </div>

        {smtp ? (
          <div className="settings-2col" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 16px' }}>
            <div><label className="eyebrow" style={lab}>SMTP host</label><input style={{ ...inp, marginTop: 5 }} value={cfg.host} onChange={(e) => set('host', e.target.value)} placeholder="smtp.office365.com" /></div>
            <div><label className="eyebrow" style={lab}>Port</label><input style={{ ...inp, marginTop: 5 }} type="number" value={cfg.port} onChange={(e) => set('port', e.target.value)} placeholder="587" /></div>
            <div><label className="eyebrow" style={lab}>Username</label><input style={{ ...inp, marginTop: 5 }} value={cfg.user} onChange={(e) => set('user', e.target.value)} placeholder="calibration@company.com" /></div>
            <div><label className="eyebrow" style={lab}>Password</label><input style={{ ...inp, marginTop: 5 }} type="password" value={touchSecret ? secret : ''} onChange={(e) => { setSecret(e.target.value); setTouchSecret(true); }} placeholder={cfg.hasSecret ? '•••••••• (unchanged)' : 'SMTP password'} /></div>
            <label className="row" style={{ gap: 8, fontSize: 12.5, cursor: 'pointer', gridColumn: '1 / -1' }}>
              <input type="checkbox" checked={!!cfg.secure} onChange={(e) => set('secure', e.target.checked)} />
              Use SSL/TLS (port 465). Leave off for STARTTLS (587).
            </label>
          </div>
        ) : (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 10, maxWidth: 420 }}>
            <div><label className="eyebrow" style={lab}>Resend API key</label><input style={{ ...inp, marginTop: 5 }} type="password" value={touchSecret ? secret : ''} onChange={(e) => { setSecret(e.target.value); setTouchSecret(true); }} placeholder={cfg.hasSecret ? '•••••••• (unchanged)' : 're_...'} /></div>
          </div>
        )}

        <div className="settings-2col" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 16px', marginTop: 12 }}>
          <div><label className="eyebrow" style={lab}>From name</label><input style={{ ...inp, marginTop: 5 }} value={cfg.fromName} onChange={(e) => set('fromName', e.target.value)} placeholder="ADAM Calibration Lab" /></div>
          <div><label className="eyebrow" style={lab}>From email</label><input style={{ ...inp, marginTop: 5 }} type="email" value={cfg.from} onChange={(e) => set('from', e.target.value)} placeholder="calibration@company.com" /></div>
          <div><label className="eyebrow" style={lab}>Reply-to (optional)</label><input style={{ ...inp, marginTop: 5 }} type="email" value={cfg.replyTo} onChange={(e) => set('replyTo', e.target.value)} placeholder="lab@company.com" /></div>
        </div>

        <div className="row" style={{ gap: 8, marginTop: 16 }}>
          <Btn variant="ghost" icon="bell" onClick={testing ? undefined : sendTest} style={testing ? { opacity: .6 } : null}>{testing ? 'Sending…' : 'Send test email'}</Btn>
          <span className="spacer" />
          <Btn variant="primary" icon="check" onClick={busy ? undefined : save} style={busy ? { opacity: .7 } : null}>{busy ? 'Saving…' : 'Save email settings'}</Btn>
        </div>
      </div>
    </div>
  );
}

/* Self-service password change — opened from the profile menu */
function ChangePasswordHost() {
  const [open, setOpen] = useState(false);
  const [current, setCurrent] = useState('');
  const [password, setPassword] = useState('');
  const [confirm, setConfirm] = useState('');
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState(null);
  useEffect(() => { window.openChangePassword = () => { setCurrent(''); setPassword(''); setConfirm(''); setError(null); setOpen(true); }; return () => { window.openChangePassword = null; }; }, []);
  if (!open) return null;
  const inp = { width: '100%', fontFamily: 'inherit', fontSize: 13.5, padding: '10px 12px', borderRadius: 10, border: '1.5px solid var(--border-2)', outline: 'none', boxSizing: 'border-box', background: 'var(--surface)' };
  const submit = async () => {
    setError(null);
    if (password.length < 8) return setError('New password must be at least 8 characters.');
    if (password !== confirm) return setError('Passwords do not match.');
    setBusy(true);
    try { await calAuth({ action: 'password', current, password }); window.toast('Password changed', 'ok'); setOpen(false); }
    catch (e) { setError(e.message); } finally { setBusy(false); }
  };
  return (
    <React.Fragment>
      <div onClick={() => setOpen(false)} style={{ position: 'fixed', inset: 0, background: 'rgba(11,26,46,.42)', zIndex: 90 }} />
      <div style={{ position: 'fixed', zIndex: 100, top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: 400, maxWidth: '94vw', background: 'var(--surface)', borderRadius: 16, boxShadow: 'var(--sh-lg)', padding: 24 }}>
        <div className="row" style={{ marginBottom: 14 }}>
          <div style={{ fontWeight: 750, fontSize: 16, flex: 1 }}>Change password</div>
          <button className="icon-btn" onClick={() => setOpen(false)}><Icon name="x" size={16} /></button>
        </div>
        {error && <div style={{ background: 'var(--bad-bg)', border: '1px solid var(--bad-line)', color: 'var(--bad)', borderRadius: 10, padding: '9px 12px', fontSize: 12.5, marginBottom: 12 }}>{error}</div>}
        {[['Current password', current, setCurrent], ['New password', password, setPassword], ['Confirm new password', confirm, setConfirm]].map(([label, val, set]) => (
          <div key={label} style={{ marginBottom: 12 }}>
            <label className="eyebrow" style={{ fontSize: 10.5 }}>{label}</label>
            <input style={{ ...inp, marginTop: 5 }} type="password" value={val} onChange={(e) => set(e.target.value)} />
          </div>
        ))}
        <div className="row" style={{ gap: 10, marginTop: 16 }}>
          <Btn variant="ghost" style={{ flex: 1 }} onClick={() => setOpen(false)}>Cancel</Btn>
          <Btn variant="primary" style={{ flex: 2, opacity: busy ? .7 : 1 }} icon="check" onClick={busy ? undefined : submit}>{busy ? 'Saving…' : 'Change password'}</Btn>
        </div>
      </div>
    </React.Fragment>
  );
}

Object.assign(window, { UsersModule, ChangePasswordHost });
