/* global React */
// Settings page with sections: Personal / Notifications / Users & Permissions / System / Security

function SettingsPage({ role = 'super-admin' }) {
  const isSuper = role === 'super-admin';
  const sections = [
    { id: 'personal', label: '个人偏好', icon: 'user',  visible: true },
    { id: 'notify',   label: '通知',     icon: 'bell',  visible: true },
    { id: 'users',    label: '用户与权限', icon: 'user', visible: isSuper, badge: '主管理员' },
    { id: 'system',   label: '系统配置',   icon: 'settings', visible: isSuper, badge: '主管理员' },
    { id: 'security', label: '安全 / 审计', icon: 'shield', visible: isSuper, badge: '主管理员' },
  ].filter((s) => s.visible);
  const [section, setSection] = React.useState(isSuper ? 'users' : 'personal');

  return (
    <div>
      <div className="page-header">
        <div>
          <div className="breadcrumb"><span>系统</span><span className="sep">/</span><span>设置</span></div>
          <h1 className="page-title">设置</h1>
          <div className="page-subtitle">
            {isSuper ? '管理你自己的偏好,以及所有管理员的账号与权限' : '管理你自己的偏好与通知'}
          </div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '220px 1fr', gap: 24, alignItems: 'flex-start' }}>
        <aside style={{ position: 'sticky', top: 16 }}>
          {sections.map((s) => {
            const Icon = window.I[s.icon];
            const active = section === s.id;
            return (
              <button key={s.id} onClick={() => setSection(s.id)} style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '8px 12px', width: '100%',
                borderRadius: 'var(--r-md)',
                background: active ? 'var(--surface)' : 'transparent',
                border: active ? '1px solid var(--border)' : '1px solid transparent',
                color: active ? 'var(--text)' : 'var(--text-2)',
                textAlign: 'left', marginBottom: 2,
                fontSize: 13, fontWeight: active ? 500 : 400,
                boxShadow: active ? 'var(--shadow-sm)' : 'none',
              }}>
                {Icon && <Icon size={16} style={{ color: active ? 'var(--indigo)' : 'var(--text-3)' }}/>}
                <span style={{ flex: 1 }}>{s.label}</span>
                {s.badge && (
                  <span style={{
                    fontSize: 9, padding: '1px 6px',
                    background: 'var(--surface-2)', border: '1px solid var(--border)',
                    color: 'var(--text-3)', borderRadius: 'var(--r-pill)',
                  }}>仅主管</span>
                )}
              </button>
            );
          })}
        </aside>

        <div>
          {section === 'personal' && <PersonalSection/>}
          {section === 'notify'   && <NotifySection/>}
          {section === 'users'    && <UsersSection role={role}/>}
          {section === 'system'   && <SystemSection/>}
          {section === 'security' && <SecuritySection/>}
        </div>
      </div>
    </div>
  );
}

// ─── Personal ────────────────────────────────────────────────
function PersonalSection() {
  return (
    <>
      <SettingsCard title="账号" subtitle="你的基本资料">
        <SettingRowEdit label="姓名"   defaultValue="主管理员"/>
        <SettingRowEdit label="邮箱"   defaultValue="admin@pokeking.icu" mono disabled/>
        <SettingRowEdit label="语言"   defaultValue="中文 (简体)"/>
        <SettingRowEdit label="时区"   defaultValue="Asia/Shanghai (UTC+8)"/>
      </SettingsCard>

      <SettingsCard title="外观" subtitle="主题和密度可在右下角 Tweaks 实时切换">
        <SettingRow label="主题"     value="跟随系统"/>
        <SettingRow label="字号"     value="14px (默认)"/>
        <SettingRow label="日期格式" value="2026-05-19 14:32"/>
        <SettingRow label="默认首页" value="仪表盘"/>
      </SettingsCard>

      <SettingsCard title="键盘" subtitle="快捷键 cheatsheet 在按 ? 时打开">
        <SettingRow label="启用 vim 风格导航"   value="开启"/>
        <SettingRow label="启用 Cmd+K 命令面板" value="开启"/>
      </SettingsCard>
    </>
  );
}

function NotifySection() {
  return (
    <SettingsCard title="通知偏好" subtitle="决定哪些事件出现在右上角铃铛 / 推送邮件">
      {[
        ['新提交进入审核台',  'app',  'email'],
        ['抓取失败',          'app',  'email'],
        ['部署失败',          'app',  'email'],
        ['新用户反馈',        'app',  null],
        ['暂存超过 24 小时未发布', 'app', null],
        ['每日审核摘要',       null,   'email'],
      ].map(([label, app, email]) => (
        <div key={label} className="hstack" style={{ padding: '10px 0', borderBottom: '1px solid var(--border)' }}>
          <span style={{ flex: 1, fontSize: 13 }}>{label}</span>
          <ToggleChip on={!!app}>站内</ToggleChip>
          <ToggleChip on={!!email}>邮件</ToggleChip>
        </div>
      ))}
    </SettingsCard>
  );
}

// ─── User Management ─────────────────────────────────────────
function UsersSection({ role }) {
  const [users, setUsers] = React.useState(window.MOCK.ADMIN_USERS);
  const [search, setSearch] = React.useState('');
  const [editing, setEditing] = React.useState(null);
  const [inviting, setInviting] = React.useState(false);

  const reload = React.useCallback(() => {
    window.API.users().then((r) => {
      if (r?.items?.length) {
        setUsers(r.items.map((u) => ({
          id: 'u' + u.id, _id: u.id, email: u.email, name: u.name, role: u.role,
          status: u.status,
          last_login: u.last_login_at ? new Date(u.last_login_at).toLocaleString('zh-CN', { hour12: false }) : '—',
          ip: u.last_login_ip || '—',
          created: u.created_at ? new Date(u.created_at).toLocaleDateString('zh-CN') : '—',
          is_self: false,
          actions: null,
        })));
      }
    }).catch(() => {});
  }, []);
  React.useEffect(reload, [reload]);

  const filtered = users.filter((u) =>
    !search ||
    u.name.includes(search) ||
    u.email.toLowerCase().includes(search.toLowerCase()) ||
    u.role.includes(search)
  );

  const updateRole = (id, newRole) => {
    setUsers(users.map((u) => u.id === id ? { ...u, role: newRole } : u));
    setEditing(null);
  };
  const setStatus = (id, status) => {
    setUsers(users.map((u) => u.id === id ? { ...u, status } : u));
  };

  const counts = {
    'super-admin': users.filter((u) => u.role === 'super-admin' && u.status === 'active').length,
    'editor':      users.filter((u) => u.role === 'editor' && u.status === 'active').length,
    'reviewer':    users.filter((u) => u.role === 'reviewer' && u.status === 'active').length,
    invited:       users.filter((u) => u.status === 'invited').length,
  };

  return (
    <>
      {/* Role summary */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginBottom: 16 }}>
        <RoleCount role="super-admin" count={counts['super-admin']}/>
        <RoleCount role="editor"      count={counts['editor']}/>
        <RoleCount role="reviewer"    count={counts['reviewer']}/>
        <RoleCount role="invited"     count={counts['invited']} label="待接受邀请"/>
      </div>

      <div className="card" style={{ padding: 0 }}>
        <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--border)', display:'flex', alignItems:'center', gap: 12 }}>
          <div style={{ position:'relative', flex: 1, maxWidth: 320 }}>
            <window.I.search size={13} style={{ position:'absolute', left: 10, top: 11, color: 'var(--text-3)' }}/>
            <input className="input" placeholder="搜索姓名 / 邮箱 / 角色"
                   style={{ paddingLeft: 30, height: 32 }}
                   value={search} onChange={(e) => setSearch(e.target.value)}/>
          </div>
          <span className="muted" style={{ fontSize: 12 }}>{filtered.length} 位用户</span>
          <div style={{ flex: 1 }}/>
          <window.Btn size="sm" icon={<window.I.download size={12}/>}>导出</window.Btn>
          <window.Btn size="sm" kind="primary" icon={<window.I.plus size={12}/>}
                      onClick={() => setInviting(true)}>邀请管理员</window.Btn>
        </div>

        <table className="table">
          <thead>
            <tr>
              <th>用户</th>
              <th style={{ width: 110 }}>角色</th>
              <th style={{ width: 92 }}>状态</th>
              <th style={{ width: 200 }}>近 7 天活跃</th>
              <th style={{ width: 100 }}>最后登录</th>
              <th style={{ width: 60 }}></th>
            </tr>
          </thead>
          <tbody>
            {filtered.map((u) => <UserRow key={u.id} u={u}
                                          onChangeRole={() => setEditing(u)}
                                          onRevoke={() => setStatus(u.id, 'revoked')}
                                          onReactivate={() => setStatus(u.id, 'active')}
                                          onResend={() => {}}/>)}
          </tbody>
        </table>

        <div style={{ padding: '10px 16px', borderTop: '1px solid var(--border)', fontSize: 12, color: 'var(--text-3)' }}>
          权限变更会立即生效,目标用户下次操作时若不再具备权限会被踢回登录页。所有变更进入操作日志。
        </div>
      </div>

      <SettingsCard title="角色定义" subtitle="后台共三种内置角色,粒度足够覆盖日常运营">
        <RoleDefRow role="super-admin"/>
        <RoleDefRow role="editor"/>
        <RoleDefRow role="reviewer"/>
        <div style={{ marginTop: 10, padding: 10, background: 'var(--surface-2)', borderRadius:'var(--r-md)', fontSize: 12, color: 'var(--text-2)' }}>
          <window.I.info size={13} style={{ verticalAlign: 'middle', marginRight: 6 }}/>
          自定义角色 / 粒度授权(模块级开关)在 v2 规划中。
        </div>
      </SettingsCard>

      {editing && (
        <RoleEditDialog user={editing} role={role}
                        onClose={() => setEditing(null)}
                        onSave={(r) => updateRole(editing.id, r)}/>
      )}
      {inviting && <InviteDialog onClose={() => setInviting(false)}/>}
    </>
  );
}

function RoleCount({ role, count, label }) {
  if (role === 'invited') {
    return (
      <div className="card" style={{ padding: 14 }}>
        <div className="muted" style={{ fontSize: 11, marginBottom: 6 }}>{label || '待接受邀请'}</div>
        <div style={{ fontSize: 22, fontWeight: 600 }}>{count}</div>
        <div className="muted" style={{ fontSize: 11, marginTop: 4 }}>邀请 7 天内有效</div>
      </div>
    );
  }
  const r = window.ROLES[role];
  return (
    <div className="card" style={{ padding: 14 }}>
      <div className="hstack" style={{ marginBottom: 6 }}>
        <window.RoleDot role={role}/>
        <span className="muted" style={{ fontSize: 12 }}>{r.label}</span>
      </div>
      <div style={{ fontSize: 22, fontWeight: 600 }}>{count}</div>
      <div className="muted" style={{ fontSize: 11, marginTop: 4 }}>活跃账号</div>
    </div>
  );
}

function ActStat({ color, symbol, n }) {
  const dim = !n;
  return (
    <span style={{
      color: dim ? 'var(--text-3)' : color,
      opacity: dim ? .4 : 1,
      display: 'inline-flex', alignItems: 'baseline', gap: 2,
    }}>
      <span style={{ fontWeight: 600 }}>{symbol}</span>
      <span>{n || 0}</span>
    </span>
  );
}

function UserRow({ u, onChangeRole, onRevoke, onReactivate, onResend }) {
  const r = window.ROLES[u.role];
  const acts = u.actions?.last7d;
  return (
    <tr>
      <td>
        <div className="hstack" style={{ gap: 12 }}>
          <span className="avatar" style={{
            width: 32, height: 32, fontSize: 12,
            background: `linear-gradient(135deg, ${r.color}, ${r.color}88)`,
          }}>{u.name[0]}</span>
          <div>
            <div style={{ fontWeight: 500, display:'flex', alignItems:'center', gap: 6 }}>
              {u.name}
              {u.is_self && <span style={{
                fontSize: 10, padding: '1px 5px',
                background: 'var(--surface-2)', border: '1px solid var(--border)',
                borderRadius: 'var(--r-pill)', color: 'var(--text-3)',
              }}>你</span>}
            </div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--text-3)' }}>{u.email}</div>
          </div>
        </div>
      </td>
      <td><window.RolePill role={u.role}/></td>
      <td>
        {u.status === 'active'   && <window.Pill status="approved">活跃</window.Pill>}
        {u.status === 'invited'  && <window.Pill status="pending">待接受</window.Pill>}
        {u.status === 'revoked'  && <window.Pill status="rejected">已停用</window.Pill>}
      </td>
      <td>
        {acts ? (
          <div style={{
            display: 'inline-flex', gap: 6, whiteSpace: 'nowrap',
            fontSize: 11, fontFamily: 'var(--font-mono)',
            alignItems: 'center',
          }}>
            <ActStat color="var(--success)" symbol="✓" n={acts.approve}/>
            <ActStat color="var(--danger)"  symbol="✗" n={acts.reject}/>
            <ActStat color="var(--warning)" symbol="~" n={acts.edit}/>
            <ActStat color="var(--indigo)"  symbol="↑" n={acts.publish}/>
            {acts.approve + acts.reject + acts.edit + acts.publish === 0 && <span className="dim">—</span>}
          </div>
        ) : <span className="dim">—</span>}
      </td>
      <td className="muted" style={{ fontSize: 12 }}>{u.last_login}</td>
      <td>
        <div style={{ display:'flex', gap: 4, justifyContent:'flex-end' }}>
          {u.status === 'invited' ? (
            <window.Btn size="xs" onClick={onResend}>重发邀请</window.Btn>
          ) : u.status === 'revoked' ? (
            <window.Btn size="xs" onClick={onReactivate}>恢复</window.Btn>
          ) : (
            <RowMenu u={u} onChangeRole={onChangeRole} onRevoke={onRevoke}/>
          )}
        </div>
      </td>
    </tr>
  );
}

function RowMenu({ u, onChangeRole, onRevoke }) {
  const [open, setOpen] = React.useState(false);
  React.useEffect(() => {
    if (!open) return;
    const close = () => setOpen(false);
    document.addEventListener('click', close);
    return () => document.removeEventListener('click', close);
  }, [open]);
  return (
    <div style={{ position: 'relative' }} onClick={(e) => e.stopPropagation()}>
      <button className="btn icon xs" onClick={() => setOpen(!open)}>
        <span style={{ fontSize: 16, lineHeight: 1 }}>···</span>
      </button>
      {open && (
        <div style={{
          position:'absolute', right: 0, top: '100%', marginTop: 4,
          background: 'var(--surface)', border:'1px solid var(--border)',
          borderRadius: 'var(--r-md)', boxShadow: 'var(--shadow-pop)',
          minWidth: 160, zIndex: 10, padding: 4,
        }}>
          <MenuItem onClick={() => { onChangeRole(); setOpen(false); }}>
            <window.I.shield size={13}/> 修改角色
          </MenuItem>
          <MenuItem onClick={() => setOpen(false)}>
            <window.I.list size={13}/> 查看操作记录
          </MenuItem>
          <MenuItem onClick={() => setOpen(false)}>
            <window.I.refresh size={13}/> 重置密码邮件
          </MenuItem>
          <div style={{ height: 1, background: 'var(--border)', margin: 4 }}/>
          <MenuItem danger disabled={u.is_self}
                   onClick={() => { onRevoke(); setOpen(false); }}>
            <window.I.x size={13}/> 撤销访问
          </MenuItem>
        </div>
      )}
    </div>
  );
}
function MenuItem({ children, danger, disabled, onClick }) {
  return (
    <button onClick={disabled ? null : onClick} disabled={disabled} style={{
      display:'flex', alignItems:'center', gap: 8,
      width: '100%', padding: '6px 10px',
      fontSize: 13, textAlign:'left',
      borderRadius: 'var(--r-sm)',
      color: disabled ? 'var(--text-3)' : danger ? 'var(--danger)' : 'var(--text)',
      cursor: disabled ? 'not-allowed' : 'pointer',
    }}
    onMouseEnter={(e) => !disabled && (e.currentTarget.style.background = danger ? 'var(--danger-bg)' : 'var(--surface-2)')}
    onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
      {children}
    </button>
  );
}

function RoleDefRow({ role }) {
  const r = window.ROLES[role];
  const perms = window.PERMS[role];
  const access = Object.entries(perms).filter(([_, v]) => v).length;
  const writeAccess = Object.entries(perms).filter(([_, v]) => v === 'w').length;
  const descs = {
    'super-admin': '完全控制 - 含数据发布、系统配置、用户与权限。',
    'editor':      '可编辑数据/攻略/反馈,但无权发布与配置系统。',
    'reviewer':    '仅审核提交、浏览图鉴/攻略/反馈/日志,不可编辑。',
  };
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '160px 1fr auto',
      gap: 12, alignItems: 'center',
      padding: '12px 0', borderBottom: '1px solid var(--border)',
    }}>
      <div className="hstack">
        <window.RoleDot role={role}/>
        <span style={{ fontWeight: 500 }}>{r.label}</span>
      </div>
      <div className="muted" style={{ fontSize: 13 }}>{descs[role]}</div>
      <span className="mono" style={{ fontSize: 11, color: 'var(--text-3)' }}>
        访问 {access}/10 · 写入 {writeAccess}
      </span>
    </div>
  );
}

// ─── Role edit dialog ───────────────────────────────────────
function RoleEditDialog({ user, role, onClose, onSave }) {
  const [picked, setPicked] = React.useState(user.role);
  const r = window.ROLES[user.role];

  return (
    <div className="drawer-backdrop" onClick={onClose} style={{ display:'grid', placeItems:'center' }}>
      <div onClick={(e) => e.stopPropagation()} className="card" style={{ width: 520, animation: 'pop .14s ease' }}>
        <div className="card-header">
          <div>
            <div className="card-title">修改角色 · {user.name}</div>
            <div className="muted mono" style={{ fontSize: 11, marginTop: 4 }}>{user.email}</div>
          </div>
          <button className="icon-btn" onClick={onClose}><window.I.x size={14}/></button>
        </div>
        <div className="card-pad">
          <div className="muted" style={{ fontSize: 12, marginBottom: 10 }}>
            当前角色: <window.RolePill role={user.role}/>
          </div>
          {['super-admin','editor','reviewer'].map((rid) => (
            <RoleOption key={rid} role={rid}
                        picked={picked === rid}
                        onPick={() => setPicked(rid)}/>
          ))}
          {picked === 'super-admin' && (
            <div className="alert warn" style={{ marginTop: 12 }}>
              <window.I.alert size={16}/>
              <div>授予主管理员权限后,该用户将能管理其他管理员、修改系统配置、发布数据。请确认对方可信。</div>
            </div>
          )}
          {user.is_self && (
            <div className="alert danger" style={{ marginTop: 12 }}>
              <window.I.alert size={16}/>
              <div>你正在修改自己的角色。降级后将立刻失去对应权限,并可能锁住自己。</div>
            </div>
          )}
        </div>
        <div className="card-pad" style={{ paddingTop: 0, display:'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span className="muted" style={{ fontSize: 12 }}>变更会写入操作日志</span>
          <div className="hstack">
            <window.Btn onClick={onClose}>取消</window.Btn>
            <window.Btn kind="primary" disabled={picked === user.role}
                       onClick={() => onSave(picked)}>
              保存 → {window.ROLES[picked].label}
            </window.Btn>
          </div>
        </div>
      </div>
    </div>
  );
}

function RoleOption({ role, picked, onPick }) {
  const r = window.ROLES[role];
  const perms = window.PERMS[role];
  const writes = Object.keys(perms).filter((k) => perms[k] === 'w');
  const reads  = Object.keys(perms).filter((k) => perms[k] === 'r');
  const denied = Object.keys(perms).filter((k) => !perms[k]);
  const moduleLabel = (id) => window.NAV.find((n) => n.id === id)?.label || id;
  return (
    <button onClick={onPick} style={{
      display: 'block', width: '100%', textAlign: 'left',
      padding: 14,
      marginBottom: 8,
      border: `1px solid ${picked ? r.color : 'var(--border)'}`,
      borderRadius: 'var(--r-md)',
      background: picked ? window.hexAlpha(r.color, .04) : 'var(--surface)',
      boxShadow: picked ? `0 0 0 1px ${r.color}` : 'none',
    }}>
      <div className="hstack" style={{ marginBottom: 8 }}>
        <span style={{
          width: 16, height: 16, borderRadius: '50%',
          border: `1.5px solid ${picked ? r.color : 'var(--border-strong)'}`,
          display:'grid', placeItems:'center',
        }}>
          {picked && <span style={{ width: 8, height: 8, borderRadius:'50%', background: r.color }}/>}
        </span>
        <window.RolePill role={role}/>
        <span style={{ fontWeight: 500 }}>{r.label}</span>
      </div>
      <div className="muted" style={{ fontSize: 12, paddingLeft: 24, lineHeight: 1.7 }}>
        <div><span style={{ color: 'var(--success)' }}>✓ 可写</span>: {writes.length ? writes.map(moduleLabel).join('、') : '无'}</div>
        {reads.length > 0 && <div><span style={{ color: 'var(--text-2)' }}>· 只读</span>: {reads.map(moduleLabel).join('、')}</div>}
        {denied.length > 0 && <div><span style={{ color: 'var(--danger)' }}>✗ 禁止</span>: {denied.map(moduleLabel).join('、')}</div>}
      </div>
    </button>
  );
}

// ─── Invite dialog ──────────────────────────────────────────
function InviteDialog({ onClose }) {
  const [role, setRole] = React.useState('reviewer');
  const [email, setEmail] = React.useState('');
  const [name, setName] = React.useState('');
  return (
    <div className="drawer-backdrop" onClick={onClose} style={{ display:'grid', placeItems:'center' }}>
      <div onClick={(e) => e.stopPropagation()} className="card" style={{ width: 480, animation: 'pop .14s ease' }}>
        <div className="card-header">
          <div className="card-title">邀请新管理员</div>
          <button className="icon-btn" onClick={onClose}><window.I.x size={14}/></button>
        </div>
        <div className="card-pad">
          <label className="field">邮箱</label>
          <input className="input" placeholder="someone@pokeking.icu"
                 value={email} onChange={(e) => setEmail(e.target.value)} autoFocus/>
          <label className="field" style={{ marginTop: 12 }}>姓名(可选)</label>
          <input className="input" placeholder="显示在列表里"
                 value={name} onChange={(e) => setName(e.target.value)}/>
          <label className="field" style={{ marginTop: 12 }}>角色</label>
          <div style={{ display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap: 6 }}>
            {['super-admin','editor','reviewer'].map((rid) => (
              <button key={rid} onClick={() => setRole(rid)} style={{
                padding: 10,
                borderRadius:'var(--r-md)',
                border: `1px solid ${role === rid ? window.ROLES[rid].color : 'var(--border)'}`,
                background: role === rid ? window.hexAlpha(window.ROLES[rid].color, .06) : 'var(--surface)',
                boxShadow: role === rid ? `0 0 0 1px ${window.ROLES[rid].color}` : 'none',
                textAlign:'center',
              }}>
                <window.RoleDot role={rid}/>
                <div style={{ fontWeight: 500, marginTop: 6, fontSize: 13 }}>{window.ROLES[rid].label}</div>
              </button>
            ))}
          </div>
          <div className="muted" style={{ fontSize: 12, marginTop: 12, padding: 10, background:'var(--surface-2)', borderRadius:'var(--r-md)' }}>
            <window.I.info size={12} style={{ verticalAlign:'middle', marginRight: 4 }}/>
            将发送邀请邮件,有效期 7 天。对方接受后会自动在登录页用此邮箱登录。
          </div>
        </div>
        <div className="card-pad" style={{ paddingTop: 0, display:'flex', justifyContent:'flex-end', gap: 8 }}>
          <window.Btn onClick={onClose}>取消</window.Btn>
          <window.Btn kind="primary" disabled={!email} onClick={onClose}>
            <window.I.message size={13}/> 发送邀请
          </window.Btn>
        </div>
      </div>
    </div>
  );
}

// ─── System config ──────────────────────────────────────────
function SystemSection() {
  return (
    <>
      <SettingsCard title="集成" subtitle="影响构建与部署的外部服务">
        <SettingRowEdit label="GitHub 仓库" defaultValue="pokeking/main" mono/>
        <SettingRowEdit label="GitHub Token" defaultValue="ghp_••••••••sx7Q" mono/>
        <SettingRowEdit label="Cloudflare 账户 ID" defaultValue="a1b2c3d4e5" mono/>
        <SettingRowEdit label="Cloudflare D1 ID"  defaultValue="db_pokeking_prod" mono/>
      </SettingsCard>

      <SettingsCard title="抓取" subtitle="自动从 pokeking.icu 拉取最新阵容">
        <SettingRowEdit label="cron 表达式" defaultValue="0 0,12 * * *" mono/>
        <SettingRow     label="下次运行"   value="2026-05-19 24:00 (8 小时后)"/>
        <SettingRow     label="并发上限"   value="2"/>
      </SettingsCard>

      <SettingsCard title="审核规则" subtitle="降低你的工作量">
        <SettingRow     label="同 IP 24h 超 10 条" value="自动拒绝"/>
        <SettingRow     label="payload 字段缺失"   value="标记为低质量"/>
        <SettingRow     label="完全重复阵容"       value="自动合并"/>
      </SettingsCard>

      <SettingsCard title="维护" subtitle="紧急时使用,会影响 App 端">
        <div className="hstack" style={{ padding: '12px 0' }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 500, fontSize: 13 }}>全站维护模式</div>
            <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>开启后,App 会拿到 503,显示"维护中"提示。</div>
          </div>
          <Toggle on={false}/>
        </div>
        <div className="hstack" style={{ padding: '12px 0', borderTop: '1px solid var(--border)' }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 500, fontSize: 13, color: 'var(--danger)' }}>清空全部 staging</div>
            <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>不可恢复,5 条暂存变更将被丢弃。</div>
          </div>
          <window.Btn kind="danger" size="sm">清空</window.Btn>
        </div>
      </SettingsCard>
    </>
  );
}

function SecuritySection() {
  return (
    <>
      <SettingsCard title="登录与会话">
        <SettingRow label="会话有效期"     value="30 天"/>
        <SettingRow label="并发会话上限"   value="3 个"/>
        <SettingRow label="非常规登录提醒" value="开启"/>
      </SettingsCard>

      <SettingsCard title="审计" subtitle="所有变更已自动入操作日志">
        <SettingRow label="日志保留时长" value="180 天"/>
        <SettingRow label="导出 JSON"    value="可在操作日志页"/>
      </SettingsCard>

      <SettingsCard title="2FA" subtitle="v2 功能,即将上线">
        <div className="muted" style={{ padding: '12px 0', fontSize: 13 }}>
          <window.I.shield size={14} style={{ verticalAlign: 'middle', marginRight: 6 }}/>
          基于 TOTP 的两步验证 / WebAuthn 安全密钥,预计在用户系统上线后跟进。
        </div>
      </SettingsCard>
    </>
  );
}

// ─── Settings primitives ────────────────────────────────────
function SettingsCard({ title, subtitle, children }) {
  return (
    <div className="card" style={{ marginBottom: 16 }}>
      <div className="card-header" style={{ display: 'block', padding: '14px 20px' }}>
        <div className="card-title">{title}</div>
        {subtitle && <div className="muted" style={{ fontSize: 12, marginTop: 4 }}>{subtitle}</div>}
      </div>
      <div style={{ padding: '4px 20px 16px' }}>{children}</div>
    </div>
  );
}

function SettingRow({ label, value, mono }) {
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '180px 1fr',
      gap: 16, padding: '12px 0', borderBottom: '1px solid var(--border)',
      alignItems: 'center',
    }}>
      <div className="muted" style={{ fontSize: 13 }}>{label}</div>
      <div className={mono ? 'mono' : ''} style={{ fontWeight: 500, fontSize: 13 }}>{value}</div>
    </div>
  );
}

function SettingRowEdit({ label, defaultValue, mono, disabled }) {
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '180px 1fr',
      gap: 16, padding: '10px 0', borderBottom: '1px solid var(--border)',
      alignItems: 'center',
    }}>
      <div className="muted" style={{ fontSize: 13 }}>{label}</div>
      <input className={`input ${mono ? 'mono' : ''}`}
             defaultValue={defaultValue} disabled={disabled}
             style={{ height: 32, fontSize: 13 }}/>
    </div>
  );
}

function ToggleChip({ on, children }) {
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap: 4,
      padding: '3px 8px',
      borderRadius: 'var(--r-pill)',
      background: on ? window.hexAlpha('#10B981', .12) : 'var(--surface-2)',
      color: on ? 'var(--success)' : 'var(--text-3)',
      border: '1px solid ' + (on ? 'transparent' : 'var(--border)'),
      fontSize: 11, fontWeight: 500, cursor: 'pointer',
    }}>
      {on ? <window.I.check size={10}/> : null}
      {children}
    </span>
  );
}

function Toggle({ on }) {
  const [v, setV] = React.useState(on);
  return (
    <button onClick={() => setV(!v)} style={{
      width: 40, height: 22, borderRadius: 22, padding: 2,
      background: v ? 'var(--indigo)' : 'var(--surface-3)',
      transition: 'background .15s',
      display: 'inline-flex', alignItems: 'center',
    }}>
      <span style={{
        width: 18, height: 18, borderRadius: '50%',
        background: 'white', boxShadow: '0 1px 2px rgba(0,0,0,.2)',
        transform: v ? 'translateX(18px)' : 'translateX(0)',
        transition: 'transform .15s',
      }}/>
    </button>
  );
}

Object.assign(window, { SettingsPage });
