// Admin → Settings — a best-in-class CRM settings suite.
// Tabs: General, Access & Roles (the access matrix lives here now), Security,
// Notifications, Data & Privacy, Integrations, API & Webhooks.
window.DEFAULT_SETTINGS = {
  org: { name: 'Kitchens U Build', currency: 'AUD', timezone: 'Australia/Melbourne', dateFormat: 'DD/MM/YYYY', fyStart: 'July', weekStart: 'Monday' },
  notifications: { defaultLeadMinutes: 15, emailReminders: true, smsReminders: false, dailyDigest: true, newLeadAlert: true, stuckDealAlert: true },
  security: { enforce2FA: false, ssoEnabled: false, sessionTimeoutMins: 60, passwordMinLength: 10, ipAllowlist: '', auditRetentionDays: 365 },
  privacy: { autoArchiveDays: 1095, allowManagerExport: true, gdprMode: true },
  appearance: { theme: 'pine' },
  integrations: {},
  apiKey: 'pk_live_•••• •••• •••• 7Q2a',
  webhooks: [],
};

// Selectable colour themes. `pine` is the signature default; the rest let users
// retheme the whole workspace. Keep ids in sync with [data-theme] blocks in styles.css.
window.THEMES = [
  { id: 'pine', name: 'Pine', desc: 'Signature — evergreen, dark forest sidebar · Hanken Grotesk', accent: '#1F6E5A', bg: '#ECEDEA', sidebar: '#163A2E', sidebarAccent: '#57C79E' },
  { id: 'indigo', name: 'Indigo', desc: 'Confident, corporate, deep-navy sidebar · IBM Plex Sans', accent: '#4F63D2', bg: '#E9EBF0', sidebar: '#1C1F45', sidebarAccent: '#8E9DFF' },
  { id: 'terracotta', name: 'Terracotta', desc: 'Warm clay, espresso sidebar · Schibsted Grotesk', accent: '#BC5B3C', bg: '#EFEAE4', sidebar: '#38231B', sidebarAccent: '#E8956F' },
  { id: 'slate', name: 'Slate', desc: 'Minimal graphite, charcoal sidebar · Geist', accent: '#44556B', bg: '#EAECEF', sidebar: '#1E2632', sidebarAccent: '#9DB0CC' },
  { id: 'ocean', name: 'Ocean', desc: 'Fresh teal, deep-sea sidebar · Figtree', accent: '#0E7490', bg: '#E8EDEF', sidebar: '#0C3742', sidebarAccent: '#51C6DF' },
];

// Full token set per theme — applied inline on <html> at runtime so theme
// switches recompute reliably (mirrors the [data-theme] blocks in styles.css).
window.THEME_TOKENS = {
  pine: {
    '--bg': '#ECEDEA', '--surface-2': '#F5F6F2', '--surface-3': '#EDEEE9', '--border': '#E0E2DC', '--border-strong': '#CDCFC7',
    '--accent': '#1F6E5A', '--accent-soft': '#E4F0EC', '--accent-ink': '#15503F',
    '--sidebar-bg': '#163A2E', '--sidebar-ink': '#EAF2EE', '--sidebar-dim': '#9DB5AC', '--sidebar-hover': 'rgba(255,255,255,0.07)', '--sidebar-active': 'rgba(87,199,158,0.16)', '--sidebar-accent': '#57C79E', '--sidebar-border': 'rgba(255,255,255,0.09)',
    '--font': "'Hanken Grotesk', system-ui, sans-serif",
  },
  indigo: {
    '--bg': '#E9EBF0', '--surface-2': '#F4F6F9', '--surface-3': '#ECEEF3', '--border': '#E1E4EA', '--border-strong': '#CDD1DA',
    '--accent': '#4F63D2', '--accent-soft': '#EEF0FD', '--accent-ink': '#2D3A8C',
    '--sidebar-bg': '#1C1F45', '--sidebar-ink': '#ECEDFB', '--sidebar-dim': '#9FA3CE', '--sidebar-hover': 'rgba(255,255,255,0.07)', '--sidebar-active': 'rgba(142,157,255,0.18)', '--sidebar-accent': '#8E9DFF', '--sidebar-border': 'rgba(255,255,255,0.08)',
    '--font': "'IBM Plex Sans', system-ui, sans-serif",
  },
  terracotta: {
    '--bg': '#EFEAE4', '--surface-2': '#F8F4EF', '--surface-3': '#F0EBE4', '--border': '#E7DFD6', '--border-strong': '#D6CBBE',
    '--accent': '#BC5B3C', '--accent-soft': '#F7E9E2', '--accent-ink': '#8A3F28',
    '--sidebar-bg': '#38231B', '--sidebar-ink': '#F4E9E3', '--sidebar-dim': '#C2A395', '--sidebar-hover': 'rgba(255,255,255,0.07)', '--sidebar-active': 'rgba(232,144,112,0.18)', '--sidebar-accent': '#E8956F', '--sidebar-border': 'rgba(255,255,255,0.08)',
    '--font': "'Schibsted Grotesk', system-ui, sans-serif",
  },
  slate: {
    '--bg': '#EAECEF', '--surface-2': '#F4F5F7', '--surface-3': '#ECEEF1', '--border': '#E2E5E9', '--border-strong': '#CFD3D9',
    '--accent': '#44556B', '--accent-soft': '#EAEDF1', '--accent-ink': '#2E3A4B',
    '--sidebar-bg': '#1E2632', '--sidebar-ink': '#E9EDF2', '--sidebar-dim': '#9AA7B8', '--sidebar-hover': 'rgba(255,255,255,0.06)', '--sidebar-active': 'rgba(157,176,204,0.18)', '--sidebar-accent': '#9DB0CC', '--sidebar-border': 'rgba(255,255,255,0.07)',
    '--font': "'Geist', system-ui, sans-serif",
  },
  ocean: {
    '--bg': '#E8EDEF', '--surface-2': '#F3F7F8', '--surface-3': '#EBF0F2', '--border': '#DEE6E9', '--border-strong': '#C9D4D8',
    '--accent': '#0E7490', '--accent-soft': '#E0F2F7', '--accent-ink': '#0A5468',
    '--sidebar-bg': '#0C3742', '--sidebar-ink': '#E5F2F5', '--sidebar-dim': '#8FB4BD', '--sidebar-hover': 'rgba(255,255,255,0.07)', '--sidebar-active': 'rgba(81,198,222,0.18)', '--sidebar-accent': '#51C6DF', '--sidebar-border': 'rgba(255,255,255,0.09)',
    '--font': "'Figtree', system-ui, sans-serif",
  },
};

function Toggle({ on, onChange, disabled }) {
  return (
    <button onClick={() => !disabled && onChange(!on)} disabled={disabled}
      style={{ width: 38, height: 22, borderRadius: 999, border: 'none', cursor: disabled ? 'not-allowed' : 'pointer', flexShrink: 0,
        background: on ? 'var(--won)' : 'var(--border-strong)', position: 'relative', transition: 'background 0.15s', opacity: disabled ? 0.5 : 1 }}>
      <span style={{ position: 'absolute', top: 2, left: on ? 18 : 2, width: 18, height: 18, borderRadius: '50%', background: 'white', transition: 'left 0.15s', boxShadow: '0 1px 2px rgba(0,0,0,0.2)' }}></span>
    </button>
  );
}

function SettingRow({ label, desc, children }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '13px 0', borderBottom: '1px solid var(--border)' }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 500 }}>{label}</div>
        {desc && <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 2 }}>{desc}</div>}
      </div>
      <div style={{ flexShrink: 0, display: 'flex', alignItems: 'center', gap: 8 }}>{children}</div>
    </div>
  );
}

const INTEGRATIONS = [
  { group: 'Email & Calendar', items: [
    { id: 'gmail', name: 'Gmail', mono: 'G', color: 'oklch(0.55 0.18 25)', desc: 'Two-way email sync & tracking', auth: 'oauth', scopes: ['Read & send email on your behalf', 'Log messages against contacts'] },
    { id: 'outlook', name: 'Outlook 365', mono: 'O', color: 'oklch(0.5 0.15 250)', desc: 'Email + calendar sync', auth: 'oauth', scopes: ['Read & send email', 'Read & write calendar events'] },
    { id: 'gcal', name: 'Google Calendar', mono: 'C', color: 'oklch(0.55 0.16 145)', desc: 'Sync appointments both ways', auth: 'oauth', scopes: ['Read & write calendar events'] },
  ]},
  { group: 'Accounting & Payments', items: [
    { id: 'xero', name: 'Xero', mono: 'X', color: 'oklch(0.6 0.13 220)', desc: 'Push deposits & invoices', auth: 'oauth', scopes: ['Create invoices & payments', 'Read contacts & chart of accounts'] },
    { id: 'myob', name: 'MYOB', mono: 'M', color: 'oklch(0.5 0.16 290)', desc: 'Invoice & payment sync', auth: 'oauth', scopes: ['Create invoices', 'Read customers'] },
    { id: 'stripe', name: 'Stripe', mono: 'S', color: 'oklch(0.5 0.16 280)', desc: 'Take deposits online', auth: 'apikey', fields: [{ key: 'pk', label: 'Publishable key', placeholder: 'pk_live_…' }, { key: 'sk', label: 'Secret key', placeholder: 'sk_live_…', secret: true }] },
  ]},
  { group: 'Comms & Marketing', items: [
    { id: 'twilio', name: 'Twilio SMS', mono: 'T', color: 'oklch(0.55 0.18 25)', desc: 'Send SMS reminders', auth: 'apikey', fields: [{ key: 'sid', label: 'Account SID', placeholder: 'AC…' }, { key: 'token', label: 'Auth token', placeholder: '••••••••', secret: true }, { key: 'from', label: 'From number', placeholder: '+61…' }] },
    { id: 'slack', name: 'Slack', mono: 'S', color: 'oklch(0.55 0.15 300)', desc: 'Deal & lead notifications', auth: 'oauth', scopes: ['Post messages to a channel'] },
    { id: 'mailchimp', name: 'Mailchimp', mono: 'M', color: 'oklch(0.7 0.15 90)', desc: 'Sync contacts to campaigns', auth: 'oauth', scopes: ['Read & write audience contacts'] },
  ]},
  { group: 'e-Sign & Automation', items: [
    { id: 'docusign', name: 'DocuSign', mono: 'D', color: 'oklch(0.5 0.15 250)', desc: 'Send contracts for e-signature', auth: 'oauth', scopes: ['Send envelopes for signature', 'Read signing status'] },
    { id: 'zapier', name: 'Zapier', mono: 'Z', color: 'oklch(0.62 0.17 40)', desc: '5,000+ app automations', auth: 'zapier' },
    { id: 'powerbi', name: 'Power BI', mono: 'P', color: 'oklch(0.68 0.16 80)', desc: 'Live BI dashboards', auth: 'apikey', fields: [{ key: 'key', label: 'Dataset API key', placeholder: 'bi_…', secret: true }] },
  ]},
];

function Settings({ settings, onChange, accessMatrix, onSetAccess, currentUser, showToast }) {
  const [tab, setTab] = React.useState('general');
  const [revealKey, setRevealKey] = React.useState(false);
  const [connecting, setConnecting] = React.useState(null);
  const [twofaOpen, setTwofaOpen] = React.useState(false);
  const isAdmin = currentUser.role === 'admin' || currentUser.superAdmin;
  const s = settings;

  const TABS = [
    { id: 'general', label: 'General', icon: 'sliders' },
    { id: 'appearance', label: 'Appearance', icon: 'tag' },
    { id: 'access', label: 'Access & Roles', icon: 'lock' },
    { id: 'security', label: 'Security', icon: 'lock' },
    { id: 'notifications', label: 'Notifications', icon: 'alert' },
    { id: 'privacy', label: 'Data & Privacy', icon: 'download' },
    { id: 'integrations', label: 'Integrations', icon: 'spark' },
    { id: 'api', label: 'API & Webhooks', icon: 'table' },
  ];

  const selStyle = { minWidth: 170 };
  const integrationConnected = (id) => !!(s.integrations && s.integrations[id]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '210px minmax(0,1fr)', gap: 20, alignItems: 'start' }}>
      {/* Sub-nav */}
      <nav style={{ position: 'sticky', top: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>
        {TABS.map(t => (
          <button key={t.id} onClick={() => setTab(t.id)}
            style={{ display: 'flex', alignItems: 'center', gap: 9, padding: '8px 11px', borderRadius: 7, fontSize: 13, fontWeight: 500, textAlign: 'left',
              color: tab === t.id ? 'var(--ink)' : 'var(--ink-3)', background: tab === t.id ? 'var(--surface-3)' : 'transparent', transition: 'background 0.12s' }}
            onMouseEnter={(e) => { if (tab !== t.id) e.currentTarget.style.background = 'var(--surface-2)'; }}
            onMouseLeave={(e) => { if (tab !== t.id) e.currentTarget.style.background = 'transparent'; }}>
            <Icon name={t.icon} size={14} style={{ opacity: 0.8 }}/> {t.label}
          </button>
        ))}
      </nav>

      <div>
        {tab === 'general' && (
          <Panel title="Organisation" sub="Workspace-wide defaults">
            <SettingRow label="Company name"><input value={s.org.name} onChange={(e) => onChange('org', 'name', e.target.value)} style={{ width: 240 }}/></SettingRow>
            <SettingRow label="Currency" desc="Used across deals, targets and reports">
              <select className="sel" style={selStyle} value={s.org.currency} onChange={(e) => onChange('org', 'currency', e.target.value)}>
                {['AUD', 'NZD', 'USD', 'GBP', 'EUR', 'CAD'].map(c => <option key={c} value={c}>{c}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="Timezone">
              <select className="sel" style={selStyle} value={s.org.timezone} onChange={(e) => onChange('org', 'timezone', e.target.value)}>
                {['Australia/Melbourne', 'Australia/Sydney', 'Australia/Brisbane', 'Australia/Perth', 'Pacific/Auckland', 'UTC'].map(t => <option key={t} value={t}>{t}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="Date format">
              <select className="sel" style={selStyle} value={s.org.dateFormat} onChange={(e) => onChange('org', 'dateFormat', e.target.value)}>
                {['DD/MM/YYYY', 'MM/DD/YYYY', 'YYYY-MM-DD'].map(t => <option key={t} value={t}>{t}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="Financial year starts">
              <select className="sel" style={selStyle} value={s.org.fyStart} onChange={(e) => onChange('org', 'fyStart', e.target.value)}>
                {['January', 'April', 'July', 'October'].map(t => <option key={t} value={t}>{t}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="Week starts on">
              <select className="sel" style={selStyle} value={s.org.weekStart} onChange={(e) => onChange('org', 'weekStart', e.target.value)}>
                {['Monday', 'Sunday'].map(t => <option key={t} value={t}>{t}</option>)}
              </select>
            </SettingRow>
          </Panel>
        )}

        {tab === 'appearance' && (
          <Panel title="Appearance" sub="Choose the colour theme for your workspace — applies across every page">
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 12, paddingTop: 6 }}>
              {(window.THEMES || []).map(t => {
                const on = ((s.appearance && s.appearance.theme) || 'pine') === t.id;
                return (
                  <button key={t.id} onClick={() => onChange('appearance', 'theme', t.id)}
                    style={{ textAlign: 'left', cursor: 'pointer', borderRadius: 10, padding: 14,
                      border: '1.5px solid ' + (on ? 'var(--accent)' : 'var(--border)'),
                      background: on ? 'var(--accent-soft)' : 'var(--surface)', transition: 'border-color 0.12s, background 0.12s' }}>
                    <div style={{ height: 56, borderRadius: 8, overflow: 'hidden', border: '1px solid var(--border)', display: 'flex', marginBottom: 11 }}>
                      <div style={{ width: '34%', background: t.sidebar, display: 'flex', flexDirection: 'column', gap: 5, padding: '8px 7px' }}>
                        <span style={{ width: '80%', height: 6, borderRadius: 3, background: t.sidebarAccent }}></span>
                        <span style={{ width: '95%', height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.28)' }}></span>
                        <span style={{ width: '70%', height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.16)' }}></span>
                        <span style={{ width: '85%', height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.16)' }}></span>
                      </div>
                      <div style={{ flex: 1, background: t.bg, padding: 8, display: 'flex', flexDirection: 'column', gap: 6 }}>
                        <span style={{ width: 46, height: 15, borderRadius: 7, background: t.accent }}></span>
                        <span style={{ width: '100%', height: 9, borderRadius: 3, background: '#fff' }}></span>
                        <span style={{ width: '70%', height: 9, borderRadius: 3, background: '#fff' }}></span>
                      </div>
                    </div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
                      <span style={{ width: 13, height: 13, borderRadius: '50%', background: t.accent, flexShrink: 0 }}></span>
                      <span style={{ fontSize: 13.5, fontWeight: 600 }}>{t.name}</span>
                      {t.id === 'pine' && <span className="pill" style={{ fontSize: 9, padding: '1px 7px' }}>Default</span>}
                      {on && <Icon name="check" size={16} color="var(--accent)" style={{ marginLeft: 'auto' }}/>}
                    </div>
                    <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 4 }}>{t.desc}</div>
                  </button>
                );
              })}
            </div>
          </Panel>
        )}

        {tab === 'access' && (
          window.AccessMatrix
            ? <AccessMatrix accessMatrix={accessMatrix} onSetAccess={onSetAccess} currentUser={currentUser}/>
            : <Panel title="Access & Roles"><div className="empty">Access matrix unavailable.</div></Panel>
        )}

        {tab === 'security' && (
          <Panel title="Security" sub="Protect access to the workspace">
            <SettingRow label="Authenticator app (2FA)" desc="Set up a time-based one-time code with Google / Microsoft Authenticator, Authy or 1Password">
              {s.security.twofaEnrolled ? (
                <React.Fragment>
                  <span className="pill" style={{ background: 'var(--won-soft)', color: 'oklch(0.4 0.1 155)' }}><Icon name="check" size={11}/> Active</span>
                  <button className="btn sm" onClick={() => setTwofaOpen(true)}>Reconfigure</button>
                  <button className="btn sm" style={{ color: 'var(--lost)' }} onClick={() => { if (confirm('Disable authenticator 2FA?')) { onChange('security', 'twofaEnrolled', false); onChange('security', 'twofaSecret', ''); showToast && showToast('Authenticator disabled'); } }}>Disable</button>
                </React.Fragment>
              ) : (
                <button className="btn sm primary" onClick={() => setTwofaOpen(true)}><Icon name="lock" size={12}/> Set up authenticator</button>
              )}
            </SettingRow>
            <SettingRow label="Enforce two-factor authentication (2FA)" desc="Require an authenticator code at sign-in for all users">
              <Toggle on={s.security.enforce2FA} onChange={(v) => onChange('security', 'enforce2FA', v)} disabled={!isAdmin}/>
            </SettingRow>
            <SettingRow label="Single sign-on (SSO / SAML)" desc="Let staff sign in with your identity provider (Okta, Azure AD, Google)">
              <Toggle on={s.security.ssoEnabled} onChange={(v) => onChange('security', 'ssoEnabled', v)} disabled={!isAdmin}/>
            </SettingRow>
            <SettingRow label="Session timeout" desc="Automatically sign out after inactivity">
              <select className="sel" style={selStyle} value={s.security.sessionTimeoutMins} onChange={(e) => onChange('security', 'sessionTimeoutMins', Number(e.target.value))} disabled={!isAdmin}>
                {[15, 30, 60, 120, 480].map(m => <option key={m} value={m}>{m < 60 ? m + ' minutes' : (m / 60) + ' hour' + (m > 60 ? 's' : '')}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="Minimum password length">
              <input type="number" min="8" max="32" value={s.security.passwordMinLength} onChange={(e) => onChange('security', 'passwordMinLength', Number(e.target.value))} style={{ width: 80 }} disabled={!isAdmin}/>
            </SettingRow>
            <SettingRow label="Audit-log retention" desc="How long change history is kept">
              <select className="sel" style={selStyle} value={s.security.auditRetentionDays} onChange={(e) => onChange('security', 'auditRetentionDays', Number(e.target.value))} disabled={!isAdmin}>
                {[90, 180, 365, 730, 1825].map(d => <option key={d} value={d}>{d < 365 ? d + ' days' : (d / 365) + ' year' + (d > 365 ? 's' : '')}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="IP allow-list" desc="Restrict sign-in to these IPs/ranges (one per line, blank = any)">
              <textarea value={s.security.ipAllowlist} onChange={(e) => onChange('security', 'ipAllowlist', e.target.value)} rows="2" placeholder="203.0.113.0/24" disabled={!isAdmin}
                style={{ width: 220, padding: '6px 8px', border: '1px solid var(--border)', borderRadius: 6, fontFamily: 'var(--mono, monospace)', fontSize: 12, resize: 'vertical' }}/>
            </SettingRow>
          </Panel>
        )}

        {tab === 'notifications' && (
          <Panel title="Notifications & reminders" sub="Defaults for the whole team">
            <SettingRow label="Default reminder lead time" desc="How far ahead reminders pop up by default">
              <select className="sel" style={selStyle} value={s.notifications.defaultLeadMinutes} onChange={(e) => onChange('notifications', 'defaultLeadMinutes', Number(e.target.value))}>
                {(window.REMINDER_LEADS || [{ v: 15, label: '15 minutes before' }]).map(o => <option key={o.v} value={o.v}>{o.label}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="Email reminders" desc="Send reminder emails to the deal owner"><Toggle on={s.notifications.emailReminders} onChange={(v) => onChange('notifications', 'emailReminders', v)}/></SettingRow>
            <SettingRow label="SMS reminders" desc="Requires the Twilio integration"><Toggle on={s.notifications.smsReminders} onChange={(v) => onChange('notifications', 'smsReminders', v)}/></SettingRow>
            <SettingRow label="Daily pipeline digest" desc="Morning summary of today's appointments & stuck deals"><Toggle on={s.notifications.dailyDigest} onChange={(v) => onChange('notifications', 'dailyDigest', v)}/></SettingRow>
            <SettingRow label="New inbound lead alert" desc="Notify the showroom instantly when a marketing lead arrives"><Toggle on={s.notifications.newLeadAlert} onChange={(v) => onChange('notifications', 'newLeadAlert', v)}/></SettingRow>
            <SettingRow label="Stuck-deal alert" desc="Flag deals with no activity for 21+ days"><Toggle on={s.notifications.stuckDealAlert} onChange={(v) => onChange('notifications', 'stuckDealAlert', v)}/></SettingRow>
          </Panel>
        )}

        {tab === 'privacy' && (
          <Panel title="Data & privacy" sub="Retention, exports and compliance">
            <SettingRow label="Auto-archive inactive contacts after" desc="Move untouched contacts to a dormant pool">
              <select className="sel" style={selStyle} value={s.privacy.autoArchiveDays} onChange={(e) => onChange('privacy', 'autoArchiveDays', Number(e.target.value))} disabled={!isAdmin}>
                {[365, 730, 1095, 1825].map(d => <option key={d} value={d}>{(d / 365)} year{d > 365 ? 's' : ''}</option>)}
              </select>
            </SettingRow>
            <SettingRow label="Allow managers to export data" desc="Store Managers can export their location's contacts"><Toggle on={s.privacy.allowManagerExport} onChange={(v) => onChange('privacy', 'allowManagerExport', v)} disabled={!isAdmin}/></SettingRow>
            <SettingRow label="Privacy / GDPR mode" desc="Hide financials from non-admins, log all exports, honour erasure requests"><Toggle on={s.privacy.gdprMode} onChange={(v) => onChange('privacy', 'gdprMode', v)} disabled={!isAdmin}/></SettingRow>
            <SettingRow label="Workspace backup" desc="Download a full snapshot of your CRM data">
              <button className="btn sm" onClick={() => showToast && showToast('Backup queued — you’ll get a download link by email')}><Icon name="download" size={12}/> Download backup</button>
            </SettingRow>
          </Panel>
        )}

        {tab === 'integrations' && (
          <div>
            <div style={{ fontSize: 12.5, color: 'var(--ink-3)', marginBottom: 14 }}>Connect Pearler to the tools your business already runs on. {Object.values(s.integrations || {}).filter(Boolean).length} connected.</div>
            {INTEGRATIONS.map(grp => (
              <div key={grp.group} style={{ marginBottom: 18 }}>
                <div style={{ fontSize: 10.5, textTransform: 'uppercase', letterSpacing: '0.07em', color: 'var(--ink-3)', fontWeight: 600, marginBottom: 8 }}>{grp.group}</div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
                  {grp.items.map(it => {
                    const conn = s.integrations && s.integrations[it.id];
                    const connected = !!conn;
                    const acct = conn && typeof conn === 'object' ? conn.account : null;
                    return (
                      <div key={it.id} className="card card-pad" style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                          <span style={{ width: 34, height: 34, borderRadius: 9, background: it.color, color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 15 }}>{it.mono}</span>
                          <div style={{ minWidth: 0 }}>
                            <div style={{ fontSize: 13, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 6 }}>{it.name}{connected && <span style={{ width: 7, height: 7, borderRadius: 4, background: 'var(--won)' }}></span>}</div>
                            <div style={{ fontSize: 11, color: 'var(--ink-3)', lineHeight: 1.3 }}>{acct || it.desc}</div>
                          </div>
                        </div>
                        {connected ? (
                          <div style={{ display: 'flex', gap: 6 }}>
                            <button className="btn sm" style={{ flex: 1, justifyContent: 'center', color: 'var(--won)', borderColor: 'var(--won-soft)' }} disabled><Icon name="check" size={12}/> Connected</button>
                            <button className="btn sm" disabled={!isAdmin} title="Disconnect" onClick={() => { if (confirm('Disconnect ' + it.name + '?')) { onChange('integrations', it.id, false); showToast && showToast(it.name + ' disconnected'); } }}>Disconnect</button>
                          </div>
                        ) : (
                          <button className="btn sm primary" disabled={!isAdmin} style={{ justifyContent: 'center' }} onClick={() => setConnecting(it)}>
                            <Icon name="spark" size={12}/> Connect
                          </button>
                        )}
                      </div>
                    );
                  })}
                </div>
              </div>
            ))}
          </div>
        )}

        {tab === 'api' && (
          <Panel title="API & webhooks" sub="Build your own integrations on the Pearler API">
            <SettingRow label="API key" desc="Use this secret to authenticate REST API requests">
              <span className="mono" style={{ fontSize: 12 }}>{revealKey ? 'pk_live_8f2c_4a91_d77Q2a' : s.apiKey}</span>
              <button className="btn sm" onClick={() => setRevealKey(v => !v)}>{revealKey ? 'Hide' : 'Reveal'}</button>
              <button className="btn sm" onClick={() => showToast && showToast('New API key generated — old key revoked')}>Regenerate</button>
            </SettingRow>
            <SettingRow label="Rate limit" desc="Requests per minute on your current plan"><span className="num" style={{ fontWeight: 600 }}>600 / min</span></SettingRow>
            <div style={{ paddingTop: 14 }}>
              <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 8 }}>Webhook endpoints</div>
              <WebhookEditor webhooks={s.webhooks || []} onChange={(arr) => onChange('webhooks', null, arr)} disabled={!isAdmin}/>
            </div>
            <div style={{ marginTop: 12, fontSize: 11.5, color: 'var(--ink-3)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <Icon name="spark" size={12} color="var(--accent)"/> Full REST &amp; GraphQL docs at <strong>developers.pearler.app</strong>
            </div>
          </Panel>
        )}
      </div>

      {connecting && (
        <ConnectModal
          integration={connecting}
          onClose={() => setConnecting(null)}
          onConnect={(payload) => { onChange('integrations', connecting.id, { connected: true, ...payload }); showToast && showToast(connecting.name + ' connected'); setConnecting(null); }}
        />
      )}
      {twofaOpen && (
        <Authenticator2FA
          account={currentUser.email || currentUser.name}
          issuer={(settings.org && settings.org.name) || 'Pearler CRM'}
          existingSecret={s.security.twofaSecret}
          onClose={() => setTwofaOpen(false)}
          onEnrolled={(secret) => { onChange('security', 'twofaSecret', secret); onChange('security', 'twofaEnrolled', true); showToast && showToast('Authenticator verified & enabled'); setTwofaOpen(false); }}
        />
      )}
    </div>
  );
}

function Panel({ title, sub, children }) {
  return (
    <div className="card">
      <div className="card-hd">
        <div>
          <div className="card-title">{title}</div>
          {sub && <div className="card-sub">{sub}</div>}
        </div>
      </div>
      <div className="card-pad" style={{ paddingTop: 4, paddingBottom: 4 }}>{children}</div>
    </div>
  );
}

function WebhookEditor({ webhooks, onChange, disabled }) {
  const [url, setUrl] = React.useState('');
  const [evt, setEvt] = React.useState('deal.won');
  const EVENTS = ['deal.created', 'deal.won', 'deal.lost', 'contact.created', 'reminder.due'];
  const add = () => { if (!/^https?:\/\//.test(url)) return; onChange([...(webhooks || []), { id: 'wh' + Date.now(), url: url.trim(), event: evt }]); setUrl(''); };
  return (
    <div>
      {webhooks.length === 0 && <div style={{ fontSize: 12, color: 'var(--ink-4)', marginBottom: 8 }}>No endpoints yet.</div>}
      {webhooks.map(w => (
        <div key={w.id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '7px 10px', border: '1px solid var(--border)', borderRadius: 6, marginBottom: 6 }}>
          <span className="pill" style={{ fontSize: 10 }}>{w.event}</span>
          <span className="mono" style={{ fontSize: 11.5, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{w.url}</span>
          {!disabled && <button className="btn icon sm" onClick={() => onChange(webhooks.filter(x => x.id !== w.id))}><Icon name="close" size={12}/></button>}
        </div>
      ))}
      {!disabled && (
        <div style={{ display: 'flex', gap: 6, marginTop: 6 }}>
          <select className="sel" value={evt} onChange={(e) => setEvt(e.target.value)}>{EVENTS.map(ev => <option key={ev} value={ev}>{ev}</option>)}</select>
          <input value={url} onChange={(e) => setUrl(e.target.value)} placeholder="https://your-app.com/webhook" className="mono" style={{ flex: 1, fontSize: 12 }}/>
          <button className="btn sm primary" onClick={add}><Icon name="plus" size={11}/> Add</button>
        </div>
      )}
    </div>
  );
}

// Connection flow modal — mirrors how real CRMs connect: OAuth consent, API-key entry, or Zapier.
function ConnectModal({ integration, onClose, onConnect }) {
  const it = integration;
  const auth = it.auth || 'oauth';
  const [phase, setPhase] = React.useState('form'); // form | connecting
  const [fields, setFields] = React.useState({});
  const [account, setAccount] = React.useState('');
  const popupRef = React.useRef(null);
  const pollRef = React.useRef(null);
  const doneRef = React.useRef(false);

  React.useEffect(() => {
    const onMsg = (e) => {
      const d = e.data || {};
      if (d.type === 'pearler-oauth' && d.id === it.id) {
        doneRef.current = true;
        if (pollRef.current) clearInterval(pollRef.current);
        if (d.approved) {
          setPhase('connecting');
          setTimeout(() => onConnect({ method: 'OAuth 2.0', account: d.account || account || ('you@' + it.id + '.com'), connectedAt: new Date().toISOString().slice(0, 10) }), 700);
        } else {
          setPhase('cancelled');
        }
      }
    };
    window.addEventListener('message', onMsg);
    return () => { window.removeEventListener('message', onMsg); if (pollRef.current) clearInterval(pollRef.current); };
  }, [it.id, account]);

  const startOAuth = () => {
    doneRef.current = false;
    const acct = account || ('you@' + it.id + '.com');
    const w = window.open('', 'pearler_oauth_' + it.id, 'width=470,height=680,menubar=no,toolbar=no,location=no');
    if (!w) { setPhase('blocked'); return; }
    popupRef.current = w;
    w.document.open();
    w.document.write(buildOAuthPage(it, acct));
    w.document.close();
    setPhase('awaiting');
    pollRef.current = setInterval(() => {
      if (w.closed) { clearInterval(pollRef.current); if (!doneRef.current) setPhase('cancelled'); }
    }, 600);
  };
  const submitKey = () => {
    const filled = (it.fields || []).every(f => (fields[f.key] || '').trim());
    if (!filled) return;
    setPhase('connecting');
    setTimeout(() => onConnect({ method: 'API key', account: (it.fields[0] && fields[it.fields[0].key]) ? String(fields[it.fields[0].key]).slice(0, 10) + '…' : 'API key', connectedAt: new Date().toISOString().slice(0, 10) }), 900);
  };

  return (
    <div>
      <div className="detail-overlay" onClick={onClose} style={{ zIndex: 60 }}/>
      <div className="invite-modal" style={{ zIndex: 61, width: 460 }}>
        <div style={{ padding: '18px 22px 14px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 12 }}>
          <span style={{ width: 38, height: 38, borderRadius: 10, background: it.color, color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 17 }}>{it.mono}</span>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 16, fontWeight: 600 }}>Connect {it.name}</div>
            <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>{auth === 'oauth' ? 'Secure sign-in via ' + it.name : auth === 'apikey' ? 'Enter your API credentials' : 'Connect via Zapier'}</div>
          </div>
          <button className="detail-close" onClick={onClose}><Icon name="close" size={16}/></button>
        </div>

        <div style={{ padding: '20px 22px' }}>
          {phase === 'connecting' ? (
            <div style={{ textAlign: 'center', padding: '20px 0' }}>
              <div className="auth-spinner" style={{ margin: '0 auto 14px' }}></div>
              <div style={{ fontSize: 13, fontWeight: 500 }}>Finishing connection to {it.name}…</div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 4 }}>Exchanging tokens &amp; establishing a secure sync</div>
            </div>
          ) : phase === 'awaiting' ? (
            <div style={{ textAlign: 'center', padding: '14px 0' }}>
              <div className="auth-spinner" style={{ margin: '0 auto 14px' }}></div>
              <div style={{ fontSize: 13, fontWeight: 500 }}>Waiting for you to approve in the {it.name} window…</div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 4 }}>Approve or deny access in the pop-up that opened.</div>
              <div style={{ display: 'flex', gap: 8, justifyContent: 'center', marginTop: 16 }}>
                <button className="btn sm" onClick={() => { if (popupRef.current && !popupRef.current.closed) popupRef.current.focus(); else startOAuth(); }}>Reopen window</button>
                <button className="btn sm" onClick={() => { if (popupRef.current && !popupRef.current.closed) popupRef.current.close(); setPhase('form'); }}>Cancel</button>
              </div>
            </div>
          ) : phase === 'blocked' ? (
            <div style={{ textAlign: 'center', padding: '14px 0' }}>
              <Icon name="alert" size={22} color="var(--lost)"/>
              <div style={{ fontSize: 13, fontWeight: 600, marginTop: 8 }}>Pop-up blocked</div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 4 }}>Allow pop-ups for this site, then try again.</div>
              <button className="btn primary" style={{ marginTop: 14 }} onClick={startOAuth}>Try again</button>
            </div>
          ) : phase === 'cancelled' ? (
            <div style={{ textAlign: 'center', padding: '14px 0' }}>
              <Icon name="alert" size={22} color="var(--warn)"/>
              <div style={{ fontSize: 13, fontWeight: 600, marginTop: 8 }}>Authorisation not completed</div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 4 }}>You closed or denied the {it.name} window — nothing was connected.</div>
              <button className="btn primary" style={{ marginTop: 14 }} onClick={startOAuth}>Try again</button>
            </div>
          ) : auth === 'oauth' ? (
            <div>
              <div style={{ border: '1px solid var(--border)', borderRadius: 'var(--r-md)', padding: '14px 16px', background: 'var(--surface-2)' }}>
                <div style={{ fontSize: 12.5, fontWeight: 600, marginBottom: 8 }}>Pearler will ask {it.name} for permission to:</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                  {(it.scopes || ['Access your account data']).map((sc, i) => (
                    <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--ink-2)' }}>
                      <Icon name="check" size={13} color="var(--won)"/> {sc}
                    </div>
                  ))}
                </div>
              </div>
              <div className="detail-field" style={{ marginTop: 14 }}>
                <span className="lbl">{it.name} account</span>
                <input value={account} onChange={(e) => setAccount(e.target.value)} placeholder={'you@' + it.id + '.com'} className="mono"/>
              </div>
              <button className="btn primary" style={{ width: '100%', justifyContent: 'center', marginTop: 14 }} onClick={startOAuth}>
                <Icon name="lock" size={12}/> Continue to {it.name}
              </button>
              <div style={{ fontSize: 10.5, color: 'var(--ink-4)', textAlign: 'center', marginTop: 8 }}>Opens {it.name} in a secure window — you approve there. Pearler never sees your password.</div>
            </div>
          ) : auth === 'zapier' ? (
            <div>
              <ol style={{ margin: 0, paddingLeft: 18, fontSize: 12.5, color: 'var(--ink-2)', lineHeight: 1.7 }}>
                <li>Open Zapier and create a new Zap.</li>
                <li>Choose <strong>Pearler CRM</strong> as the trigger or action app.</li>
                <li>Paste your API key (Settings → API &amp; Webhooks) when prompted.</li>
              </ol>
              <button className="btn primary" style={{ width: '100%', justifyContent: 'center', marginTop: 16 }} onClick={() => { setPhase('connecting'); setTimeout(() => onConnect({ method: 'Zapier', account: 'via Zapier', connectedAt: new Date().toISOString().slice(0, 10) }), 800); }}>
                <Icon name="spark" size={12}/> I’ve connected it in Zapier
              </button>
            </div>
          ) : (
            <div>
              {(it.fields || []).map(f => (
                <div className="detail-field" key={f.key} style={{ marginBottom: 12 }}>
                  <span className="lbl">{f.label}</span>
                  <input type={f.secret ? 'password' : 'text'} value={fields[f.key] || ''} onChange={(e) => setFields(p => ({ ...p, [f.key]: e.target.value }))} placeholder={f.placeholder} className="mono"/>
                </div>
              ))}
              <button className="btn primary" style={{ width: '100%', justifyContent: 'center', marginTop: 4 }} onClick={submitKey}>
                <Icon name="lock" size={12}/> Connect securely
              </button>
              <div style={{ fontSize: 10.5, color: 'var(--ink-4)', textAlign: 'center', marginTop: 8 }}>Credentials are encrypted at rest. Find these in your {it.name} dashboard.</div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// Builds the simulated provider authorization page (rendered in the OAuth pop-up).
function buildOAuthPage(it, acct) {
  const esc = (str) => String(str).replace(/[<>&"']/g, (c) => ({ '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', "'": '&#39;' }[c]));
  const scopes = (it.scopes || ['Access your account data']).map((sc) => '<li>' + esc(sc) + '</li>').join('');
  return '<!DOCTYPE html><html><head><meta charset="utf-8"><title>Sign in · ' + esc(it.name) + '</title><meta name="viewport" content="width=device-width,initial-scale=1">'
    + '<style>*{box-sizing:border-box;font-family:-apple-system,Segoe UI,Helvetica,Arial,sans-serif}'
    + 'body{margin:0;background:#f1f3f4;color:#202124;display:flex;min-height:100vh;align-items:center;justify-content:center;padding:18px}'
    + '.card{background:#fff;border:1px solid #dadce0;border-radius:12px;max-width:400px;width:100%;padding:26px 30px;box-shadow:0 1px 4px rgba(0,0,0,.12)}'
    + '.brand{display:flex;align-items:center;gap:10px;margin-bottom:16px}.logo{width:36px;height:36px;border-radius:9px;background:' + it.color + ';color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:18px}'
    + 'h1{font-size:17px;font-weight:500;margin:0 0 4px}.sub{font-size:13px;color:#5f6368;margin-bottom:16px}'
    + '.acct{display:flex;align-items:center;gap:10px;border:1px solid #dadce0;border-radius:8px;padding:9px 12px;margin-bottom:16px}.acct input{border:none;outline:none;font-size:14px;flex:1;background:none}'
    + '.perms{font-size:13px;color:#3c4043;margin:0 0 6px}ul{margin:0 0 16px;padding-left:18px;font-size:13px;color:#5f6368;line-height:1.7}'
    + '.row{display:flex;justify-content:flex-end;gap:8px;margin-top:8px}button{font:inherit;font-size:14px;font-weight:500;padding:9px 18px;border-radius:8px;cursor:pointer;border:1px solid transparent}'
    + '.ghost{background:none;color:#1a73e8}.primary{background:#1a73e8;color:#fff}.foot{font-size:11px;color:#80868b;margin-top:16px;text-align:center}</style></head><body>'
    + '<div class="card"><div class="brand"><span class="logo">' + esc(it.mono) + '</span><div><div style="font-size:12px;color:#5f6368">Sign in with</div><div style="font-weight:600">' + esc(it.name) + '</div></div></div>'
    + '<h1>Pearler CRM wants to access your ' + esc(it.name) + ' account</h1><div class="sub">Choose an account to continue</div>'
    + '<div class="acct"><span class="logo" style="width:26px;height:26px;font-size:12px;background:#5f6368">' + esc((acct[0] || 'U').toUpperCase()) + '</span><input id="acct" value="' + esc(acct) + '"/></div>'
    + '<div class="perms">This will allow Pearler to:</div><ul>' + scopes + '</ul>'
    + '<div class="row"><button class="ghost" onclick="send(false)">Cancel</button><button class="primary" onclick="send(true)">Allow</button></div>'
    + '<div class="foot">You can revoke access any time in your ' + esc(it.name) + ' security settings.</div></div>'
    + '<scr' + 'ipt>function send(ok){try{window.opener&&window.opener.postMessage({type:"pearler-oauth",id:"' + esc(it.id) + '",approved:ok,account:document.getElementById("acct").value},"*");}catch(e){}window.close();}</scr' + 'ipt>'
    + '</body></html>';
}

// Authenticator (TOTP) enrolment — QR + manual key + live code verification.
// In LIVE mode (Supabase present) this enrols a real MFA factor with Supabase
// so the sign-in flow will actually challenge for it. In DEMO mode it falls
// back to a self-contained local TOTP so the UX can still be explored.
function Authenticator2FA({ account, issuer, existingSecret, onClose, onEnrolled }) {
  const isLive = !!(window.sb && window.STAGEVO_BACKEND === 'live' && window.sb.auth && window.sb.auth.mfa);

  const [code, setCode] = React.useState('');
  const [status, setStatus] = React.useState(null); // null | 'ok' | 'bad'
  const [reveal, setReveal] = React.useState(false);
  const [liveCode, setLiveCode] = React.useState('');
  const [secs, setSecs] = React.useState(30);
  const [verifying, setVerifying] = React.useState(false);

  // Live-mode enrolment state
  const [enrolling, setEnrolling] = React.useState(isLive);
  const [enrollErr, setEnrollErr] = React.useState(null);
  const [factorId, setFactorId] = React.useState(null);
  const [qrDataUri, setQrDataUri] = React.useState('');   // Supabase returns an SVG data-URI
  const [secret, setSecret] = React.useState(() => isLive ? '' : (existingSecret || (window.TOTP ? window.TOTP.newSecret() : '')));

  const qrRef = React.useRef(null);
  const demoUri = (!isLive && window.TOTP) ? window.TOTP.otpauthURI(secret, account, issuer) : '';

  // ── LIVE: enrol a real Supabase TOTP factor on open ────────────────────
  React.useEffect(() => {
    if (!isLive) return;
    let alive = true;
    (async () => {
      try {
        setEnrolling(true); setEnrollErr(null);
        // Clean up any half-finished (unverified) factors from a previous attempt.
        try {
          const list = await window.sb.auth.mfa.listFactors();
          const stale = (list.data && list.data.all || []).filter(f => f.factor_type === 'totp' && f.status !== 'verified');
          for (const f of stale) { try { await window.sb.auth.mfa.unenroll({ factorId: f.id }); } catch (e) {} }
        } catch (e) {}

        const { data, error } = await window.sb.auth.mfa.enroll({
          factorType: 'totp',
          friendlyName: 'Authenticator ' + new Date().toISOString().slice(0, 10),
        });
        if (error) throw error;
        if (!alive) return;
        setFactorId(data.id);
        setSecret((data.totp && data.totp.secret) || '');
        setQrDataUri((data.totp && data.totp.qr_code) || '');
        setEnrolling(false);
      } catch (e) {
        if (!alive) return;
        setEnrollErr(e.message || String(e));
        setEnrolling(false);
      }
    })();
    return () => { alive = false; };
  }, [isLive]);

  // ── DEMO: render QR from the local otpauth URI ─────────────────────────
  React.useEffect(() => {
    if (isLive) return;
    if (window.qrcode && qrRef.current && demoUri) {
      try {
        const qr = window.qrcode(0, 'M');
        qr.addData(demoUri);
        qr.make();
        qrRef.current.innerHTML = qr.createSvgTag({ cellSize: 5, margin: 8, scalable: true });
        const svg = qrRef.current.querySelector('svg');
        if (svg) { svg.style.width = '170px'; svg.style.height = '170px'; }
      } catch (e) { qrRef.current.textContent = 'QR unavailable — use the key below'; }
    }
  }, [demoUri, isLive]);

  // Live preview of the current code — only meaningful when we hold the secret.
  React.useEffect(() => {
    let alive = true;
    const tick = async () => {
      if (!window.TOTP || !alive || !secret) return;
      try { setLiveCode(await window.TOTP.now(secret)); } catch (e) {}
      setSecs(window.TOTP.secondsRemaining(30));
    };
    tick();
    const id = setInterval(tick, 1000);
    return () => { alive = false; clearInterval(id); };
  }, [secret]);

  const verify = async () => {
    if (code.length !== 6) return;
    setVerifying(true); setStatus(null);
    try {
      if (isLive) {
        if (!factorId) throw new Error('Enrolment not ready');
        const ch = await window.sb.auth.mfa.challenge({ factorId });
        if (ch.error) throw ch.error;
        const res = await window.sb.auth.mfa.verify({ factorId, challengeId: ch.data.id, code });
        if (res.error) { setStatus('bad'); setVerifying(false); return; }
        setStatus('ok');
        setTimeout(() => onEnrolled(secret || 'live'), 600);
      } else {
        const ok = window.TOTP ? await window.TOTP.verify(secret, code) : false;
        setStatus(ok ? 'ok' : 'bad');
        if (ok) setTimeout(() => onEnrolled(secret), 600);
      }
    } catch (e) {
      setStatus('bad');
    }
    setVerifying(false);
  };

  const grouped = (secret.match(/.{1,4}/g) || []).join(' ');

  return (
    <div>
      <div className="detail-overlay" onClick={onClose} style={{ zIndex: 60 }}/>
      <div className="invite-modal" style={{ zIndex: 61, width: 440 }}>
        <div style={{ padding: '16px 22px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 11 }}>
          <div style={{ width: 32, height: 32, borderRadius: 8, background: 'var(--accent-soft)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="lock" size={16} color="var(--accent-ink)"/></div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Set up authenticator app</div>
            <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>Google / Microsoft Authenticator, Authy, 1Password…</div>
          </div>
          {isLive && <span className="pill" style={{ background: 'var(--won-soft)', color: 'oklch(0.4 0.1 155)', marginRight: 4 }}>Secured by Supabase</span>}
          <button className="detail-close" onClick={onClose}><Icon name="close" size={16}/></button>
        </div>

        <div style={{ padding: '18px 22px' }}>
          {enrolling ? (
            <div style={{ padding: '40px 0', textAlign: 'center' }}>
              <div className="auth-spinner" style={{ margin: '0 auto 14px' }}></div>
              <div style={{ fontSize: 12.5, color: 'var(--ink-3)' }}>Generating your secure key…</div>
            </div>
          ) : enrollErr ? (
            <div style={{ padding: '24px 0', textAlign: 'center' }}>
              <Icon name="alert" size={22} color="var(--lost)"/>
              <div style={{ fontSize: 13, color: 'var(--lost)', marginTop: 10, lineHeight: 1.5 }}>Couldn't start enrolment:<br/>{enrollErr}</div>
              <button className="btn sm" style={{ marginTop: 12 }} onClick={onClose}>Close</button>
            </div>
          ) : (
            <React.Fragment>
              <div style={{ fontSize: 12.5, color: 'var(--ink-2)', marginBottom: 12 }}>1. Scan this QR code in your authenticator app:</div>
              <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 14 }}>
                {isLive ? (
                  <div style={{ width: 186, height: 186, background: 'white', border: '1px solid var(--border)', borderRadius: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 8 }}>
                    {qrDataUri
                      ? <img src={qrDataUri} alt="2FA QR code" style={{ width: 170, height: 170 }}/>
                      : <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>Use the key below</span>}
                  </div>
                ) : (
                  <div ref={qrRef} style={{ width: 186, height: 186, background: 'white', border: '1px solid var(--border)', borderRadius: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 8 }}></div>
                )}
              </div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 6 }}>Or enter this key manually:</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 18 }}>
                <span className="mono" style={{ flex: 1, fontSize: 13, letterSpacing: '0.04em', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, padding: '8px 10px', userSelect: 'all' }}>{reveal ? (grouped || '—') : '•••• •••• •••• ••••'}</span>
                <button className="btn sm" onClick={() => setReveal(r => !r)}>{reveal ? 'Hide' : 'Show'}</button>
              </div>

              <div style={{ fontSize: 12.5, color: 'var(--ink-2)', marginBottom: 8 }}>2. Enter the 6-digit code from your app to verify:</div>
              <div style={{ display: 'flex', gap: 8 }}>
                <input className="mono" value={code} onChange={(e) => { setCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setStatus(null); }}
                  placeholder="000000" style={{ flex: 1, letterSpacing: '0.35em', textAlign: 'center', fontSize: 18, padding: '8px', border: '1px solid ' + (status === 'bad' ? 'var(--lost)' : 'var(--border-strong)'), borderRadius: 6 }}/>
                <button className="btn primary" disabled={code.length !== 6 || verifying} style={{ opacity: (code.length === 6 && !verifying) ? 1 : 0.5 }} onClick={verify}><Icon name="check" size={12}/> {verifying ? 'Verifying…' : 'Verify'}</button>
              </div>
              {status === 'ok' && <div style={{ fontSize: 12, color: 'var(--won)', marginTop: 8, display: 'flex', alignItems: 'center', gap: 5 }}><Icon name="check" size={12}/> Verified — authenticator enabled.</div>}
              {status === 'bad' && <div style={{ fontSize: 12, color: 'var(--lost)', marginTop: 8 }}>That code didn’t match. Check your app and try again.</div>}

              {secret && (
                <details style={{ marginTop: 14 }}>
                  <summary style={{ cursor: 'pointer', fontSize: 11, color: 'var(--ink-3)' }}>No phone handy? Show current code (testing)</summary>
                  <div style={{ marginTop: 8, display: 'flex', alignItems: 'center', gap: 10, background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 6, padding: '8px 12px' }}>
                    <span className="mono" style={{ fontSize: 18, fontWeight: 700, letterSpacing: '0.2em' }}>{liveCode || '••••••'}</span>
                    <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>refreshes in {secs}s</span>
                    <button className="btn sm" style={{ marginLeft: 'auto' }} onClick={() => setCode(liveCode)}>Use</button>
                  </div>
                </details>
              )}
            </React.Fragment>
          )}
        </div>
      </div>
    </div>
  );
}

window.Settings = Settings;