(function(){
// 管理後台頁（僅 admin 可見）
// API：GET /api/admin/pending、POST /api/admin/approve|reject、GET /api/admin/users
const T = window.STOCK_TOKENS;

// ── Toast 通知（輕量版，掛在頁面內）────────────────────────────────────────
function useToast() {
  const [toasts, setToasts] = React.useState([]);
  const show = (msg, type = 'success') => {
    const id = Date.now();
    setToasts(prev => [...prev, { id, msg, type }]);
    setTimeout(() => {
      setToasts(prev => prev.filter(t => t.id !== id));
    }, 3000);
  };
  const ToastContainer = () => (
    <div style={{
      position: 'fixed', bottom: 24, right: 24, zIndex: 9000,
      display: 'flex', flexDirection: 'column', gap: 8,
      pointerEvents: 'none',
    }}>
      {toasts.map(t => (
        <div key={t.id} style={{
          padding: '10px 16px', borderRadius: T.radius,
          background: t.type === 'error' ? T.down : 'oklch(0.25 0.01 250)',
          color: 'white', fontSize: 13, fontWeight: 500,
          boxShadow: '0 4px 20px rgba(0,0,0,0.25)',
          fontFamily: T.fontSans,
          animation: 'loginReveal 0.2s ease-out both',
        }}>{t.msg}</div>
      ))}
    </div>
  );
  return { show, ToastContainer };
}

// ── 相對時間（複用 shell.jsx 的 window.relativeTime）─────────────────────
const relTime = (iso) => window.relativeTime ? window.relativeTime(iso) : (iso || '—');

// ── 區塊 A：待審申請 ─────────────────────────────────────────────────────
function PendingRequests({ toast }) {
  const [requests, setRequests] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [processing, setProcessing] = React.useState({}); // { email: 'approve'|'reject' }

  React.useEffect(() => {
    window.fetchAPI('/api/admin/pending')
      .then(data => {
        setRequests(data.requests || []);
        setLoading(false);
      })
      .catch(err => {
        if (err && err.status === 403) {
          setError('無權限');
        } else {
          setError('載入失敗，請重試');
        }
        setLoading(false);
      });
  }, []);

  const handleAction = (email, action) => {
    setProcessing(prev => ({ ...prev, [email]: action }));
    const endpoint = action === 'approve' ? '/api/admin/approve' : '/api/admin/reject';
    window.fetchAPI(endpoint, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    })
      .then(() => {
        setRequests(prev => prev.filter(r => r.email !== email));
        setProcessing(prev => { const n = { ...prev }; delete n[email]; return n; });
        toast.show(action === 'approve' ? `已核准 ${email}` : `已拒絕 ${email}`);
      })
      .catch(() => {
        setProcessing(prev => { const n = { ...prev }; delete n[email]; return n; });
        toast.show('操作失敗，請重試', 'error');
      });
  };

  return (
    <window.Card
      title="待審申請"
      subtitle={loading ? '' : `${requests.length} 筆待審`}
      padding={0}
    >
      {loading && (
        <div style={{ padding: '40px 20px', textAlign: 'center', color: T.text3, fontSize: 13 }}>
          載入中…
        </div>
      )}
      {!loading && error && (
        <div style={{ padding: '40px 20px', textAlign: 'center', color: T.down, fontSize: 13 }}>
          {error}
        </div>
      )}
      {!loading && !error && requests.length === 0 && (
        <div style={{ padding: '40px 20px', textAlign: 'center', color: T.text3, fontSize: 13 }}>
          目前沒有待審申請
        </div>
      )}
      {!loading && !error && requests.map((req, i) => (
        <div key={req.email} style={{
          padding: '16px 20px',
          borderBottom: i < requests.length - 1 ? `1px solid ${T.border}` : 'none',
          display: 'flex', flexWrap: 'wrap', alignItems: 'flex-start', gap: 12,
        }}>
          {/* 左側資訊 */}
          <div style={{ flex: 1, minWidth: 200 }}>
            <div style={{ fontWeight: 600, fontSize: 13, color: T.text, marginBottom: 3 }}>
              {req.email}
            </div>
            {req.message && (
              <div style={{ fontSize: 12, color: T.text2, lineHeight: 1.5, marginBottom: 4 }}>
                {req.message}
              </div>
            )}
            <div style={{ fontSize: 11, color: T.text4, fontFamily: T.fontMono }}>
              {relTime(req.created_at)}
            </div>
          </div>
          {/* 右側按鈕 */}
          <div style={{ display: 'flex', gap: 8, flexShrink: 0 }}>
            <button
              disabled={!!processing[req.email]}
              onClick={() => handleAction(req.email, 'approve')}
              style={{
                padding: '6px 14px', borderRadius: 6, border: 'none',
                background: processing[req.email] === 'approve' ? T.text3 : 'oklch(0.55 0.15 155)',
                color: 'white', fontSize: 12, fontWeight: 600,
                cursor: processing[req.email] ? 'wait' : 'pointer',
                fontFamily: T.fontSans, transition: 'opacity 0.15s',
              }}
            >
              {processing[req.email] === 'approve' ? '處理中…' : '核准'}
            </button>
            <button
              disabled={!!processing[req.email]}
              onClick={() => handleAction(req.email, 'reject')}
              style={{
                padding: '6px 14px', borderRadius: 6,
                border: `1px solid ${T.border}`,
                background: processing[req.email] === 'reject' ? T.text3 : T.surface,
                color: processing[req.email] === 'reject' ? 'white' : T.text2,
                fontSize: 12, fontWeight: 500,
                cursor: processing[req.email] ? 'wait' : 'pointer',
                fontFamily: T.fontSans, transition: 'opacity 0.15s',
              }}
            >
              {processing[req.email] === 'reject' ? '處理中…' : '拒絕'}
            </button>
          </div>
        </div>
      ))}
    </window.Card>
  );
}

// ── 區塊 B：使用者管理 ────────────────────────────────────────────────────
function UserManagement() {
  const [users, setUsers] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const vp = window.useViewport ? window.useViewport() : { isMobile: false };

  React.useEffect(() => {
    window.fetchAPI('/api/admin/users')
      .then(data => {
        setUsers(data.users || []);
        setLoading(false);
      })
      .catch(err => {
        if (err && err.status === 403) {
          setError('無權限');
        } else {
          setError('載入失敗，請重試');
        }
        setLoading(false);
      });
  }, []);

  const roleBadge = (role) => {
    const map = {
      admin: { bg: 'oklch(0.55 0.18 240)', color: 'white', label: 'admin' },
      member: { bg: T.surface, color: T.text2, label: 'member' },
      pending: { bg: 'oklch(0.75 0.12 80)', color: 'white', label: 'pending' },
    };
    const s = map[role] || map.pending;
    return (
      <span style={{
        display: 'inline-block', padding: '2px 8px', borderRadius: 4,
        background: s.bg, color: s.color, fontSize: 10, fontWeight: 700,
        fontFamily: T.fontMono, letterSpacing: 0.3,
      }}>{s.label}</span>
    );
  };

  return (
    <window.Card title="使用者管理" subtitle={loading ? '' : `${users.length} 位使用者`} padding={0}>
      {loading && (
        <div style={{ padding: '40px 20px', textAlign: 'center', color: T.text3, fontSize: 13 }}>
          載入中…
        </div>
      )}
      {!loading && error && (
        <div style={{ padding: '40px 20px', textAlign: 'center', color: T.down, fontSize: 13 }}>
          {error}
        </div>
      )}
      {!loading && !error && (
        <>
          {/* 桌面：表格 */}
          {!vp.isMobile && (
            <div style={{ overflowX: 'auto' }}>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
                <thead>
                  <tr style={{ borderBottom: `1px solid ${T.border}` }}>
                    {['Email', '角色', '核准時間', '最後上線'].map(h => (
                      <th key={h} style={{
                        padding: '10px 16px', textAlign: 'left',
                        color: T.text3, fontWeight: 600, fontSize: 10,
                        letterSpacing: 0.5, fontFamily: T.fontSans,
                        whiteSpace: 'nowrap',
                      }}>{h}</th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {users.map((u, i) => (
                    <tr key={u.email} style={{
                      borderBottom: i < users.length - 1 ? `1px solid ${T.border}` : 'none',
                    }}>
                      <td style={{ padding: '12px 16px', color: T.text, fontWeight: 500 }}>{u.email}</td>
                      <td style={{ padding: '12px 16px' }}>{roleBadge(u.role)}</td>
                      <td style={{ padding: '12px 16px', color: T.text3, fontFamily: T.fontMono }}>
                        {u.approved_at ? relTime(u.approved_at) : '—'}
                      </td>
                      <td style={{ padding: '12px 16px', color: T.text3, fontFamily: T.fontMono }}>
                        {u.last_seen_at ? relTime(u.last_seen_at) : '—'}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
          {/* 手機：列表卡片 */}
          {vp.isMobile && users.map((u, i) => (
            <div key={u.email} style={{
              padding: '12px 16px',
              borderBottom: i < users.length - 1 ? `1px solid ${T.border}` : 'none',
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                <span style={{ fontSize: 13, fontWeight: 600, color: T.text, flex: 1, minWidth: 0,
                  overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{u.email}</span>
                {roleBadge(u.role)}
              </div>
              <div style={{ fontSize: 11, color: T.text4, fontFamily: T.fontMono }}>
                核准：{u.approved_at ? relTime(u.approved_at) : '—'} ·
                上線：{u.last_seen_at ? relTime(u.last_seen_at) : '—'}
              </div>
            </div>
          ))}
          {!loading && users.length === 0 && (
            <div style={{ padding: '40px 20px', textAlign: 'center', color: T.text3, fontSize: 13 }}>
              目前沒有使用者
            </div>
          )}
        </>
      )}
    </window.Card>
  );
}

// ── AdminPage 主元件 ──────────────────────────────────────────────────────
function AdminPage() {
  const toast = useToast();
  const vp = window.useViewport ? window.useViewport() : { isMobile: false };
  const [forbidden, setForbidden] = React.useState(false);

  // 進入時先確認自己有 admin 權限（額外保護）
  React.useEffect(() => {
    if (!window.fetchAPI) return;
    window.fetchAPI('/api/admin/pending')
      .catch(err => {
        if (err && (err.status === 403 || err.status === 401)) setForbidden(true);
      });
  }, []);

  if (forbidden) {
    return (
      <div style={{ padding: vp.isMobile ? 16 : 24 }}>
        <div style={{
          padding: '40px 20px', textAlign: 'center',
          background: T.surface, border: `1px solid ${T.border}`,
          borderRadius: T.radiusLg, color: T.text2, fontSize: 14,
        }}>
          無權限存取管理後台
        </div>
      </div>
    );
  }

  return (
    <div style={{ padding: vp.isMobile ? 12 : 24, display: 'flex', flexDirection: 'column', gap: 20 }}>
      {/* 頁首說明 */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: '12px 16px',
        background: 'oklch(0.97 0.01 240)',
        border: `1px solid ${T.border}`,
        borderRadius: T.radius,
      }}>
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke={T.text3} strokeWidth="1.5">
          <circle cx="8" cy="8" r="6"/><path d="M8 7v4M8 5.5v.5"/>
        </svg>
        <span style={{ fontSize: 12, color: T.text3 }}>
          管理後台僅限 admin 存取。核准/拒絕操作即時生效，無法撤銷。
        </span>
      </div>

      {/* 區塊 A */}
      <PendingRequests toast={toast} />

      {/* 區塊 B */}
      <UserManagement />

      {/* Toast 容器 */}
      <toast.ToastContainer />
    </div>
  );
}
window.AdminPage = AdminPage;

})();
