import { useState, useEffect, useCallback } from 'react'
import { Card, CardContent } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import { Label } from '@/components/ui/label'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { Badge } from '@/components/ui/badge'
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog'
import { Switch } from '@/components/ui/switch'
import { Textarea } from '@/components/ui/textarea'
import {
  Search,
  UserPlus,
  Trash2,
  Edit3,
  Key,
  Save,
  X,
  RefreshCw,
  Users,
  Eye,
  Crown,
  Plus,
  BookOpen,
  Settings,
  PenLine,
  Navigation,
  TrendingUp,
  ArrowUpDown,
  ChevronDown,
  ChevronUp,
} from 'lucide-react'
import { UserDetailModal } from '@/components/modules/user/UserDetailModal'
import { SetVipModal } from '@/components/modules/user/SetVipModal'
import { Pagination } from '@/components/ui/Pagination'
import { useDebounce } from '@/hooks/useDebounce'
import { get, del, post, put } from '@/api/client'

interface User {
  id: string
  openId?: string | null
  phone?: string | null
  nickname: string
  wechatId?: string | null
  avatar?: string | null
  isAdmin?: boolean | number
  hasFullBook?: boolean | number
  referralCode?: string
  earnings: number | string
  pendingEarnings?: number | string
  withdrawnEarnings?: number | string
  referralCount?: number
  createdAt: string
  updatedAt?: string | null
  // RFM（排序模式时有值）
  rfmScore?: number
  rfmLevel?: string
}

interface UserRule {
  id: number
  title: string
  description: string
  trigger: string
  sort: number
  enabled: boolean
  createdAt?: string
}

interface VipRole {
  id: number
  name: string
  sort: number
  createdAt?: string
}

// 用户旅程阶段定义
const JOURNEY_STAGES = [
  { id: 'register', label: '注册/登录', icon: '👤', color: 'bg-blue-500/20 border-blue-500/40 text-blue-400', desc: '微信授权登录或手机号注册' },
  { id: 'browse', label: '浏览章节', icon: '📖', color: 'bg-purple-500/20 border-purple-500/40 text-purple-400', desc: '点击免费/付费章节预览' },
  { id: 'bind_phone', label: '绑定手机', icon: '📱', color: 'bg-cyan-500/20 border-cyan-500/40 text-cyan-400', desc: '触发付费章节后绑定手机' },
  { id: 'first_pay', label: '首次付款', icon: '💳', color: 'bg-green-500/20 border-green-500/40 text-green-400', desc: '购买单章或全书' },
  { id: 'fill_profile', label: '完善资料', icon: '✍️', color: 'bg-yellow-500/20 border-yellow-500/40 text-yellow-400', desc: '填写头像、MBTI、行业等' },
  { id: 'match', label: '派对房匹配', icon: '🤝', color: 'bg-orange-500/20 border-orange-500/40 text-orange-400', desc: '参与 Soul 派对房' },
  { id: 'vip', label: '升级 VIP', icon: '👑', color: 'bg-amber-500/20 border-amber-500/40 text-amber-400', desc: '付款 ¥1980 购买全书' },
  { id: 'distribution', label: '开启分销', icon: '🔗', color: 'bg-[#38bdac]/20 border-[#38bdac]/40 text-[#38bdac]', desc: '生成推广码并推荐好友' },
]

export function UsersPage() {
  // ===== 用户列表 state =====
  const [users, setUsers] = useState<User[]>([])
  const [total, setTotal] = useState(0)
  const [page, setPage] = useState(1)
  const [pageSize, setPageSize] = useState(10)
  const [searchTerm, setSearchTerm] = useState('')
  const debouncedSearch = useDebounce(searchTerm, 300)
  const [vipFilter, setVipFilter] = useState<'all' | 'vip'>('all')
  const [isLoading, setIsLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [rfmSortMode, setRfmSortMode] = useState(false) // RFM 排序模式
  const [rfmSortDir, setRfmSortDir] = useState<'desc' | 'asc'>('desc')

  // 弹框
  const [showUserModal, setShowUserModal] = useState(false)
  const [showPasswordModal, setShowPasswordModal] = useState(false)
  const [editingUser, setEditingUser] = useState<User | null>(null)
  const [newPassword, setNewPassword] = useState('')
  const [confirmPassword, setConfirmPassword] = useState('')
  const [isSaving, setIsSaving] = useState(false)
  const [showReferralsModal, setShowReferralsModal] = useState(false)
  const [referralsData, setReferralsData] = useState<{ referrals?: unknown[]; stats?: Record<string, unknown> }>({ referrals: [], stats: {} })
  const [referralsLoading, setReferralsLoading] = useState(false)
  const [selectedUserForReferrals, setSelectedUserForReferrals] = useState<User | null>(null)
  const [showDetailModal, setShowDetailModal] = useState(false)
  const [selectedUserIdForDetail, setSelectedUserIdForDetail] = useState<string | null>(null)
  const [showSetVipModal, setShowSetVipModal] = useState(false)
  const [selectedUserForVip, setSelectedUserForVip] = useState<User | null>(null)
  const [formData, setFormData] = useState({ phone: '', nickname: '', password: '', isAdmin: false, hasFullBook: false })

  // ===== 规则管理 =====
  const [rules, setRules] = useState<UserRule[]>([])
  const [rulesLoading, setRulesLoading] = useState(false)
  const [showRuleModal, setShowRuleModal] = useState(false)
  const [editingRule, setEditingRule] = useState<UserRule | null>(null)
  const [ruleForm, setRuleForm] = useState({ title: '', description: '', trigger: '', sort: 0, enabled: true })

  // ===== VIP 角色 =====
  const [vipRoles, setVipRoles] = useState<VipRole[]>([])
  const [vipRolesLoading, setVipRolesLoading] = useState(false)
  const [showVipRoleModal, setShowVipRoleModal] = useState(false)
  const [editingVipRole, setEditingVipRole] = useState<VipRole | null>(null)
  const [vipRoleForm, setVipRoleForm] = useState({ name: '', sort: 0 })

  // ===== 用户旅程总览 =====
  const [journeyStats, setJourneyStats] = useState<Record<string, number>>({})
  const [journeyLoading, setJourneyLoading] = useState(false)

  // ===== 用户列表 =====
  async function loadUsers() {
    setIsLoading(true)
    setError(null)
    try {
      if (rfmSortMode) {
        // RFM 排序模式：从 RFM 接口获取
        const params = new URLSearchParams({ search: debouncedSearch, limit: String(pageSize * 5) })
        const data = await get<{ success?: boolean; users?: User[]; error?: string }>(`/api/db/users/rfm?${params}`)
        if (data?.success) {
          let list = data.users || []
          if (rfmSortDir === 'asc') list = [...list].reverse()
          const start = (page - 1) * pageSize
          setUsers(list.slice(start, start + pageSize))
          setTotal(data.users?.length ?? 0)
          if (list.length === 0) {
            // 暂无订单数据，退回普通模式
            setRfmSortMode(false)
            setError('暂无订单数据，RFM 排序需要用户有购买记录后才能生效')
          }
        } else {
          setRfmSortMode(false)
          setError(data?.error || 'RFM 加载失败，已切回普通模式')
        }
      } else {
        const params = new URLSearchParams({
          page: String(page),
          pageSize: String(pageSize),
          search: debouncedSearch,
          ...(vipFilter === 'vip' && { vip: 'true' }),
        })
        const data = await get<{ success?: boolean; users?: User[]; total?: number; error?: string }>(`/api/db/users?${params}`)
        if (data?.success) {
          setUsers(data.users || [])
          setTotal(data.total ?? 0)
        } else {
          setError(data?.error || '加载失败')
        }
      }
    } catch (err) {
      console.error('Load users error:', err)
      setError('网络错误')
    } finally {
      setIsLoading(false)
    }
  }

  useEffect(() => { setPage(1) }, [debouncedSearch, vipFilter, rfmSortMode])
  useEffect(() => { loadUsers() }, [page, pageSize, debouncedSearch, vipFilter, rfmSortMode, rfmSortDir])

  const totalPages = Math.ceil(total / pageSize) || 1

  const toggleRfmSort = () => {
    if (rfmSortMode) {
      if (rfmSortDir === 'desc') setRfmSortDir('asc')
      else { setRfmSortMode(false); setRfmSortDir('desc') }
    } else {
      setRfmSortMode(true)
      setRfmSortDir('desc')
    }
  }

  const getRFMLevelColor = (level?: string) => {
    const map: Record<string, string> = {
      S: 'bg-amber-500/20 text-amber-400',
      A: 'bg-green-500/20 text-green-400',
      B: 'bg-blue-500/20 text-blue-400',
      C: 'bg-gray-500/20 text-gray-400',
      D: 'bg-red-500/20 text-red-400',
    }
    return map[level || ''] || 'bg-gray-500/20 text-gray-400'
  }

  async function handleDelete(userId: string) {
    if (!confirm('确定要删除这个用户吗？')) return
    try {
      const data = await del<{ success?: boolean; error?: string }>(`/api/db/users?id=${encodeURIComponent(userId)}`)
      if (data?.success) loadUsers()
      else alert('删除失败: ' + (data?.error || ''))
    } catch { alert('删除失败') }
  }

  const handleEditUser = (user: User) => {
    setEditingUser(user)
    setFormData({ phone: user.phone || '', nickname: user.nickname || '', password: '', isAdmin: !!(user.isAdmin ?? false), hasFullBook: !!(user.hasFullBook ?? false) })
    setShowUserModal(true)
  }

  const handleAddUser = () => {
    setEditingUser(null)
    setFormData({ phone: '', nickname: '', password: '', isAdmin: false, hasFullBook: false })
    setShowUserModal(true)
  }

  async function handleSaveUser() {
    if (!formData.phone || !formData.nickname) { alert('请填写手机号和昵称'); return }
    setIsSaving(true)
    try {
      if (editingUser) {
        const data = await put<{ success?: boolean; error?: string }>('/api/db/users', { id: editingUser.id, nickname: formData.nickname, isAdmin: formData.isAdmin, hasFullBook: formData.hasFullBook, ...(formData.password && { password: formData.password }) })
        if (!data?.success) { alert('更新失败: ' + (data?.error || '')); return }
      } else {
        const data = await post<{ success?: boolean; error?: string }>('/api/db/users', { phone: formData.phone, nickname: formData.nickname, password: formData.password, isAdmin: formData.isAdmin })
        if (!data?.success) { alert('创建失败: ' + (data?.error || '')); return }
      }
      setShowUserModal(false)
      loadUsers()
    } catch { alert('保存失败') } finally { setIsSaving(false) }
  }

  const handleChangePassword = (user: User) => { setEditingUser(user); setNewPassword(''); setConfirmPassword(''); setShowPasswordModal(true) }

  async function handleViewReferrals(user: User) {
    setSelectedUserForReferrals(user); setShowReferralsModal(true); setReferralsLoading(true)
    try {
      const data = await get<{ success?: boolean; referrals?: unknown[]; stats?: Record<string, unknown> }>(`/api/db/users/referrals?userId=${encodeURIComponent(user.id)}`)
      if (data?.success) setReferralsData({ referrals: data.referrals || [], stats: data.stats || {} })
      else setReferralsData({ referrals: [], stats: {} })
    } catch { setReferralsData({ referrals: [], stats: {} }) } finally { setReferralsLoading(false) }
  }

  async function handleSavePassword() {
    if (!newPassword) { alert('请输入新密码'); return }
    if (newPassword !== confirmPassword) { alert('两次密码不一致'); return }
    if (newPassword.length < 6) { alert('密码至少6位'); return }
    setIsSaving(true)
    try {
      const data = await put<{ success?: boolean; error?: string }>('/api/db/users', { id: editingUser?.id, password: newPassword })
      if (data?.success) { alert('修改成功'); setShowPasswordModal(false) }
      else alert('修改失败: ' + (data?.error || ''))
    } catch { alert('修改失败') } finally { setIsSaving(false) }
  }

  // ===== 规则管理 =====
  const loadRules = useCallback(async () => {
    setRulesLoading(true)
    try {
      const data = await get<{ success?: boolean; rules?: UserRule[] }>('/api/db/user-rules')
      if (data?.success) setRules(data.rules || [])
    } catch { } finally { setRulesLoading(false) }
  }, [])

  async function handleSaveRule() {
    if (!ruleForm.title) { alert('请填写规则标题'); return }
    setIsSaving(true)
    try {
      if (editingRule) {
        const data = await put<{ success?: boolean; error?: string }>('/api/db/user-rules', { id: editingRule.id, ...ruleForm })
        if (!data?.success) { alert('更新失败: ' + (data?.error || '')); return }
      } else {
        const data = await post<{ success?: boolean; error?: string }>('/api/db/user-rules', ruleForm)
        if (!data?.success) { alert('创建失败: ' + (data?.error || '')); return }
      }
      setShowRuleModal(false); loadRules()
    } catch { alert('保存失败') } finally { setIsSaving(false) }
  }

  async function handleDeleteRule(id: number) {
    if (!confirm('确定删除？')) return
    try {
      const data = await del<{ success?: boolean }>(`/api/db/user-rules?id=${id}`)
      if (data?.success) loadRules()
    } catch { }
  }

  async function handleToggleRule(rule: UserRule) {
    try { await put('/api/db/user-rules', { id: rule.id, enabled: !rule.enabled }); loadRules() } catch { }
  }

  // ===== VIP 角色 =====
  const loadVipRoles = useCallback(async () => {
    setVipRolesLoading(true)
    try {
      const data = await get<{ success?: boolean; roles?: VipRole[] }>('/api/db/vip-roles')
      if (data?.success) setVipRoles(data.roles || [])
    } catch { } finally { setVipRolesLoading(false) }
  }, [])

  async function handleSaveVipRole() {
    if (!vipRoleForm.name) { alert('请填写角色名称'); return }
    setIsSaving(true)
    try {
      if (editingVipRole) {
        const data = await put<{ success?: boolean; error?: string }>('/api/db/vip-roles', { id: editingVipRole.id, ...vipRoleForm })
        if (!data?.success) { alert('更新失败'); return }
      } else {
        const data = await post<{ success?: boolean; error?: string }>('/api/db/vip-roles', vipRoleForm)
        if (!data?.success) { alert('创建失败'); return }
      }
      setShowVipRoleModal(false); loadVipRoles()
    } catch { alert('保存失败') } finally { setIsSaving(false) }
  }

  async function handleDeleteVipRole(id: number) {
    if (!confirm('确定删除？')) return
    try {
      const data = await del<{ success?: boolean }>(`/api/db/vip-roles?id=${id}`)
      if (data?.success) loadVipRoles()
    } catch { }
  }

  // ===== 用户旅程总览 =====
  const loadJourneyStats = useCallback(async () => {
    setJourneyLoading(true)
    try {
      const data = await get<{ success?: boolean; stats?: Record<string, number> }>('/api/db/users/journey-stats')
      if (data?.success && data.stats) setJourneyStats(data.stats)
    } catch { } finally { setJourneyLoading(false) }
  }, [])

  return (
    <div className="p-8 w-full">
      {error && (
        <div className="mb-4 px-4 py-3 rounded-lg bg-red-500/20 border border-red-500/50 text-red-400 text-sm flex items-center justify-between">
          <span>{error}</span>
          <button type="button" onClick={() => setError(null)}>×</button>
        </div>
      )}

      <div className="flex justify-between items-center mb-6">
        <div>
          <h2 className="text-2xl font-bold text-white">用户管理</h2>
          <p className="text-gray-400 mt-1 text-sm">共 {total} 位注册用户{rfmSortMode && ' · RFM 排序中'}</p>
        </div>
      </div>

      <Tabs defaultValue="users" className="w-full">
        <TabsList className="bg-[#0a1628] border border-gray-700/50 p-1 mb-6 flex-wrap h-auto gap-1">
          <TabsTrigger value="users" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] flex items-center gap-1.5">
            <Users className="w-4 h-4" /> 用户列表
          </TabsTrigger>
          <TabsTrigger value="journey" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] flex items-center gap-1.5" onClick={loadJourneyStats}>
            <Navigation className="w-4 h-4" /> 用户旅程总览
          </TabsTrigger>
          <TabsTrigger value="rules" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] flex items-center gap-1.5" onClick={loadRules}>
            <Settings className="w-4 h-4" /> 规则配置
          </TabsTrigger>
          <TabsTrigger value="vip-roles" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] flex items-center gap-1.5" onClick={loadVipRoles}>
            <Crown className="w-4 h-4" /> VIP 角色
          </TabsTrigger>
        </TabsList>

        {/* ===== 用户列表 ===== */}
        <TabsContent value="users">
          <div className="flex items-center gap-3 mb-4 justify-end flex-wrap">
            <Button
              variant="outline"
              onClick={loadUsers}
              disabled={isLoading}
              className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent"
            >
              <RefreshCw className={`w-4 h-4 mr-2 ${isLoading ? 'animate-spin' : ''}`} /> 刷新
            </Button>
            <select
              value={vipFilter}
              onChange={(e) => { setVipFilter(e.target.value as 'all' | 'vip'); setPage(1) }}
              className="bg-[#0f2137] border border-gray-700 text-white rounded-lg px-3 py-2 text-sm"
              disabled={rfmSortMode}
            >
              <option value="all">全部用户</option>
              <option value="vip">VIP会员</option>
            </select>
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500" />
              <Input
                type="text"
                placeholder="搜索用户..."
                className="pl-10 bg-[#0f2137] border-gray-700 text-white placeholder:text-gray-500 w-56"
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
              />
            </div>
            <Button onClick={handleAddUser} className="bg-[#38bdac] hover:bg-[#2da396] text-white">
              <UserPlus className="w-4 h-4 mr-2" /> 添加用户
            </Button>
          </div>

          <Card className="bg-[#0f2137] border-gray-700/50 shadow-xl">
            <CardContent className="p-0">
              {isLoading ? (
                <div className="flex items-center justify-center py-12">
                  <RefreshCw className="w-6 h-6 text-[#38bdac] animate-spin" />
                  <span className="ml-2 text-gray-400">加载中...</span>
                </div>
              ) : (
                <div>
                  <Table>
                    <TableHeader>
                      <TableRow className="bg-[#0a1628] hover:bg-[#0a1628] border-gray-700">
                        <TableHead className="text-gray-400">用户信息</TableHead>
                        <TableHead className="text-gray-400">绑定信息</TableHead>
                        <TableHead className="text-gray-400">购买状态</TableHead>
                        <TableHead className="text-gray-400">分销收益</TableHead>
                        <TableHead className="text-gray-400 cursor-pointer select-none" onClick={toggleRfmSort}>
                          <div className="flex items-center gap-1 group">
                            <TrendingUp className="w-3.5 h-3.5" />
                            <span>RFM分值</span>
                            {rfmSortMode ? (
                              rfmSortDir === 'desc'
                                ? <ChevronDown className="w-3.5 h-3.5 text-[#38bdac]" />
                                : <ChevronUp className="w-3.5 h-3.5 text-[#38bdac]" />
                            ) : (
                              <ArrowUpDown className="w-3.5 h-3.5 text-gray-600 group-hover:text-gray-400" />
                            )}
                          </div>
                          {rfmSortMode && (
                            <div className="text-[10px] text-[#38bdac] font-normal mt-0.5">点击切换方向/关闭</div>
                          )}
                        </TableHead>
                        <TableHead className="text-gray-400">注册时间</TableHead>
                        <TableHead className="text-right text-gray-400">操作</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {users.map((user) => (
                        <TableRow key={user.id} className="hover:bg-[#0a1628] border-gray-700/50">
                          <TableCell>
                            <div className="flex items-center gap-3">
                              <div className="w-10 h-10 rounded-full bg-[#38bdac]/20 flex items-center justify-center text-sm font-medium text-[#38bdac]">
                                {user.avatar ? (
                                  <img src={user.avatar} className="w-full h-full rounded-full object-cover" alt="" />
                                ) : user.nickname?.charAt(0) || '?'}
                              </div>
                              <div>
                                <div className="flex items-center gap-1.5">
                                  <p className="font-medium text-white">{user.nickname}</p>
                                  {user.isAdmin && <Badge className="bg-purple-500/20 text-purple-400 hover:bg-purple-500/20 border-0 text-xs">管理员</Badge>}
                                  {user.openId && !user.id?.startsWith('user_') && <Badge className="bg-green-500/20 text-green-400 hover:bg-green-500/20 border-0 text-xs">微信</Badge>}
                                </div>
                                <p className="text-xs text-gray-500 font-mono">
                                  {user.openId ? user.openId.slice(0, 12) + '...' : user.id?.slice(0, 12)}
                                </p>
                              </div>
                            </div>
                          </TableCell>
                          <TableCell>
                            <div className="space-y-1">
                              {user.phone && <div className="flex items-center gap-1 text-xs"><span className="text-gray-500">📱</span><span className="text-gray-300">{user.phone}</span></div>}
                              {user.wechatId && <div className="flex items-center gap-1 text-xs"><span className="text-gray-500">💬</span><span className="text-gray-300">{user.wechatId}</span></div>}
                              {user.openId && <div className="flex items-center gap-1 text-xs"><span className="text-gray-500">🔗</span><span className="text-gray-500 truncate max-w-[100px]" title={user.openId}>{user.openId.slice(0, 12)}...</span></div>}
                              {!user.phone && !user.wechatId && !user.openId && <span className="text-gray-600 text-xs">未绑定</span>}
                            </div>
                          </TableCell>
                          <TableCell>
                            {user.hasFullBook ? (
                              <Badge className="bg-amber-500/20 text-amber-400 hover:bg-amber-500/20 border-0">VIP</Badge>
                            ) : (
                              <Badge variant="outline" className="text-gray-500 border-gray-600">未购买</Badge>
                            )}
                          </TableCell>
                          <TableCell>
                            <div className="space-y-1">
                              <div className="text-white font-medium">¥{parseFloat(String(user.earnings || 0)).toFixed(2)}</div>
                              {parseFloat(String(user.pendingEarnings || 0)) > 0 && (
                                <div className="text-xs text-yellow-400">待提现: ¥{parseFloat(String(user.pendingEarnings || 0)).toFixed(2)}</div>
                              )}
                              <div className="text-xs text-[#38bdac] cursor-pointer hover:underline flex items-center gap-1" onClick={() => handleViewReferrals(user)} role="button" tabIndex={0} onKeyDown={(e) => e.key === 'Enter' && handleViewReferrals(user)}>
                                <Users className="w-3 h-3" /> 绑定{user.referralCount || 0}人
                              </div>
                            </div>
                          </TableCell>
                          {/* RFM 分值列 */}
                          <TableCell>
                            {user.rfmScore !== undefined ? (
                              <div className="flex flex-col gap-1">
                                <div className="flex items-center gap-1.5">
                                  <span className="text-white font-bold text-base">{user.rfmScore}</span>
                                  <Badge className={`border-0 text-xs ${getRFMLevelColor(user.rfmLevel)}`}>{user.rfmLevel}</Badge>
                                </div>
                              </div>
                            ) : (
                              <span className="text-gray-600 text-sm">— <span className="text-xs text-gray-700">点列头排序</span></span>
                            )}
                          </TableCell>
                          <TableCell className="text-gray-400">
                            {user.createdAt ? new Date(user.createdAt).toLocaleDateString() : '-'}
                          </TableCell>
                          <TableCell className="text-right">
                            <div className="flex items-center justify-end gap-1">
                              <Button variant="ghost" size="sm" onClick={() => { setSelectedUserForVip(user); setShowSetVipModal(true) }} className="text-gray-400 hover:text-amber-400 hover:bg-amber-400/10" title="设置 VIP"><Crown className="w-4 h-4" /></Button>
                              <Button variant="ghost" size="sm" onClick={() => { setSelectedUserIdForDetail(user.id); setShowDetailModal(true) }} className="text-gray-400 hover:text-blue-400 hover:bg-blue-400/10" title="查看详情"><Eye className="w-4 h-4" /></Button>
                              <Button variant="ghost" size="sm" onClick={() => handleEditUser(user)} className="text-gray-400 hover:text-[#38bdac] hover:bg-[#38bdac]/10" title="编辑"><Edit3 className="w-4 h-4" /></Button>
                              <Button variant="ghost" size="sm" onClick={() => handleChangePassword(user)} className="text-gray-400 hover:text-yellow-400 hover:bg-yellow-400/10" title="修改密码"><Key className="w-4 h-4" /></Button>
                              <Button variant="ghost" size="sm" className="text-red-400 hover:text-red-300 hover:bg-red-500/10" onClick={() => handleDelete(user.id)} title="删除"><Trash2 className="w-4 h-4" /></Button>
                            </div>
                          </TableCell>
                        </TableRow>
                      ))}
                      {users.length === 0 && (
                        <TableRow>
                          <TableCell colSpan={7} className="text-center py-12 text-gray-500">暂无用户数据</TableCell>
                        </TableRow>
                      )}
                    </TableBody>
                  </Table>
                  <Pagination page={page} totalPages={totalPages} total={total} pageSize={pageSize} onPageChange={setPage} onPageSizeChange={(n) => { setPageSize(n); setPage(1) }} />
                </div>
              )}
            </CardContent>
          </Card>
        </TabsContent>

        {/* ===== 用户旅程总览 ===== */}
        <TabsContent value="journey">
          <div className="flex items-center justify-between mb-5">
            <p className="text-gray-400 text-sm">用户从注册到 VIP 的完整行动路径，点击各阶段查看用户动态</p>
            <Button variant="outline" onClick={loadJourneyStats} disabled={journeyLoading} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent">
              <RefreshCw className={`w-4 h-4 mr-2 ${journeyLoading ? 'animate-spin' : ''}`} /> 刷新数据
            </Button>
          </div>

          {/* 流程图 */}
          <div className="relative mb-8">
            {/* 连接线 */}
            <div className="absolute top-16 left-0 right-0 h-0.5 bg-gradient-to-r from-blue-500/20 via-[#38bdac]/30 to-amber-500/20 mx-20" />
            <div className="grid grid-cols-4 gap-4 lg:grid-cols-8">
              {JOURNEY_STAGES.map((stage, idx) => (
                <div key={stage.id} className="relative flex flex-col items-center">
                  {/* 阶段卡片 */}
                  <div className={`relative w-full p-3 rounded-xl border ${stage.color} text-center cursor-default`}>
                    <div className="text-2xl mb-1">{stage.icon}</div>
                    <div className={`text-xs font-medium ${stage.color.split(' ').find(c => c.startsWith('text-'))}`}>{stage.label}</div>
                    {journeyStats[stage.id] !== undefined && (
                      <div className="mt-1.5 text-xs text-gray-400">
                        <span className="font-bold text-white">{journeyStats[stage.id]}</span> 人
                      </div>
                    )}
                    {/* 序号 */}
                    <div className="absolute -top-2.5 -left-2.5 w-5 h-5 rounded-full bg-[#0a1628] border border-gray-700 flex items-center justify-center text-[10px] text-gray-500">{idx + 1}</div>
                  </div>
                  {/* 箭头（非最后一个）*/}
                  {idx < JOURNEY_STAGES.length - 1 && (
                    <div className="hidden lg:block absolute right-0 top-1/2 -translate-y-1/2 translate-x-1/2 z-10">
                      <svg width="20" height="12" viewBox="0 0 20 12" fill="none">
                        <path d="M0 6H16M16 6L11 1M16 6L11 11" stroke="#374151" strokeWidth="1.5" strokeLinecap="round" />
                      </svg>
                    </div>
                  )}
                  {/* 描述 */}
                  <p className="text-[10px] text-gray-600 text-center mt-2 leading-tight">{stage.desc}</p>
                </div>
              ))}
            </div>
          </div>

          {/* 旅程说明 */}
          <div className="grid grid-cols-2 gap-4">
            <div className="bg-[#0f2137] border border-gray-700/50 rounded-lg p-4">
              <div className="flex items-center gap-2 mb-3">
                <Navigation className="w-4 h-4 text-[#38bdac]" />
                <span className="text-white font-medium">旅程关键节点</span>
              </div>
              <div className="space-y-2 text-sm">
                {[
                  { step: '① 注册', action: '微信 OAuth 或手机号注册', next: '引导填写头像' },
                  { step: '② 浏览', action: '点击章节/阅读免费内容', next: '触发绑定手机' },
                  { step: '③ 首付', action: '购买单章或全书', next: '推送分销功能' },
                  { step: '④ VIP', action: '¥1980 购买全书', next: '进入 VIP 私域群' },
                  { step: '⑤ 分销', action: '推广好友购买', next: '提现分销收益' },
                ].map((item) => (
                  <div key={item.step} className="flex items-start gap-3 p-2 bg-[#0a1628] rounded">
                    <span className="text-[#38bdac] font-mono text-xs shrink-0 mt-0.5">{item.step}</span>
                    <div>
                      <p className="text-gray-300">{item.action}</p>
                      <p className="text-gray-600 text-xs">→ {item.next}</p>
                    </div>
                  </div>
                ))}
              </div>
            </div>
            <div className="bg-[#0f2137] border border-gray-700/50 rounded-lg p-4">
              <div className="flex items-center gap-2 mb-3">
                <BookOpen className="w-4 h-4 text-purple-400" />
                <span className="text-white font-medium">行为锚点统计</span>
                <span className="text-gray-500 text-xs ml-auto">实时更新</span>
              </div>
              {journeyLoading ? (
                <div className="flex items-center justify-center py-8">
                  <RefreshCw className="w-5 h-5 text-[#38bdac] animate-spin" />
                </div>
              ) : Object.keys(journeyStats).length > 0 ? (
                <div className="space-y-2">
                  {JOURNEY_STAGES.map((stage) => {
                    const count = journeyStats[stage.id] || 0
                    const maxCount = Math.max(...JOURNEY_STAGES.map(s => journeyStats[s.id] || 0), 1)
                    const pct = Math.round((count / maxCount) * 100)
                    return (
                      <div key={stage.id} className="flex items-center gap-2">
                        <span className="text-gray-500 text-xs w-20 shrink-0">{stage.icon} {stage.label}</span>
                        <div className="flex-1 h-2 bg-[#0a1628] rounded-full overflow-hidden">
                          <div className="h-full bg-[#38bdac]/60 rounded-full transition-all" style={{ width: `${pct}%` }} />
                        </div>
                        <span className="text-gray-400 text-xs w-10 text-right">{count}</span>
                      </div>
                    )
                  })}
                </div>
              ) : (
                <div className="text-center py-8">
                  <p className="text-gray-500 text-sm">点击「刷新数据」加载统计</p>
                </div>
              )}
            </div>
          </div>
        </TabsContent>

        {/* ===== 规则配置 ===== */}
        <TabsContent value="rules">
          <div className="mb-4 flex items-center justify-between">
            <p className="text-gray-400 text-sm">用户旅程引导规则，定义各行为节点的触发条件与引导内容</p>
            <div className="flex items-center gap-2">
              <Button variant="outline" onClick={loadRules} disabled={rulesLoading} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent">
                <RefreshCw className={`w-4 h-4 mr-2 ${rulesLoading ? 'animate-spin' : ''}`} /> 刷新
              </Button>
              <Button onClick={() => { setEditingRule(null); setRuleForm({ title: '', description: '', trigger: '', sort: 0, enabled: true }); setShowRuleModal(true) }} className="bg-[#38bdac] hover:bg-[#2da396] text-white">
                <Plus className="w-4 h-4 mr-2" /> 添加规则
              </Button>
            </div>
          </div>

          {rulesLoading ? (
            <div className="flex items-center justify-center py-12"><RefreshCw className="w-6 h-6 text-[#38bdac] animate-spin" /></div>
          ) : rules.length === 0 ? (
            <div className="text-center py-16 bg-[#0f2137] rounded-lg border border-gray-700/50">
              <BookOpen className="w-12 h-12 text-[#38bdac]/30 mx-auto mb-4" />
              <p className="text-gray-400 mb-4">暂无规则（重启服务将自动写入10条默认规则）</p>
              <Button onClick={loadRules} className="bg-[#38bdac] hover:bg-[#2da396] text-white"><RefreshCw className="w-4 h-4 mr-2" /> 重新加载</Button>
            </div>
          ) : (
            <div className="space-y-2">
              {rules.map((rule) => (
                <div key={rule.id} className={`p-4 rounded-lg border transition-all ${rule.enabled ? 'bg-[#0f2137] border-gray-700/50' : 'bg-[#0a1628]/50 border-gray-700/30 opacity-55'}`}>
                  <div className="flex items-start justify-between">
                    <div className="flex-1">
                      <div className="flex items-center gap-2 flex-wrap mb-1">
                        <PenLine className="w-4 h-4 text-[#38bdac] shrink-0" />
                        <span className="text-white font-medium">{rule.title}</span>
                        {rule.trigger && <Badge className="bg-[#38bdac]/10 text-[#38bdac] border border-[#38bdac]/30 text-xs">触发：{rule.trigger}</Badge>}
                        <Badge className={`text-xs border-0 ${rule.enabled ? 'bg-green-500/20 text-green-400' : 'bg-gray-500/20 text-gray-400'}`}>{rule.enabled ? '启用' : '禁用'}</Badge>
                      </div>
                      {rule.description && <p className="text-gray-400 text-sm ml-6">{rule.description}</p>}
                    </div>
                    <div className="flex items-center gap-2 ml-4 shrink-0">
                      <Switch checked={rule.enabled} onCheckedChange={() => handleToggleRule(rule)} />
                      <Button variant="ghost" size="sm" onClick={() => { setEditingRule(rule); setRuleForm({ title: rule.title, description: rule.description, trigger: rule.trigger, sort: rule.sort, enabled: rule.enabled }); setShowRuleModal(true) }} className="text-gray-400 hover:text-[#38bdac] hover:bg-[#38bdac]/10"><Edit3 className="w-4 h-4" /></Button>
                      <Button variant="ghost" size="sm" onClick={() => handleDeleteRule(rule.id)} className="text-red-400 hover:text-red-300 hover:bg-red-500/10"><Trash2 className="w-4 h-4" /></Button>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </TabsContent>

        {/* ===== VIP 角色 ===== */}
        <TabsContent value="vip-roles">
          <div className="mb-4 flex items-center justify-between">
            <p className="text-gray-400 text-sm">管理用户 VIP 角色分类，这些角色将在用户详情和会员展示中使用</p>
            <div className="flex items-center gap-2">
              <Button variant="outline" onClick={loadVipRoles} disabled={vipRolesLoading} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent">
                <RefreshCw className={`w-4 h-4 mr-2 ${vipRolesLoading ? 'animate-spin' : ''}`} /> 刷新
              </Button>
              <Button onClick={() => { setEditingVipRole(null); setVipRoleForm({ name: '', sort: 0 }); setShowVipRoleModal(true) }} className="bg-[#38bdac] hover:bg-[#2da396] text-white">
                <Plus className="w-4 h-4 mr-2" /> 添加角色
              </Button>
            </div>
          </div>

          {vipRolesLoading ? (
            <div className="flex items-center justify-center py-12"><RefreshCw className="w-6 h-6 text-[#38bdac] animate-spin" /></div>
          ) : vipRoles.length === 0 ? (
            <div className="text-center py-16 bg-[#0f2137] rounded-lg border border-gray-700/50">
              <Crown className="w-12 h-12 text-amber-400/30 mx-auto mb-4" />
              <p className="text-gray-400 mb-4">暂无 VIP 角色</p>
              <Button onClick={() => { setEditingVipRole(null); setVipRoleForm({ name: '', sort: 0 }); setShowVipRoleModal(true) }} className="bg-[#38bdac] hover:bg-[#2da396] text-white"><Plus className="w-4 h-4 mr-2" /> 添加第一个角色</Button>
            </div>
          ) : (
            <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
              {vipRoles.map((role) => (
                <div key={role.id} className="p-4 bg-[#0f2137] border border-amber-500/20 rounded-xl hover:border-amber-500/40 transition-all group">
                  <div className="flex items-start justify-between mb-2">
                    <div className="flex items-center gap-2">
                      <Crown className="w-4 h-4 text-amber-400" />
                      <span className="text-white font-medium">{role.name}</span>
                    </div>
                    <div className="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
                      <button type="button" onClick={() => { setEditingVipRole(role); setVipRoleForm({ name: role.name, sort: role.sort }); setShowVipRoleModal(true) }} className="text-gray-500 hover:text-[#38bdac]"><Edit3 className="w-3.5 h-3.5" /></button>
                      <button type="button" onClick={() => handleDeleteVipRole(role.id)} className="text-gray-500 hover:text-red-400"><Trash2 className="w-3.5 h-3.5" /></button>
                    </div>
                  </div>
                  <p className="text-gray-600 text-xs">排序: {role.sort}</p>
                </div>
              ))}
            </div>
          )}
        </TabsContent>
      </Tabs>

      {/* ===== 弹框组件 ===== */}

      {/* 添加/编辑用户 */}
      <Dialog open={showUserModal} onOpenChange={setShowUserModal}>
        <DialogContent className="bg-[#0f2137] border-gray-700 text-white max-w-lg">
          <DialogHeader><DialogTitle className="text-white flex items-center gap-2">{editingUser ? <Edit3 className="w-5 h-5 text-[#38bdac]" /> : <UserPlus className="w-5 h-5 text-[#38bdac]" />}{editingUser ? '编辑用户' : '添加用户'}</DialogTitle></DialogHeader>
          <div className="space-y-4 py-4">
            <div className="space-y-2"><Label className="text-gray-300">手机号</Label><Input className="bg-[#0a1628] border-gray-700 text-white" placeholder="请输入手机号" value={formData.phone} onChange={(e) => setFormData({ ...formData, phone: e.target.value })} disabled={!!editingUser} /></div>
            <div className="space-y-2"><Label className="text-gray-300">昵称</Label><Input className="bg-[#0a1628] border-gray-700 text-white" placeholder="请输入昵称" value={formData.nickname} onChange={(e) => setFormData({ ...formData, nickname: e.target.value })} /></div>
            <div className="space-y-2"><Label className="text-gray-300">{editingUser ? '新密码 (留空则不修改)' : '密码'}</Label><Input type="password" className="bg-[#0a1628] border-gray-700 text-white" placeholder={editingUser ? '留空则不修改' : '请输入密码'} value={formData.password} onChange={(e) => setFormData({ ...formData, password: e.target.value })} /></div>
            <div className="flex items-center justify-between"><Label className="text-gray-300">管理员权限</Label><Switch checked={formData.isAdmin} onCheckedChange={(c) => setFormData({ ...formData, isAdmin: c })} /></div>
            <div className="flex items-center justify-between"><Label className="text-gray-300">已购全书</Label><Switch checked={formData.hasFullBook} onCheckedChange={(c) => setFormData({ ...formData, hasFullBook: c })} /></div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setShowUserModal(false)} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent"><X className="w-4 h-4 mr-2" />取消</Button>
            <Button onClick={handleSaveUser} disabled={isSaving} className="bg-[#38bdac] hover:bg-[#2da396] text-white"><Save className="w-4 h-4 mr-2" />{isSaving ? '保存中...' : '保存'}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 修改密码 */}
      <Dialog open={showPasswordModal} onOpenChange={setShowPasswordModal}>
        <DialogContent className="bg-[#0f2137] border-gray-700 text-white max-w-md">
          <DialogHeader><DialogTitle className="text-white flex items-center gap-2"><Key className="w-5 h-5 text-[#38bdac]" />修改密码</DialogTitle></DialogHeader>
          <div className="space-y-4 py-4">
            <div className="bg-[#0a1628] rounded-lg p-3"><p className="text-gray-400 text-sm">用户：{editingUser?.nickname}</p><p className="text-gray-400 text-sm">手机号：{editingUser?.phone}</p></div>
            <div className="space-y-2"><Label className="text-gray-300">新密码</Label><Input type="password" className="bg-[#0a1628] border-gray-700 text-white" placeholder="请输入新密码 (至少6位)" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} /></div>
            <div className="space-y-2"><Label className="text-gray-300">确认密码</Label><Input type="password" className="bg-[#0a1628] border-gray-700 text-white" placeholder="请再次输入" value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} /></div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setShowPasswordModal(false)} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent">取消</Button>
            <Button onClick={handleSavePassword} disabled={isSaving} className="bg-[#38bdac] hover:bg-[#2da396] text-white">{isSaving ? '保存中...' : '确认修改'}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 添加/编辑规则 */}
      <Dialog open={showRuleModal} onOpenChange={setShowRuleModal}>
        <DialogContent className="bg-[#0f2137] border-gray-700 text-white max-w-lg">
          <DialogHeader><DialogTitle className="text-white flex items-center gap-2"><PenLine className="w-5 h-5 text-[#38bdac]" />{editingRule ? '编辑规则' : '添加规则'}</DialogTitle></DialogHeader>
          <div className="space-y-4 py-4">
            <div className="space-y-2"><Label className="text-gray-300">规则标题 *</Label><Input className="bg-[#0a1628] border-gray-700 text-white" placeholder="例：匹配后填写头像、付款1980需填写信息" value={ruleForm.title} onChange={(e) => setRuleForm({ ...ruleForm, title: e.target.value })} /></div>
            <div className="space-y-2"><Label className="text-gray-300">规则描述</Label><Textarea className="bg-[#0a1628] border-gray-700 text-white min-h-[80px] resize-none" placeholder="详细说明规则内容..." value={ruleForm.description} onChange={(e) => setRuleForm({ ...ruleForm, description: e.target.value })} /></div>
            <div className="space-y-2"><Label className="text-gray-300">触发条件</Label><Input className="bg-[#0a1628] border-gray-700 text-white" placeholder="例：完成匹配、付款后、注册时" value={ruleForm.trigger} onChange={(e) => setRuleForm({ ...ruleForm, trigger: e.target.value })} /></div>
            <div className="flex items-center justify-between"><div><Label className="text-gray-300">启用状态</Label></div><Switch checked={ruleForm.enabled} onCheckedChange={(c) => setRuleForm({ ...ruleForm, enabled: c })} /></div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setShowRuleModal(false)} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent"><X className="w-4 h-4 mr-2" />取消</Button>
            <Button onClick={handleSaveRule} disabled={isSaving} className="bg-[#38bdac] hover:bg-[#2da396] text-white"><Save className="w-4 h-4 mr-2" />{isSaving ? '保存中...' : '保存'}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 添加/编辑 VIP 角色 */}
      <Dialog open={showVipRoleModal} onOpenChange={setShowVipRoleModal}>
        <DialogContent className="bg-[#0f2137] border-gray-700 text-white max-w-md">
          <DialogHeader><DialogTitle className="text-white flex items-center gap-2"><Crown className="w-5 h-5 text-amber-400" />{editingVipRole ? '编辑 VIP 角色' : '添加 VIP 角色'}</DialogTitle></DialogHeader>
          <div className="space-y-4 py-4">
            <div className="space-y-2"><Label className="text-gray-300">角色名称 *</Label><Input className="bg-[#0a1628] border-gray-700 text-white" placeholder="例：创业者、资源整合者、技术咖" value={vipRoleForm.name} onChange={(e) => setVipRoleForm({ ...vipRoleForm, name: e.target.value })} /></div>
            <div className="space-y-2"><Label className="text-gray-300">排序（越小越前）</Label><Input type="number" className="bg-[#0a1628] border-gray-700 text-white" value={vipRoleForm.sort} onChange={(e) => setVipRoleForm({ ...vipRoleForm, sort: parseInt(e.target.value) || 0 })} /></div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setShowVipRoleModal(false)} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent"><X className="w-4 h-4 mr-2" />取消</Button>
            <Button onClick={handleSaveVipRole} disabled={isSaving} className="bg-[#38bdac] hover:bg-[#2da396] text-white"><Save className="w-4 h-4 mr-2" />{isSaving ? '保存中...' : '保存'}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 绑定关系 */}
      <Dialog open={showReferralsModal} onOpenChange={setShowReferralsModal}>
        <DialogContent className="bg-[#0f2137] border-gray-700 text-white max-w-2xl max-h-[80vh] overflow-auto">
          <DialogHeader><DialogTitle className="text-white flex items-center gap-2"><Users className="w-5 h-5 text-[#38bdac]" />绑定关系 - {selectedUserForReferrals?.nickname}</DialogTitle></DialogHeader>
          <div className="space-y-4 py-4">
            <div className="grid grid-cols-4 gap-3">
              <div className="bg-[#0a1628] rounded-lg p-3 text-center"><div className="text-2xl font-bold text-[#38bdac]">{(referralsData.stats?.total as number) || 0}</div><div className="text-xs text-gray-400">绑定总数</div></div>
              <div className="bg-[#0a1628] rounded-lg p-3 text-center"><div className="text-2xl font-bold text-green-400">{(referralsData.stats?.purchased as number) || 0}</div><div className="text-xs text-gray-400">已付费</div></div>
              <div className="bg-[#0a1628] rounded-lg p-3 text-center"><div className="text-2xl font-bold text-yellow-400">¥{((referralsData.stats?.earnings as number) || 0).toFixed(2)}</div><div className="text-xs text-gray-400">累计收益</div></div>
              <div className="bg-[#0a1628] rounded-lg p-3 text-center"><div className="text-2xl font-bold text-orange-400">¥{((referralsData.stats?.pendingEarnings as number) || 0).toFixed(2)}</div><div className="text-xs text-gray-400">待提现</div></div>
            </div>
            {referralsLoading ? <div className="flex items-center justify-center py-8"><RefreshCw className="w-5 h-5 text-[#38bdac] animate-spin" /><span className="ml-2 text-gray-400">加载中...</span></div>
              : (referralsData.referrals?.length ?? 0) > 0 ? (
                <div className="space-y-2 max-h-[300px] overflow-y-auto">
                  {(referralsData.referrals ?? []).map((ref: unknown, i: number) => {
                    const r = ref as { id?: string; nickname?: string; phone?: string; hasOpenId?: boolean; status?: string; purchasedSections?: number; createdAt?: string }
                    return (
                      <div key={r.id || i} className="flex items-center justify-between bg-[#0a1628] rounded-lg p-3">
                        <div className="flex items-center gap-3">
                          <div className="w-8 h-8 rounded-full bg-[#38bdac]/20 flex items-center justify-center text-sm text-[#38bdac]">{r.nickname?.charAt(0) || '?'}</div>
                          <div><div className="text-white text-sm">{r.nickname}</div><div className="text-xs text-gray-500">{r.phone || (r.hasOpenId ? '微信用户' : '未绑定')}</div></div>
                        </div>
                        <div className="flex items-center gap-2">
                          {r.status === 'vip' && <Badge className="bg-green-500/20 text-green-400 border-0 text-xs">全书已购</Badge>}
                          {r.status === 'paid' && <Badge className="bg-blue-500/20 text-blue-400 border-0 text-xs">已付费{r.purchasedSections}章</Badge>}
                          {r.status === 'free' && <Badge className="bg-gray-500/20 text-gray-400 border-0 text-xs">未付费</Badge>}
                          <span className="text-xs text-gray-500">{r.createdAt ? new Date(r.createdAt).toLocaleDateString() : ''}</span>
                        </div>
                      </div>
                    )
                  })}
                </div>
              ) : <div className="text-center py-8 text-gray-500">暂无绑定用户</div>}
          </div>
          <DialogFooter><Button variant="outline" onClick={() => setShowReferralsModal(false)} className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent">关闭</Button></DialogFooter>
        </DialogContent>
      </Dialog>

      <UserDetailModal open={showDetailModal} onClose={() => setShowDetailModal(false)} userId={selectedUserIdForDetail} onUserUpdated={loadUsers} />
      <SetVipModal open={showSetVipModal} onClose={() => { setShowSetVipModal(false); setSelectedUserForVip(null) }} userId={selectedUserForVip?.id ?? null} userNickname={selectedUserForVip?.nickname} onSaved={loadUsers} />
    </div>
  )
}
