// Project R — Skills page components
// Three-column master-detail: Orgs | Employees | Skills, with right-side drawer for edit/create.

const { useState: useS, useMemo: useM, useRef: useR, useEffect: useE } = React;

/* ---------- Topbar ---------- */
function getInitials(name) {
  if (!name) return '??';
  return name.split(/\s+/).filter(Boolean).map(w => w[0]).slice(0, 2).join('').toUpperCase();
}

// Derives a friendly display name from the auth user. Prefers an explicit
// `name`, then falls back to the email's local part with separators turned
// into spaces and each word capitalized — `riya.banerjee@x.com` → `Riya Banerjee`.
function displayNameFromUser(u) {
  if (!u) return 'Signed in';
  if (u.name && String(u.name).trim()) return u.name.trim();
  const email = String(u.email || '');
  const local = email.split('@')[0] || '';
  if (!local) return 'Signed in';
  return local.split(/[._-]+/).filter(Boolean)
    .map(w => w[0].toUpperCase() + w.slice(1).toLowerCase())
    .join(' ');
}

function PRTopbar({ onLogout, user, onOpenOrgSettings }) {
  const [menuOpen, setMenuOpen] = useS(false);
  const [adminModalOpen, setAdminModalOpen] = useS(false);
  const [resetModalOpen, setResetModalOpen] = useS(false);
  const ref = useR(null);
  // Role gates: everyone can add people (with restricted role choices) and reset their own password;
  // only admin sees "Organization settings" (super_admin manages each org from the Orgs list).
  const role = (user && user.role) || 'user';
  const canAddPeople = true;
  // Both admin (manages own org) and super_admin (picks the org) can edit org settings.
  const canViewOrgSettings = role === 'admin' || role === 'super_admin';
  useE(() => {
    if (!menuOpen) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setMenuOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setMenuOpen(false); };
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onDoc); document.removeEventListener('keydown', onKey); };
  }, [menuOpen]);

  // Fall back to whatever's in localStorage if the prop wasn't passed.
  const currentUser = user || (() => {
    try { return JSON.parse(localStorage.getItem('pr.user') || 'null'); } catch { return null; }
  })() || { email: '' };
  const displayName = displayNameFromUser(currentUser);
  const initials = getInitials(displayName);
  const handleLogout = () => { setMenuOpen(false); if (onLogout) onLogout(); };
  const handleAddPeople = () => { setMenuOpen(false); setAdminModalOpen(true); };
  const handleResetPassword = () => { setMenuOpen(false); setResetModalOpen(true); };
  const handleOrgSettings = () => { setMenuOpen(false); onOpenOrgSettings && onOpenOrgSettings(); };

  return (
    <header style={{
      display: 'flex', alignItems: 'center', gap: 16, padding: '14px 24px',
      background: 'var(--c-cream-50)', borderBottom: '1px solid var(--border-subtle)',
    }}>
      <img src="../assets/creatium-logo.png" style={{ height: 26 }} alt="Creatium" />
      <div style={{
        height: 24, width: 1, background: 'var(--border-default)', margin: '0 8px',
      }} />
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
        <span style={{
          fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700, fontSize: 16,
          color: 'var(--c-ink-900)', letterSpacing: '-0.01em',
        }}>Project R</span>
        <span className="eyebrow" style={{ color: 'var(--c-ink-500)', background: 'var(--c-cream-100)', padding: '4px 8px', borderRadius: 6 }}>Skills admin</span>
      </div>
      <div style={{ flex: 1 }} />
      <span style={{
        fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 500, fontSize: 13,
        color: 'var(--c-ink-800)',
      }}>{displayName}</span>
      <div ref={ref} style={{ position: 'relative' }}>
        <button onClick={() => setMenuOpen(o => !o)} title={displayName}
          aria-haspopup="menu" aria-expanded={menuOpen}
          style={{
            width: 36, height: 36, borderRadius: '50%', flex: 'none', cursor: 'pointer',
            background: 'var(--c-petrol-800)', color: '#fff',
            border: '2px solid #fff', boxShadow: 'var(--shadow-raised-sm)',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: 0,
            fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12, letterSpacing: '0.04em',
          }}>{initials}</button>
        {menuOpen && (
          <div role="menu" style={{
            position: 'absolute', top: 'calc(100% + 8px)', right: 0, minWidth: 240,
            background: 'var(--c-cream-50)', border: '1px solid var(--border-subtle)',
            borderRadius: 12, boxShadow: 'var(--shadow-float-lg)', zIndex: 120,
            padding: 6, animation: 'pr-fade .15s ease-out',
          }}>
            <div style={{
              display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px 12px',
              borderBottom: '1px solid var(--border-subtle)',
            }}>
              <div style={{
                width: 36, height: 36, borderRadius: '50%', flex: 'none',
                background: 'var(--c-petrol-800)', color: '#fff',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12, letterSpacing: '0.04em',
              }}>{initials}</div>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 500, fontSize: 14,
                  color: 'var(--c-ink-900)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{displayName}</div>
                <div style={{ fontFamily: "'Inter', sans-serif", fontSize: 11, color: 'var(--c-ink-500)',
                  letterSpacing: '0.02em', marginTop: 2,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{currentUser.email}</div>
              </div>
            </div>
            {canAddPeople && (
              <button role="menuitem" onClick={handleAddPeople} style={menuItemStyle}>
                <img src="../assets/icons/plus.svg" width={12} height={12} alt="" />
                Add people
              </button>
            )}
            <button role="menuitem" onClick={handleResetPassword} style={menuItemStyle}>
              <img src="../assets/icons/settings.svg" width={12} height={12} alt="" />
              Reset password
            </button>
            {canViewOrgSettings && (
              <button role="menuitem" onClick={handleOrgSettings} style={menuItemStyle}>
                <img src="../assets/icons/library.svg" width={12} height={12} alt="" />
                Organization settings
              </button>
            )}
            <button role="menuitem" onClick={handleLogout} style={{ ...menuItemStyle, color: 'var(--c-terra-600, #C65A42)' }}>
              <img src="../assets/icons/cross.svg" width={11} height={11} alt=""
                style={{ filter: 'invert(34%) sepia(45%) saturate(1850%) hue-rotate(345deg) brightness(85%)' }} />
              Log out
            </button>
          </div>
        )}
      </div>
      {adminModalOpen && (
        <AddPeopleModal currentRole={role} onClose={() => setAdminModalOpen(false)} />
      )}
      {resetModalOpen && (
        <ResetPasswordModal onClose={() => setResetModalOpen(false)} />
      )}
    </header>
  );
}

function ResetPasswordModal({ onClose }) {
  const [current, setCurrent] = useS('');
  const [pw, setPw] = useS('');
  const [pw2, setPw2] = useS('');
  const [submitted, setSubmitted] = useS(false);
  const currentValid = current.length > 0;
  const pwValid = pw.length >= 8;
  const pwMatches = pw.length > 0 && pw === pw2;
  const distinct = pw.length === 0 || pw !== current;
  const valid = currentValid && pwValid && pwMatches && distinct;

  useE(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, []);

  const handleSubmit = () => {
    if (!valid) return;
    setSubmitted(true);
    setTimeout(onClose, 1400);
  };

  const inputStyle = {
    height: 44, padding: '0 14px', borderRadius: 12,
    background: 'var(--c-cream-50)',
    border: '1.5px solid var(--border-subtle)',
    boxShadow: 'var(--shadow-inset-input)',
    fontFamily: "'Suisse Int\\'l', sans-serif", fontSize: 14, color: 'var(--c-ink-900)',
    width: '100%', outline: 'none', boxSizing: 'border-box',
  };
  const labelStyle = { fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 500, fontSize: 13, color: 'var(--c-ink-900)' };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(23,53,64,0.32)',
      zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24, animation: 'pr-fade .15s ease-out',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width: 460, maxWidth: '100%', background: 'var(--c-cream-50)',
        border: '1px solid var(--border-subtle)', borderRadius: 16,
        boxShadow: 'var(--shadow-float-lg)', overflow: 'hidden',
        animation: 'pr-fade .18s ease-out',
      }}>
        <header style={{
          display: 'flex', alignItems: 'flex-start', gap: 12,
          padding: '20px 22px 16px', borderBottom: '1px solid var(--border-subtle)',
          background: 'var(--c-cream-100)',
        }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="eyebrow" style={{ color: 'var(--c-ink-500)', letterSpacing: '1.5px' }}>Account</div>
            <div style={{
              fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700, fontSize: 20,
              letterSpacing: '-0.02em', color: 'var(--c-ink-800)', marginTop: 4,
            }}>Reset password</div>
          </div>
          <button onClick={onClose} title="Close" style={{
            width: 32, height: 32, borderRadius: 10, border: '1px solid var(--border-subtle)',
            background: 'var(--c-white)', boxShadow: 'var(--shadow-raised-sm)', cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none',
          }}>
            <img src="../assets/icons/cross.svg" width={11} height={11} alt="Close" />
          </button>
        </header>

        <div style={{ padding: '20px 22px', display: 'flex', flexDirection: 'column', gap: 16 }}>
          <p style={{ margin: 0, fontSize: 13, lineHeight: 1.55, color: 'var(--c-ink-600)', textWrap: 'pretty' }}>
            Confirm your current password, then choose a new one. You will stay signed in.
          </p>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Current password</label>
            <input type="password" autoFocus value={current} onChange={e => setCurrent(e.target.value)}
              placeholder="Your current password" style={inputStyle} />
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>New password</label>
            <input type="password" value={pw} onChange={e => setPw(e.target.value)}
              placeholder="At least 8 characters" style={inputStyle} />
            {pw.length > 0 && !pwValid && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Use at least 8 characters.</span>
            )}
            {pw.length > 0 && pwValid && !distinct && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>New password must differ from the current one.</span>
            )}
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Confirm new password</label>
            <input type="password" value={pw2} onChange={e => setPw2(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter' && valid && !submitted) handleSubmit(); }}
              placeholder="Re-enter new password" style={inputStyle} />
            {pw2.length > 0 && !pwMatches && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Passwords do not match.</span>
            )}
          </div>
        </div>

        <footer style={{
          padding: '14px 22px', borderTop: '1px solid var(--border-subtle)',
          background: 'var(--c-cream-100)', display: 'flex', alignItems: 'center', gap: 10,
        }}>
          {submitted && (
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              color: 'var(--c-olive-600, #5A6A3A)', fontSize: 12, fontWeight: 500,
            }}>
              <img src="../assets/icons/success.svg" width={13} height={13} alt="" />
              Password updated
            </span>
          )}
          <div style={{ flex: 1 }} />
          <button onClick={onClose} style={{
            height: 40, padding: '0 16px', borderRadius: 10, border: '1.5px solid var(--c-petrol-800)',
            background: 'transparent', color: 'var(--c-petrol-800)',
            fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12, cursor: 'pointer',
          }}>Cancel</button>
          <button onClick={handleSubmit} disabled={!valid || submitted} style={{
            height: 40, padding: '0 18px', borderRadius: 10, border: 'none',
            background: (valid && !submitted) ? 'var(--c-petrol-800)' : 'var(--c-cream-100)',
            color: (valid && !submitted) ? '#fff' : 'var(--c-ink-300)',
            fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12,
            boxShadow: (valid && !submitted) ? 'var(--shadow-raised-sm)' : 'none',
            cursor: (valid && !submitted) ? 'pointer' : 'not-allowed',
          }}>Update password</button>
        </footer>
      </div>
    </div>
  );
}

function AddPeopleModal({ currentRole, onClose }) {
  // Restrict role choices by the current user's role.
  //   super_admin → super_admin | admin | user
  //   admin       → admin | user
  //   user        → user
  const ALL_ROLES = [
    { value: 'super_admin', label: 'Super admin', help: 'Sees every organization.' },
    { value: 'admin',       label: 'Admin',       help: 'Manages a single organization.' },
    { value: 'user',        label: 'User',        help: 'Can view their organization’s skills.' },
  ];
  const allowed =
    currentRole === 'super_admin' ? ['super_admin', 'admin', 'user']
    : currentRole === 'admin'     ? ['admin', 'user']
    : ['user'];
  const roleOptions = ALL_ROLES.filter(r => allowed.includes(r.value));
  // Default to the lowest-privilege role available so we don't silently
  // pre-elevate someone.
  const defaultRole = roleOptions[roleOptions.length - 1].value;

  const [name, setName] = useS('');
  const [email, setEmail] = useS('');
  const [pw, setPw] = useS('');
  const [pw2, setPw2] = useS('');
  const [newRole, setNewRole] = useS(defaultRole);
  const [submitted, setSubmitted] = useS(false);
  const [busy, setBusy] = useS(false);
  const [serverError, setServerError] = useS('');
  const nameValid = name.trim().length >= 2;
  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
  const pwValid = pw.length >= 8;
  const pwMatches = pw.length > 0 && pw === pw2;
  const roleValid = allowed.includes(newRole);
  const valid = nameValid && emailValid && pwValid && pwMatches && roleValid;

  useE(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, []);

  const handleSubmit = async () => {
    setServerError('');
    if (!valid || busy) return;
    setBusy(true);
    try {
      const token = (() => { try { return localStorage.getItem('pr.token'); } catch { return null; } })();
      const r = await fetch('/api/auth/admins', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        body: JSON.stringify({ name: name.trim(), email: email.trim(), password: pw, role: newRole }),
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok) {
        const msg =
          data.error === 'email_already_exists' ? 'An account with that email already exists.'
          : data.error === 'password_too_short' ? 'Password must be at least 8 characters.'
          : data.error === 'invalid_email' ? 'Invalid email address.'
          : data.error === 'name_required' ? 'Full name is required.'
          : data.error === 'role_not_allowed' ? 'You can’t assign that role.'
          : data.error || `Failed (${r.status})`;
        setServerError(msg);
        return;
      }
      setSubmitted(true);
      setTimeout(onClose, 1400);
    } catch (e) {
      setServerError(String(e?.message || e));
    } finally {
      setBusy(false);
    }
  };

  const inputStyle = {
    height: 44, padding: '0 14px', borderRadius: 12,
    background: 'var(--c-cream-50)',
    border: '1.5px solid var(--border-subtle)',
    boxShadow: 'var(--shadow-inset-input)',
    fontFamily: "'Suisse Int\\'l', sans-serif", fontSize: 14, color: 'var(--c-ink-900)',
    width: '100%', outline: 'none', boxSizing: 'border-box',
  };
  const labelStyle = { fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 500, fontSize: 13, color: 'var(--c-ink-900)' };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(23,53,64,0.32)',
      zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24, animation: 'pr-fade .15s ease-out',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width: 480, maxWidth: '100%', background: 'var(--c-cream-50)',
        border: '1px solid var(--border-subtle)', borderRadius: 16,
        boxShadow: 'var(--shadow-float-lg)', overflow: 'hidden',
        animation: 'pr-fade .18s ease-out',
      }}>
        <header style={{
          display: 'flex', alignItems: 'flex-start', gap: 12,
          padding: '20px 22px 16px', borderBottom: '1px solid var(--border-subtle)',
          background: 'var(--c-cream-100)',
        }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="eyebrow" style={{ color: 'var(--c-ink-500)', letterSpacing: '1.5px' }}>Access</div>
            <div style={{
              fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700, fontSize: 20,
              letterSpacing: '-0.02em', color: 'var(--c-ink-800)', marginTop: 4,
            }}>Add people</div>
          </div>
          <button onClick={onClose} title="Close" style={{
            width: 32, height: 32, borderRadius: 10, border: '1px solid var(--border-subtle)',
            background: 'var(--c-white)', boxShadow: 'var(--shadow-raised-sm)', cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none',
          }}>
            <img src="../assets/icons/cross.svg" width={11} height={11} alt="Close" />
          </button>
        </header>

        <div style={{ padding: '20px 22px', display: 'flex', flexDirection: 'column', gap: 16 }}>
          <p style={{ margin: 0, fontSize: 13, lineHeight: 1.55, color: 'var(--c-ink-600)', textWrap: 'pretty' }}>
            Set their name, email, password and role. They can change the password after first sign-in.
          </p>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Full name</label>
            <input type="text" autoFocus value={name} onChange={e => setName(e.target.value)}
              placeholder="e.g. Deepak Sekar" style={inputStyle} />
            {name.length > 0 && !nameValid && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Enter their full name.</span>
            )}
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Email address</label>
            <input type="email" value={email} onChange={e => setEmail(e.target.value)}
              placeholder="name@company.com" style={inputStyle} />
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Role</label>
            <div style={{ display: 'grid', gap: 8 }}>
              {roleOptions.map(opt => {
                const sel = newRole === opt.value;
                return (
                  <label key={opt.value} style={{
                    display: 'flex', alignItems: 'flex-start', gap: 10, cursor: 'pointer',
                    padding: '10px 12px', borderRadius: 10,
                    background: sel ? 'var(--c-white)' : 'var(--c-cream-50)',
                    border: sel ? '1.5px solid var(--c-petrol-800)' : '1px solid var(--border-subtle)',
                    boxShadow: sel ? 'var(--shadow-raised-sm)' : 'none',
                  }}>
                    <input type="radio" name="new-role" value={opt.value}
                      checked={sel} onChange={() => setNewRole(opt.value)}
                      style={{ marginTop: 3, accentColor: 'var(--c-petrol-800)' }} />
                    <span style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                      <span style={{
                        fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 500, fontSize: 14,
                        color: 'var(--c-ink-900)', letterSpacing: '-0.01em',
                      }}>{opt.label}</span>
                      <span style={{ fontSize: 11, color: 'var(--c-ink-500)' }}>{opt.help}</span>
                    </span>
                  </label>
                );
              })}
            </div>
            {roleOptions.length === 1 && (
              <span style={{ fontSize: 11, color: 'var(--c-ink-500)' }}>
                You can only invite users at your level.
              </span>
            )}
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Password</label>
            <input type="password" value={pw} onChange={e => setPw(e.target.value)}
              placeholder="At least 8 characters" style={inputStyle} />
            {pw.length > 0 && !pwValid && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Use at least 8 characters.</span>
            )}
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Confirm password</label>
            <input type="password" value={pw2} onChange={e => setPw2(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter' && valid && !submitted) handleSubmit(); }}
              placeholder="Re-enter password" style={inputStyle} />
            {pw2.length > 0 && !pwMatches && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Passwords do not match.</span>
            )}
          </div>

          {serverError && (
            <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>{serverError}</span>
          )}
        </div>

        <footer style={{
          padding: '14px 22px', borderTop: '1px solid var(--border-subtle)',
          background: 'var(--c-cream-100)', display: 'flex', alignItems: 'center', gap: 10,
        }}>
          {submitted && (
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              color: 'var(--c-olive-600, #5A6A3A)', fontSize: 12, fontWeight: 500,
            }}>
              <img src="../assets/icons/success.svg" width={13} height={13} alt="" />
              Person added
            </span>
          )}
          <div style={{ flex: 1 }} />
          <button onClick={onClose} style={{
            height: 40, padding: '0 16px', borderRadius: 10, border: '1.5px solid var(--c-petrol-800)',
            background: 'transparent', color: 'var(--c-petrol-800)',
            fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12, cursor: 'pointer',
          }}>Cancel</button>
          <button onClick={handleSubmit} disabled={!valid || submitted || busy} style={{
            height: 40, padding: '0 18px', borderRadius: 10, border: 'none',
            background: (valid && !submitted && !busy) ? 'var(--c-petrol-800)' : 'var(--c-cream-100)',
            color: (valid && !submitted && !busy) ? '#fff' : 'var(--c-ink-300)',
            fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12,
            boxShadow: (valid && !submitted && !busy) ? 'var(--shadow-raised-sm)' : 'none',
            cursor: (valid && !submitted && !busy) ? 'pointer' : 'not-allowed',
            display: 'inline-flex', alignItems: 'center', gap: 8,
          }}>
            <img src="../assets/icons/plus.svg" width={11} height={11} alt=""
              style={{ filter: (valid && !submitted && !busy) ? 'invert(1) brightness(2)' : 'none' }} />
            {busy ? 'Adding…' : 'Add person'}
          </button>
        </footer>
      </div>
    </div>
  );
}

function AddAdminModal({ onClose }) {
  const [name, setName] = useS('');
  const [email, setEmail] = useS('');
  const [pw, setPw] = useS('');
  const [pw2, setPw2] = useS('');
  const [submitted, setSubmitted] = useS(false);
  const [busy, setBusy] = useS(false);
  const [serverError, setServerError] = useS('');
  const nameValid = name.trim().length >= 2;
  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
  const pwValid = pw.length >= 8;
  const pwMatches = pw.length > 0 && pw === pw2;
  const valid = nameValid && emailValid && pwValid && pwMatches;

  useE(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, []);

  const handleSubmit = async () => {
    setServerError('');
    if (!valid || busy) return;
    setBusy(true);
    try {
      const token = (() => { try { return localStorage.getItem('pr.token'); } catch { return null; } })();
      const r = await fetch('/api/auth/admins', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        body: JSON.stringify({ name: name.trim(), email: email.trim(), password: pw }),
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok) {
        const msg =
          data.error === 'email_already_exists' ? 'An account with that email already exists.'
          : data.error === 'password_too_short' ? 'Password must be at least 8 characters.'
          : data.error === 'invalid_email' ? 'Invalid email address.'
          : data.error === 'name_required' ? 'Full name is required.'
          : data.error || `Failed (${r.status})`;
        setServerError(msg);
        return;
      }
      setSubmitted(true);
      setTimeout(onClose, 1400);
    } catch (e) {
      setServerError(String(e?.message || e));
    } finally {
      setBusy(false);
    }
  };

  const inputStyle = {
    height: 44, padding: '0 14px', borderRadius: 12,
    background: 'var(--c-cream-50)',
    border: '1.5px solid var(--border-subtle)',
    boxShadow: 'var(--shadow-inset-input)',
    fontFamily: "'Suisse Int\\'l', sans-serif", fontSize: 14, color: 'var(--c-ink-900)',
    width: '100%', outline: 'none', boxSizing: 'border-box',
  };
  const labelStyle = { fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 500, fontSize: 13, color: 'var(--c-ink-900)' };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(23,53,64,0.32)',
      zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24, animation: 'pr-fade .15s ease-out',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width: 460, maxWidth: '100%', background: 'var(--c-cream-50)',
        border: '1px solid var(--border-subtle)', borderRadius: 16,
        boxShadow: 'var(--shadow-float-lg)', overflow: 'hidden',
        animation: 'pr-fade .18s ease-out',
      }}>
        <header style={{
          display: 'flex', alignItems: 'flex-start', gap: 12,
          padding: '20px 22px 16px', borderBottom: '1px solid var(--border-subtle)',
          background: 'var(--c-cream-100)',
        }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="eyebrow" style={{ color: 'var(--c-ink-500)', letterSpacing: '1.5px' }}>Admin access</div>
            <div style={{
              fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700, fontSize: 20,
              letterSpacing: '-0.02em', color: 'var(--c-ink-800)', marginTop: 4,
            }}>Add an admin</div>
          </div>
          <button onClick={onClose} title="Close" style={{
            width: 32, height: 32, borderRadius: 10, border: '1px solid var(--border-subtle)',
            background: 'var(--c-white)', boxShadow: 'var(--shadow-raised-sm)', cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none',
          }}>
            <img src="../assets/icons/cross.svg" width={11} height={11} alt="Close" />
          </button>
        </header>

        <div style={{ padding: '20px 22px', display: 'flex', flexDirection: 'column', gap: 16 }}>
          <p style={{ margin: 0, fontSize: 13, lineHeight: 1.55, color: 'var(--c-ink-600)', textWrap: 'pretty' }}>
            Set the new admin's name, email and a temporary password. They can change it after first sign-in.
          </p>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Full name</label>
            <input type="text" autoFocus value={name} onChange={e => setName(e.target.value)}
              placeholder="e.g. Deepak Sekar" style={inputStyle} />
            {name.length > 0 && !nameValid && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Enter the admin's full name.</span>
            )}
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Email address</label>
            <input type="email" value={email} onChange={e => setEmail(e.target.value)}
              placeholder="name@company.com" style={inputStyle} />
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Password</label>
            <input type="password" value={pw} onChange={e => setPw(e.target.value)}
              placeholder="At least 8 characters" style={inputStyle} />
            {pw.length > 0 && !pwValid && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Use at least 8 characters.</span>
            )}
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <label style={labelStyle}>Confirm password</label>
            <input type="password" value={pw2} onChange={e => setPw2(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter' && valid && !submitted) handleSubmit(); }}
              placeholder="Re-enter password" style={inputStyle} />
            {pw2.length > 0 && !pwMatches && (
              <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>Passwords do not match.</span>
            )}
          </div>

          {serverError && (
            <span style={{ fontSize: 12, color: 'var(--c-terra-600, #C65A42)' }}>{serverError}</span>
          )}
        </div>

        <footer style={{
          padding: '14px 22px', borderTop: '1px solid var(--border-subtle)',
          background: 'var(--c-cream-100)', display: 'flex', alignItems: 'center', gap: 10,
        }}>
          {submitted && (
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              color: 'var(--c-olive-600, #5A6A3A)', fontSize: 12, fontWeight: 500,
            }}>
              <img src="../assets/icons/success.svg" width={13} height={13} alt="" />
              Admin added
            </span>
          )}
          <div style={{ flex: 1 }} />
          <button onClick={onClose} style={{
            height: 40, padding: '0 16px', borderRadius: 10, border: '1.5px solid var(--c-petrol-800)',
            background: 'transparent', color: 'var(--c-petrol-800)',
            fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12, cursor: 'pointer',
          }}>Cancel</button>
          <button onClick={handleSubmit} disabled={!valid || submitted || busy} style={{
            height: 40, padding: '0 18px', borderRadius: 10, border: 'none',
            background: (valid && !submitted && !busy) ? 'var(--c-petrol-800)' : 'var(--c-cream-100)',
            color: (valid && !submitted && !busy) ? '#fff' : 'var(--c-ink-300)',
            fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 12,
            boxShadow: (valid && !submitted && !busy) ? 'var(--shadow-raised-sm)' : 'none',
            cursor: (valid && !submitted && !busy) ? 'pointer' : 'not-allowed',
            display: 'inline-flex', alignItems: 'center', gap: 8,
          }}>
            <img src="../assets/icons/plus.svg" width={11} height={11} alt=""
              style={{ filter: (valid && !submitted && !busy) ? 'invert(1) brightness(2)' : 'none' }} />
            {busy ? 'Adding…' : 'Add admin'}
          </button>
        </footer>
      </div>
    </div>
  );
}

function roleLabel(role) {
  if (role === 'super_admin') return 'Super admin';
  if (role === 'admin') return 'Admin';
  return 'User';
}

const menuItemStyle = {
  display: 'flex', alignItems: 'center', gap: 10, width: '100%',
  padding: '10px 12px', borderRadius: 8, border: 'none', cursor: 'pointer',
  background: 'transparent', textAlign: 'left',
  fontFamily: "'Inter', sans-serif", fontWeight: 500, fontSize: 13,
  color: 'var(--c-ink-800)', letterSpacing: '0.01em',
};

/* ---------- Column shell ---------- */
function Col({ title, count, action, children, width, density }) {
  return (
    <section style={{
      width, flex: width ? 'none' : 1, minWidth: 0,
      background: 'var(--c-cream-50)', borderRadius: 16,
      border: '1px solid var(--border-subtle)', boxShadow: 'var(--shadow-raised-sm)',
      display: 'flex', flexDirection: 'column', overflow: 'hidden',
    }}>
      <header style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: density === 'compact' ? '12px 14px' : '16px 18px',
        borderBottom: '1px solid var(--border-subtle)',
        background: 'var(--c-cream-100)',
      }}>
        <span className="eyebrow" style={{ color: 'var(--c-ink-700)', letterSpacing: '1.5px' }}>{title}</span>
        {count != null && <span style={{
          fontFamily: "'Inter', sans-serif", fontSize: 10, fontWeight: 700,
          color: 'var(--c-ink-500)', background: 'var(--c-white)',
          border: '1px solid var(--border-subtle)', borderRadius: 999,
          padding: '2px 8px', lineHeight: 1.4,
        }}>{count}</span>}
        <div style={{ flex: 1 }} />
        {action}
      </header>
      <div style={{ flex: 1, overflow: 'auto', padding: density === 'compact' ? 8 : 10 }}>
        {children}
      </div>
    </section>
  );
}

/* ---------- Org list item ---------- */
function OrgRow({ org, selected, count, onSelect, density }) {
  return (
    <button onClick={onSelect} style={{
      display: 'flex', alignItems: 'center', gap: 12, width: '100%',
      padding: density === 'compact' ? '10px 12px' : '14px 14px',
      borderRadius: 12, border: 'none', cursor: 'pointer', textAlign: 'left',
      background: selected ? 'var(--c-white)' : 'transparent',
      boxShadow: selected ? 'var(--shadow-raised-sm)' : 'none',
      borderLeft: selected ? '3px solid var(--c-petrol-800)' : '3px solid transparent',
      marginBottom: 4, transition: 'all .15s ease-out',
    }}>
      <div style={{
        width: 36, height: 36, borderRadius: 10, flex: 'none',
        background: 'var(--c-petrol-800)', color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700, fontSize: 14, letterSpacing: '-0.02em',
      }}>{org.name.split(' ').map(w => w[0]).slice(0, 2).join('')}</div>
      <div style={{ minWidth: 0, flex: 1 }}>
        <div style={{
          fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 500, fontSize: 14,
          color: 'var(--c-ink-900)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>{org.name}</div>
        <div style={{ fontSize: 11, color: 'var(--c-ink-500)', marginTop: 2,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{org.kind}</div>
      </div>
      <div style={{
        fontFamily: "'Inter', sans-serif", fontSize: 10, fontWeight: 700,
        color: 'var(--c-ink-500)',
      }}>{count}</div>
    </button>
  );
}

/* ---------- Employee list item ---------- */
function EmpRow({ emp, selected, onSelect, density }) {
  const initials = emp.name.split(' ').map(w => w[0]).slice(0, 2).join('');
  return (
    <button onClick={onSelect} style={{
      display: 'flex', alignItems: 'center', gap: 12, width: '100%',
      padding: density === 'compact' ? '8px 10px' : '12px 12px',
      borderRadius: 12, border: 'none', cursor: 'pointer', textAlign: 'left',
      background: selected ? 'var(--c-white)' : 'transparent',
      boxShadow: selected ? 'var(--shadow-raised-sm)' : 'none',
      marginBottom: 4, transition: 'all .15s ease-out',
    }}>
      <div style={{
        width: 32, height: 32, borderRadius: '50%', flex: 'none',
        background: 'var(--c-cream-100)', color: 'var(--c-petrol-800)',
        border: '1px solid var(--border-subtle)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 11,
      }}>{initials}</div>
      <div style={{ minWidth: 0, flex: 1 }}>
        <div style={{ fontWeight: 500, fontSize: 14, color: 'var(--c-ink-900)',
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{emp.name}</div>
        <div style={{ fontSize: 11, color: 'var(--c-ink-500)', marginTop: 1,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{emp.role}</div>
      </div>
      <span style={{
        fontFamily: "'Inter', sans-serif", fontSize: 10, fontWeight: 700,
        color: 'var(--c-petrol-800)', background: 'var(--c-petrol-050)',
        padding: '2px 8px', borderRadius: 999,
      }}>{emp.skills.length}</span>
    </button>
  );
}

/* ---------- Skill card (grid view) ---------- */
function SkillCard({ skill, onClick, density }) {
  return (
    <div onClick={onClick} style={{
      borderRadius: 16, padding: density === 'compact' ? 14 : 18, cursor: 'pointer',
      background: 'var(--c-white)', border: '1px solid var(--border-subtle)',
      boxShadow: 'var(--shadow-raised-sm)', display: 'flex', flexDirection: 'column', gap: 10,
      transition: 'all .15s ease-out', minHeight: 140,
    }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
        <div style={{
          width: 32, height: 32, borderRadius: 10, flex: 'none',
          background: 'var(--c-petrol-050)', color: 'var(--c-petrol-800)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <img src="../assets/icons/sparkle.svg" width={16} height={16} alt="" />
        </div>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ fontWeight: 500, fontSize: 15, color: 'var(--c-ink-900)',
            letterSpacing: '-0.01em', lineHeight: 1.3 }}>{skill.name}</div>
          <div style={{ fontFamily: "'Inter', sans-serif", fontSize: 10, fontWeight: 500,
            color: 'var(--c-ink-500)', letterSpacing: '0.02em', marginTop: 4 }}>
            {skill.file?.version ? `v${skill.file.version} · ${skill.file.updated || ''}` : 'no version yet'}
          </div>
        </div>
      </div>
      <p style={{
        margin: 0, fontSize: 13, lineHeight: 1.45, color: 'var(--c-ink-600)',
        display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical',
        overflow: 'hidden', textWrap: 'pretty',
      }}>{skill.desc}</p>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 'auto' }}>
        {skill.inputs.slice(0, 4).map(i => (
          <span key={i} style={{
            fontFamily: "'Inter', sans-serif", fontSize: 10, fontWeight: 500,
            color: 'var(--c-ink-700)', background: 'var(--c-cream-100)',
            border: '1px solid var(--border-subtle)',
            padding: '3px 8px', borderRadius: 6, letterSpacing: '0.02em',
          }}>{i}</span>
        ))}
        {skill.inputs.length > 4 && (
          <span style={{ fontFamily: "'Inter', sans-serif", fontSize: 10, fontWeight: 500, color: 'var(--c-ink-500)' }}>
            +{skill.inputs.length - 4} more
          </span>
        )}
      </div>
    </div>
  );
}

/* ---------- Skill row (list view) ---------- */
function SkillListRow({ skill, onClick, density }) {
  return (
    <div onClick={onClick} style={{
      display: 'grid', gridTemplateColumns: '1fr 80px 120px 24px',
      gap: 12, alignItems: 'center', cursor: 'pointer',
      padding: density === 'compact' ? '10px 14px' : '14px 16px',
      borderRadius: 12, background: 'var(--c-white)',
      border: '1px solid var(--border-subtle)', boxShadow: 'var(--shadow-raised-sm)',
      marginBottom: 8,
    }}>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontWeight: 500, fontSize: 14, color: 'var(--c-ink-900)',
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{skill.name}</div>
        <div style={{ fontSize: 12, color: 'var(--c-ink-500)', marginTop: 2,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', textWrap: 'pretty' }}>{skill.desc}</div>
      </div>
      <span style={{
        fontFamily: "'Inter', sans-serif", fontSize: 11, fontWeight: 700,
        color: 'var(--c-petrol-800)', background: 'var(--c-petrol-050)',
        padding: '4px 10px', borderRadius: 999, justifySelf: 'start',
      }}>{skill.inputs.length} input{skill.inputs.length === 1 ? '' : 's'}</span>
      <span style={{
        fontFamily: "'Inter', sans-serif", fontSize: 11, fontWeight: 500,
        color: 'var(--c-ink-500)', letterSpacing: '0.02em',
      }}>{skill.file?.version ? `v${skill.file.version} · ${skill.file.updated || ''}` : '—'}</span>
      <img src="../assets/icons/next.svg" width={14} height={14} alt="" style={{ opacity: 0.5, justifySelf: 'end' }} />
    </div>
  );
}

/* ---------- Empty state ---------- */
function Empty({ icon = 'sparkle', title, body, action }) {
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', alignItems: 'center',
      justifyContent: 'center', padding: '48px 24px', height: '100%',
      gap: 14, textAlign: 'center',
    }}>
      <div style={{
        width: 56, height: 56, borderRadius: 16, background: 'var(--c-cream-100)',
        border: '1px solid var(--border-subtle)', boxShadow: 'var(--shadow-raised-sm)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: 'var(--c-petrol-500)',
      }}>
        <img src={`../assets/icons/${icon}.svg`} width={22} height={22} alt="" />
      </div>
      <div>
        <div style={{ fontWeight: 500, fontSize: 16, color: 'var(--c-ink-900)' }}>{title}</div>
        {body && <div style={{ fontSize: 13, color: 'var(--c-ink-500)', marginTop: 6, maxWidth: 320, textWrap: 'pretty' }}>{body}</div>}
      </div>
      {action}
    </div>
  );
}

Object.assign(window, { PRTopbar, Col, OrgRow, EmpRow, SkillCard, SkillListRow, Empty });
