import toast from '@/utils/toast'
import { normalizeImageUrl } from '@/lib/utils'
import { useState, useEffect, useMemo } from 'react'
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Switch } from '@/components/ui/switch'
import {
  User,
  Phone,
  MapPin,
  RefreshCw,
  Link2,
  BookOpen,
  ShoppingBag,
  Users,
  MessageCircle,
  Clock,
  Save,
  X,
  Tag,
  Zap,
  Search,
  CheckCircle2,
  Crown,
  Key,
  Navigation,
} from 'lucide-react'
import { get, put, post } from '@/api/client'

interface UserDetailModalProps {
  open: boolean
  onClose: () => void
  userId: string | null
  onUserUpdated?: () => void
}

interface UserDetail {
  id: string
  phone?: string
  nickname: string
  avatar?: string
  wechatId?: string
  openId?: string
  referralCode?: string
  referredBy?: string
  hasFullBook?: boolean
  isAdmin?: boolean
  earnings?: number
  pendingEarnings?: number
  referralCount?: number
  createdAt?: string
  updatedAt?: string
  tags?: string
  ckbTags?: string
  ckbSyncedAt?: string
  isVip?: boolean
  vipExpireDate?: string | null
  vipName?: string | null
  vipAvatar?: string | null
  vipProject?: string | null
  vipContact?: string | null
  vipBio?: string | null
  vipRole?: string | null
  // 扩展字段
  mbti?: string
  region?: string
  industry?: string
  position?: string
}

interface UserTrack {
  id: string
  action: string
  actionLabel?: string
  target?: string
  chapterTitle?: string
  module?: string
  moduleLabel?: string
  createdAt: string
  timeAgo?: string
}

interface InboundVisitItem {
  seq: number
  visitedAt?: string
  referrerId?: string
  referrerNickname?: string
  referrerAvatar?: string
  source?: string
  page?: string
}

interface InboundSourceData {
  totalVisits?: number
  firstVisit?: InboundVisitItem
  latestVisit?: InboundVisitItem
  activeBinding?: {
    referrerId?: string
    referrerNickname?: string
    referrerAvatar?: string
    referralCode?: string
    bindingDate?: string
    expiryDate?: string
  }
  visits?: InboundVisitItem[]
}

interface ShensheShouData {
  rfm_score?: number
  user_level?: string
  tags?: string[]
  last_active?: string
  phone?: string
}

const TRACK_ACTION_LABELS: Record<string, string> = {
  view_chapter: '浏览章节',
  purchase: '购买',
  match: '派对匹配',
  login: '登录',
  register: '注册',
  share: '分享',
  bind_phone: '绑定手机',
  bind_wechat: '绑定微信',
  fill_profile: '完善资料',
  fill_avatar: '设置头像',
  visit_page: '访问页面',
  first_pay: '首次付款',
  vip_activate: '开通会员',
  click_super: '点击超级个体',
  lead_submit: '提交留资',
  withdraw: '申请提现',
  referral_bind: '绑定推荐人',
  card_click: '点击名片',
  btn_click: '按钮点击',
  tab_click: '切换标签',
  nav_click: '导航点击',
  page_view: '页面浏览',
  search: '搜索',
}

function labelTrackAction(action: string) {
  return TRACK_ACTION_LABELS[action] || action || '行为'
}

/** 根据行为轨迹统计推断运营标签（供标签体系 Tab 展示，可一键合并到已选） */
function inferTagsFromJourney(trackStats: Record<string, number>, user: UserDetail | null): string[] {
  const set = new Set<string>()
  const has = (a: string) => (trackStats[a] ?? 0) > 0
  if (has('purchase') || has('first_pay') || has('vip_activate')) set.add('已付费')
  if (has('lead_submit') || has('click_super')) set.add('高意向')
  if (has('view_chapter')) set.add('想学习')
  if (has('match')) set.add('找合伙人')
  if (has('withdraw')) set.add('有提现行为')
  if (has('referral_bind')) set.add('推广参与')
  if (has('fill_profile') || has('fill_avatar') || has('bind_phone')) set.add('资料完善中')
  if (user?.hasFullBook) set.add('全书读者')
  if (user?.isVip) set.add('VIP会员')
  if (user?.mbti && /^[EI][NS][FT][JP]$/i.test(user.mbti)) set.add(String(user.mbti).toUpperCase())
  return Array.from(set)
}

export function UserDetailModal({
  open,
  onClose,
  userId,
  onUserUpdated,
}: UserDetailModalProps) {
  const [user, setUser] = useState<UserDetail | null>(null)
  const [tracks, setTracks] = useState<UserTrack[]>([])
  const [trackStats, setTrackStats] = useState<Record<string, number>>({})
  const [referrals, setReferrals] = useState<unknown[]>([])
  const [inboundSource, setInboundSource] = useState<InboundSourceData | null>(null)
  const [balanceData, setBalanceData] = useState<{ balance: number; transactions: Array<{ id: string; type: string; amount: number; orderId?: string; createdAt: string }> } | null>(null)
  const [loading, setLoading] = useState(false)
  const [syncing, setSyncing] = useState(false)
  const [saving, setSaving] = useState(false)
  const [activeTab, setActiveTab] = useState('info')
  const [editPhone, setEditPhone] = useState('')
  const [editWechatId, setEditWechatId] = useState('')
  const [editNickname, setEditNickname] = useState('')
  const [editTags, setEditTags] = useState<string[]>([])
  const [newTag, setNewTag] = useState('')

  // 修改密码
  const [newPassword, setNewPassword] = useState('')
  const [confirmPassword, setConfirmPassword] = useState('')
  const [passwordSaving, setPasswordSaving] = useState(false)

  // 设成超级个体（VIP）
  const [vipForm, setVipForm] = useState({ isVip: false, vipExpireDate: '', vipRole: '', vipName: '', vipProject: '', vipContact: '', vipBio: '' })
  const [vipRoles, setVipRoles] = useState<{ id: number; name: string }[]>([])

  // 调整余额
  const [adjustBalanceOpen, setAdjustBalanceOpen] = useState(false)
  const [adjustAmount, setAdjustAmount] = useState('')
  const [adjustRemark, setAdjustRemark] = useState('')
  const [adjustLoading, setAdjustLoading] = useState(false)

  // 用户资料完善（神射手）
  const [sssLoading, setSssLoading] = useState(false)
  const [sssData, setSssData] = useState<ShensheShouData | null>(null)
  const [sssError, setSssError] = useState<string | null>(null)
  const [sssQueryPhone, setSssQueryPhone] = useState('')
  const [sssQueryWechatId, setSssQueryWechatId] = useState('')
  const [sssQueryOpenId, setSssQueryOpenId] = useState('')
  const [batchIngestLoading, setBatchIngestLoading] = useState(false)
  const [batchIngestResult, setBatchIngestResult] = useState<Record<string, unknown> | null>(null)
  const [avatarBroken, setAvatarBroken] = useState(false)
  const [mbtiAvatarsMap, setMbtiAvatarsMap] = useState<Record<string, string>>({})
  const [purchaseList, setPurchaseList] = useState<{ orderSn: string; productType: string; productId?: string; amount: number; createdAt: string }[]>([])

  useEffect(() => {
    if (open && userId) {
      setAvatarBroken(false)
      setActiveTab('info')
      setSssData(null)
      setSssError(null)
      setBatchIngestResult(null)
      setNewPassword('')
      setConfirmPassword('')
      loadUserDetail()
      get<{ success?: boolean; data?: { id: number; name: string }[] }>('/api/db/vip-roles').then((r) => {
        if (r?.success && (r as { data?: { id: number; name: string }[] }).data) setVipRoles((r as { data: { id: number; name: string }[] }).data)
      }).catch(() => {})
    }
  }, [open, userId])

  useEffect(() => {
    if (!open) return
    get<{ success?: boolean; avatars?: Record<string, string> }>('/api/admin/mbti-avatars')
      .then((r) => {
        if (r?.avatars && typeof r.avatars === 'object') setMbtiAvatarsMap(r.avatars)
        else setMbtiAvatarsMap({})
      })
      .catch(() => setMbtiAvatarsMap({}))
  }, [open])

  const resolveAvatarByMbti = (avatar?: string | null, mbti?: string | null): string => {
    const av = (avatar || '').trim()
    if (av) return normalizeImageUrl(av)
    const key = (mbti || '').trim().toUpperCase()
    if (!/^[EI][NS][FT][JP]$/.test(key)) return ''
    return (mbtiAvatarsMap[key] || '').trim()
  }

  async function loadUserDetail() {
    if (!userId) return
    setLoading(true)
    try {
      const userData = await get<{ success?: boolean; user?: UserDetail }>(
        `/api/db/users?id=${encodeURIComponent(userId)}`,
      )
      if (userData?.success && userData.user) {
        const u = userData.user
        setUser(u)
        setEditPhone(u.phone || '')
        setEditWechatId(u.wechatId || '')
        setEditNickname(u.nickname || '')
        setSssQueryPhone(u.phone || '')
        setSssQueryWechatId(u.wechatId || '')
        setSssQueryOpenId(u.openId || '')
        try {
          setEditTags(typeof u.tags === 'string' ? (JSON.parse(u.tags || '[]') as string[]) : [])
        } catch {
          setEditTags([])
        }
        setVipForm({
          isVip: !!(u.isVip ?? false),
          vipExpireDate: u.vipExpireDate ? String(u.vipExpireDate).slice(0, 10) : '',
          vipRole: String(u.vipRole ?? ''),
          vipName: String(u.vipName ?? ''),
          vipProject: String(u.vipProject ?? ''),
          vipContact: String(u.vipContact ?? ''),
          vipBio: String(u.vipBio ?? ''),
        })
      }
      // 行为轨迹（用户旅程）
      try {
        const trackData = await get<{ success?: boolean; tracks?: UserTrack[]; stats?: Record<string, number> }>(
          `/api/admin/user/track?userId=${encodeURIComponent(userId)}&limit=100`,
        )
        if (trackData?.success) {
          setTrackStats(trackData.stats && typeof trackData.stats === 'object' ? trackData.stats : {})
          const list = trackData.tracks || []
          setTracks(
            list.map((t) => ({
              ...t,
              actionLabel: t.actionLabel || t.action,
              timeAgo: t.timeAgo || '',
            })),
          )
        } else {
          setTrackStats({})
          setTracks([])
        }
      } catch {
        setTrackStats({})
        setTracks([])
      }
      // 关系链路
      try {
        const refData = await get<{ success?: boolean; referrals?: unknown[]; inboundSource?: InboundSourceData }>(
          `/api/db/users/referrals?userId=${encodeURIComponent(userId)}`,
        )
        if (refData?.success) {
          setReferrals(refData.referrals || [])
          setInboundSource(refData.inboundSource || null)
        } else {
          setReferrals([])
          setInboundSource(null)
        }
      } catch {
        setReferrals([])
        setInboundSource(null)
      }
      try {
        const balData = await get<{ success?: boolean; data?: { balance: number; transactions: Array<{ id: string; type: string; amount: number; orderId?: string; createdAt: string }> } }>(
          `/api/admin/users/${encodeURIComponent(userId)}/balance`,
        )
        if (balData?.success && balData.data) setBalanceData(balData.data)
        else setBalanceData(null)
      } catch { setBalanceData(null) }
      try {
        const ordersData = await get<{ success?: boolean; orders?: { orderSn: string; productType: string; productId?: string; amount: number; createdAt: string }[] }>(
          `/api/orders?userId=${encodeURIComponent(userId)}&status=paid&pageSize=50`,
        )
        if (ordersData?.success && ordersData.orders) setPurchaseList(ordersData.orders)
        else setPurchaseList([])
      } catch { setPurchaseList([]) }
    } catch (e) {
      console.error('Load user detail error:', e)
    } finally {
      setLoading(false)
    }
  }

  async function handleSyncCKB() {
    if (!user?.phone) { toast.info('用户未绑定手机号，无法同步'); return }
    setSyncing(true)
    try {
      const data = await post<{ success?: boolean; error?: string }>('/api/ckb/sync', {
        action: 'full_sync',
        phone: user.phone,
        userId: user.id,
      })
      if (data?.success) { toast.success('同步成功'); loadUserDetail() }
      else toast.error('同步失败: ' + (data as { error?: string })?.error)
    } catch (e) {
      console.error('Sync CKB error:', e)
      toast.error('同步失败')
    } finally {
      setSyncing(false)
    }
  }

  async function handleSave() {
    if (!user) return
    if (vipForm.isVip && !vipForm.vipExpireDate.trim()) {
      toast.error('开启 VIP 请填写有效到期日')
      return
    }
    setSaving(true)
    try {
      const payload: Record<string, unknown> = {
        id: user.id,
        phone: editPhone.trim() || undefined,
        wechatId: editWechatId.trim(),
        nickname: editNickname || undefined,
        tags: JSON.stringify(editTags),
        // 超级个体/VIP 相关字段一并保存
        isVip: vipForm.isVip,
        vipExpireDate: vipForm.isVip ? vipForm.vipExpireDate : undefined,
        vipRole: vipForm.vipRole || undefined,
        vipName: vipForm.vipName || undefined,
        vipProject: vipForm.vipProject || undefined,
        vipContact: vipForm.vipContact || undefined,
        vipBio: vipForm.vipBio || undefined,
      }
      const data = await put<{ success?: boolean; error?: string }>('/api/db/users', payload)
      if (data?.success) {
        toast.success('保存成功')
        loadUserDetail()
        onUserUpdated?.()
      } else {
        toast.error('保存失败: ' + (data as { error?: string })?.error)
      }
    } catch (e) {
      console.error('Save user error:', e)
      toast.error('保存失败')
    } finally {
      setSaving(false)
    }
  }

  const addTag = () => {
    if (newTag && !editTags.includes(newTag)) {
      setEditTags([...editTags, newTag])
      setNewTag('')
    }
  }

  const removeTag = (tag: string) => setEditTags(editTags.filter((t) => t !== tag))

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

  async function handleAdjustBalance() {
    if (!user) return
    const amt = parseFloat(adjustAmount)
    if (Number.isNaN(amt) || amt === 0) { toast.error('请输入有效金额（正数增加、负数扣减）'); return }
    setAdjustLoading(true)
    try {
      const res = await post<{ success?: boolean; error?: string }>(`/api/admin/users/${user.id}/balance/adjust`, {
        amount: amt,
        remark: adjustRemark || undefined,
      })
      if (res?.success) {
        toast.success('余额已调整')
        setAdjustBalanceOpen(false)
        setAdjustAmount('')
        setAdjustRemark('')
        loadUserDetail()
        onUserUpdated?.()
      } else {
        toast.error('调整失败: ' + (res?.error || ''))
      }
    } catch { toast.error('调整失败') } finally { setAdjustLoading(false) }
  }

  // 用户资料完善查询（支持多维度）
  async function handleSSSQuery() {
    if (!sssQueryPhone && !sssQueryOpenId && !sssQueryWechatId) {
      setSssError('请至少输入手机号、微信号或 OpenID 中的一项')
      return
    }
    setSssLoading(true)
    setSssError(null)
    setSssData(null)
    try {
      const params = new URLSearchParams()
      if (sssQueryPhone) params.set('phone', sssQueryPhone)
      if (sssQueryOpenId) params.set('openId', sssQueryOpenId)
      if (sssQueryWechatId) params.set('wechatId', sssQueryWechatId)
      const data = await get<{ success?: boolean; data?: ShensheShouData; error?: string }>(
        `/api/admin/shensheshou/query?${params}`,
      )
      if (data?.success && data.data) {
        setSssData(data.data)
        // 自动回填到用户信息
        if (user) await handleSSSEnrich(data.data)
      }
      else setSssError(data?.error || '未查询到数据，该用户可能未在神射手收录')
    } catch (e) {
      console.error('SSS query error:', e)
      setSssError('请求失败，请检查神射手接口配置')
    } finally {
      setSssLoading(false)
    }
  }

  // 查询后自动回填用户基础信息
  async function handleSSSEnrich(_sssResult?: ShensheShouData) {
    if (!user) return
    try {
      await post('/api/admin/shensheshou/enrich', {
        userId: user.id,
        phone: sssQueryPhone || user.phone || '',
        openId: sssQueryOpenId || user.openId || '',
        wechatId: sssQueryWechatId || user.wechatId || '',
      })
      loadUserDetail()
    } catch (e) {
      console.error('SSS enrich error:', e)
    }
  }

  // 神射手 - 将当前用户信息推送/同步到神射手
  async function handleSSSIngest() {
    if (!user) return
    setBatchIngestLoading(true)
    setBatchIngestResult(null)
    try {
      // 购买意向：看浏览/购买轨迹，把章节名备注给神射手（需求：便于 wepop/外部侧识别“想买哪章”）
      const purchaseIntentChapterTitles = Array.from(
        new Set(
          tracks
            .filter((t) => t.action === 'view_chapter' || t.action === 'purchase' || t.action === 'first_pay')
            .map((t) => (t.chapterTitle || t.target || '').trim())
            .filter(Boolean),
        ),
      ).slice(0, 12)
      const purchaseIntentActions = {
        viewChapter: trackStats.view_chapter || 0,
        purchase: trackStats.purchase || 0,
        firstPay: trackStats.first_pay || 0,
      }
      const purchaseIntentRemark = purchaseIntentChapterTitles.length > 0
        ? `意向章节：${purchaseIntentChapterTitles.join('、')}`
        : ''
      const payload = {
        users: [{
          phone: user.phone || '',
          name: user.nickname || '',
          openId: user.openId || '',
          tags: editTags,
          purchaseIntent: purchaseIntentActions,
          purchaseIntentChapters: purchaseIntentChapterTitles,
          remark: purchaseIntentRemark,
        }]
      }
      const data = await post<{ success?: boolean; data?: Record<string, unknown>; error?: string }>(
        '/api/admin/shensheshou/ingest',
        payload,
      )
      if (data?.success && data.data) setBatchIngestResult(data.data)
      else setBatchIngestResult({ error: data?.error || '推送失败' })
    } catch (e) {
      console.error('SSS ingest error:', e)
      setBatchIngestResult({ error: '请求失败' })
    } finally {
      setBatchIngestLoading(false)
    }
  }

  const getActionIcon = (action: string) => {
    const icons: Record<string, React.ComponentType<{ className?: string }>> = {
      view_chapter: BookOpen,
      purchase: ShoppingBag,
      match: Users,
      login: User,
      register: User,
      share: Link2,
      bind_phone: Phone,
      bind_wechat: MessageCircle,
      fill_profile: Tag,
      fill_avatar: User,
      visit_page: Navigation,
      first_pay: ShoppingBag,
      vip_activate: Crown,
      click_super: Users,
      lead_submit: Phone,
      withdraw: Key,
      referral_bind: Link2,
      card_click: User,
      btn_click: Zap,
      tab_click: Navigation,
      nav_click: Navigation,
      page_view: Navigation,
      search: Navigation,
    }
    const Icon = icons[action] || Clock
    return <Icon className="w-4 h-4" />
  }

  function trackTargetIsOpaqueId(s: string) {
    const t = String(s || '').trim()
    return t.length > 22 && /^[a-zA-Z0-9_-]+$/.test(t)
  }

  const journeyInferredTags = useMemo(
    () => inferTagsFromJourney(trackStats, user),
    [trackStats, user],
  )

  function mergeJourneyTagsIntoSelected() {
    const next = [...editTags]
    for (const t of journeyInferredTags) {
      if (!next.includes(t)) next.push(t)
    }
    setEditTags(next)
    toast.success('已将旅程推断标签合并到已选')
  }

  if (!open) return null

  return (
    <>
    <Dialog open={open} onOpenChange={() => onClose()}>
      <DialogContent className="bg-[#0f2137] border-gray-700 text-white max-w-4xl max-h-[92vh] overflow-hidden flex flex-col p-4 sm:p-5">
        <DialogHeader>
          <DialogTitle className="text-white flex items-center gap-2">
            <User className="w-5 h-5 text-[#38bdac]" />
            用户详情
            {user?.phone && <Badge className="bg-green-500/20 text-green-400 border-0 ml-2">已绑定手机</Badge>}
            {user?.isVip && <Badge className="bg-amber-500/20 text-amber-400 border-0">VIP</Badge>}
          </DialogTitle>
        </DialogHeader>

        {loading ? (
          <div className="flex items-center justify-center py-20">
            <RefreshCw className="w-6 h-6 text-[#38bdac] animate-spin" />
            <span className="ml-2 text-gray-400">加载中...</span>
          </div>
        ) : user ? (
          <div className="flex flex-col min-h-0 flex-1 overflow-hidden">
            {/* 头部：身份 + 收益（紧凑） */}
            <div className="flex flex-col sm:flex-row gap-2.5 p-2.5 bg-[#0a1628] rounded-lg mb-2 shrink-0">
              <div className="flex gap-2.5 min-w-0 flex-1">
                <div className="w-11 h-11 rounded-full bg-[#38bdac]/20 flex items-center justify-center text-lg text-[#38bdac] shrink-0">
                  {resolveAvatarByMbti(user.avatar, user.mbti) && !avatarBroken ? (
                    <img
                      src={resolveAvatarByMbti(user.avatar, user.mbti)}
                      className="w-full h-full rounded-full object-cover"
                      alt=""
                      onError={() => setAvatarBroken(true)}
                    />
                  ) : (
                    user.nickname?.charAt(0) || '?'
                  )}
                </div>
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-1.5 flex-wrap">
                    <h3 className="text-base font-bold text-white leading-tight">{user.nickname}</h3>
                    {user.isAdmin && <Badge className="bg-purple-500/20 text-purple-400 border-0 text-[10px] py-0">管理员</Badge>}
                    {user.hasFullBook && <Badge className="bg-green-500/20 text-green-400 border-0 text-[10px] py-0">全书已购</Badge>}
                    {user.vipRole && <Badge className="bg-amber-500/20 text-amber-400 border-0 text-[10px] py-0">{user.vipRole}</Badge>}
                  </div>
                  {user.referralCode && (
                    <p className="text-[10px] text-gray-500 mt-0.5">
                      推荐码 <code className="text-[#38bdac]">{user.referralCode}</code>
                    </p>
                  )}
                  <div className="mt-1 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-1.5 text-[11px]">
                    <div className="px-2 py-1 rounded bg-[#162840] border border-gray-700/50">
                      <span className="text-gray-500">昵称</span>
                      <p className="text-white truncate">{editNickname || user.nickname || '—'}</p>
                    </div>
                    <div className="px-2 py-1 rounded bg-[#162840] border border-gray-700/50">
                      <span className="text-gray-500">手机号</span>
                      <p className="text-white truncate">{editPhone || '—'}</p>
                    </div>
                    <div className="px-2 py-1 rounded bg-[#162840] border border-gray-700/50">
                      <span className="text-gray-500">微信标识</span>
                      <p className="text-white truncate">{editWechatId || '—'}</p>
                    </div>
                    <div className="px-2 py-1 rounded bg-[#162840] border border-gray-700/50">
                      <span className="text-gray-500">画像</span>
                      <p className="text-[#38bdac] truncate">
                        {[user.region, user.industry, user.position, user.mbti ? `MBTI ${user.mbti}` : ''].filter(Boolean).join(' · ') || '未完善'}
                      </p>
                    </div>
                  </div>
                </div>
              </div>
              <div className="grid grid-cols-2 sm:grid-cols-2 gap-1.5 shrink-0 sm:w-[220px]">
                <div className="rounded-md bg-[#162840] px-2 py-1.5 border border-gray-700/40">
                  <p className="text-[9px] text-gray-500 uppercase tracking-wide">累计佣金</p>
                  <p className="text-sm font-bold text-[#38bdac] leading-tight">¥{(user.earnings ?? 0).toFixed(2)}</p>
                  <p className="text-[9px] text-gray-600">推广/分佣入账</p>
                </div>
                <div className="rounded-md bg-[#162840] px-2 py-1.5 border border-gray-700/40">
                  <p className="text-[9px] text-gray-500">待提现</p>
                  <p className="text-sm font-bold text-yellow-400 leading-tight">¥{(user.pendingEarnings ?? 0).toFixed(2)}</p>
                  <p className="text-[9px] text-gray-600">未打款部分</p>
                </div>
                <div className="rounded-md bg-[#162840] px-2 py-1.5 border border-gray-700/40">
                  <div className="flex items-center justify-between gap-1">
                    <p className="text-[9px] text-gray-500">账户余额</p>
                    <Button
                      type="button"
                      size="sm"
                      variant="ghost"
                      className="h-5 px-1 text-[9px] text-[#38bdac] hover:bg-[#38bdac]/10"
                      onClick={() => {
                        setAdjustAmount('')
                        setAdjustRemark('')
                        setAdjustBalanceOpen(true)
                      }}
                    >
                      调整
                    </Button>
                  </div>
                  <p className="text-sm font-bold text-white leading-tight">¥{(balanceData?.balance ?? 0).toFixed(2)}</p>
                  <p className="text-[9px] text-gray-600">可消费/抵扣</p>
                </div>
                <div className="rounded-md bg-[#162840] px-2 py-1.5 border border-gray-700/40">
                  <p className="text-[9px] text-gray-500">推荐人数</p>
                  <p className="text-sm font-bold text-white leading-tight">{user.referralCount ?? 0}</p>
                  <p className="text-[9px] text-gray-600">{user.createdAt ? `注册 ${new Date(user.createdAt).toLocaleDateString()}` : '—'}</p>
                </div>
              </div>
            </div>

            <Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col min-h-0 overflow-hidden">
              <TabsList className="bg-[#0a1628] border border-gray-700/50 p-0.5 mb-2 flex-wrap h-auto gap-0.5 shrink-0">
                <TabsTrigger value="info" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] text-[11px] px-2 py-1 h-7">
                  用户信息
                </TabsTrigger>
                <TabsTrigger value="journey" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] text-[11px] px-2 py-1 h-7">
                  <Navigation className="w-3 h-3 mr-0.5" />
                  旅程与轨迹
                </TabsTrigger>
                <TabsTrigger value="relations" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] text-[11px] px-2 py-1 h-7">
                  关系链路
                </TabsTrigger>
                <TabsTrigger value="tags" className="data-[state=active]:bg-[#38bdac]/20 data-[state=active]:text-[#38bdac] text-[11px] px-2 py-1 h-7">
                  标签体系
                </TabsTrigger>
              </TabsList>

              {/* ===== 用户信息（紧凑单屏）：基础字段 + 超级个体 + 外部同步合并为一屏滚动 ===== */}
              <TabsContent value="info" className="flex-1 min-h-0 overflow-y-auto space-y-2 pr-0.5">
                <details className="rounded-lg bg-[#0a1628] border border-gray-700/40 p-2 text-[11px] group">
                  <summary className="cursor-pointer text-gray-400 select-none list-none flex items-center gap-1">
                    <span className="group-open:text-[#38bdac]">技术标识</span>
                    <span className="text-gray-600">（用户ID / OpenID，默认折叠）</span>
                  </summary>
                  <div className="mt-2 space-y-1.5 text-gray-300 font-mono text-[10px] break-all border-t border-gray-700/30 pt-2">
                    <p>
                      <span className="text-gray-500 not-italic font-sans">用户ID</span> {user.id}
                    </p>
                    <p>
                      <span className="text-gray-500 not-italic font-sans">OpenID</span> {user.openId || '—'}
                    </p>
                    <p className="text-gray-500 not-italic font-sans leading-snug">
                      OpenID 为微信用户标识；下方「微信标识」为微信号/wxid，供存客宝归属，与 OpenID 不同。
                    </p>
                  </div>
                </details>
                <div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
                  <div className="space-y-1">
                    <Label className="text-gray-400 text-[11px]">昵称</Label>
                    <Input className="bg-[#162840] border-gray-700 text-white h-8 text-xs" placeholder="昵称" value={editNickname} onChange={(e) => setEditNickname(e.target.value)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-gray-400 text-[11px]">手机号（可改，点底部保存生效）</Label>
                    <Input className="bg-[#162840] border-gray-700 text-white h-8 text-xs" placeholder="11 位手机号" value={editPhone} onChange={(e) => setEditPhone(e.target.value)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-gray-400 text-[11px]">微信标识（微信号/wxid，非 OpenID）</Label>
                    <Input className="bg-[#162840] border-gray-700 text-white h-8 text-xs" placeholder="如 wxid_xxx 或自定义微信号" value={editWechatId} onChange={(e) => setEditWechatId(e.target.value)} />
                  </div>
                </div>

                {(user.region || user.industry || user.position || user.mbti) && (
                  <div className="flex flex-wrap gap-1.5 text-[11px]">
                    {user.region && (
                      <span className="px-2 py-0.5 rounded bg-[#162840] text-gray-300">
                        <MapPin className="w-3 h-3 inline mr-0.5" />
                        {user.region}
                      </span>
                    )}
                    {user.industry && <span className="px-2 py-0.5 rounded bg-[#162840] text-gray-300">行业 {user.industry}</span>}
                    {user.position && <span className="px-2 py-0.5 rounded bg-[#162840] text-gray-300">职位 {user.position}</span>}
                    {user.mbti && <span className="px-2 py-0.5 rounded bg-[#38bdac]/15 text-[#38bdac]">MBTI {user.mbti}</span>}
                  </div>
                )}

                <div className="p-2 rounded-lg bg-[#0a1628] border border-amber-500/25">
                  <div className="flex items-center justify-between gap-2">
                    <div className="flex items-center gap-1.5 min-w-0">
                      <Crown className="w-3.5 h-3.5 text-amber-400 shrink-0" />
                      <span className="text-white text-xs font-medium">超级个体</span>
                      {user.isVip && <Badge className="bg-amber-500/20 text-amber-400 border-0 text-[10px] py-0 shrink-0">{user.vipRole || 'VIP'}</Badge>}
                    </div>
                    <Switch className="scale-90" checked={vipForm.isVip} onCheckedChange={(c) => setVipForm((f) => ({ ...f, isVip: c }))} />
                  </div>
                  {vipForm.isVip && (
                    <div className="grid grid-cols-2 sm:grid-cols-3 gap-1.5 mt-2">
                      <div className="space-y-0.5">
                        <Label className="text-gray-500 text-[10px]">到期日</Label>
                        <Input type="date" className="bg-[#162840] border-gray-700 text-white h-7 text-xs" value={vipForm.vipExpireDate} onChange={(e) => setVipForm((f) => ({ ...f, vipExpireDate: e.target.value }))} />
                      </div>
                      <div className="space-y-0.5">
                        <Label className="text-gray-500 text-[10px]">角色</Label>
                        <select className="w-full bg-[#162840] border border-gray-700 text-white rounded px-1.5 h-7 text-xs" value={vipForm.vipRole} onChange={(e) => setVipForm((f) => ({ ...f, vipRole: e.target.value }))}>
                          <option value="">请选择</option>
                          {vipRoles.map((r) => (
                            <option key={r.id} value={r.name}>
                              {r.name}
                            </option>
                          ))}
                        </select>
                      </div>
                      <div className="space-y-0.5">
                        <Label className="text-gray-500 text-[10px]">展示名</Label>
                        <Input className="bg-[#162840] border-gray-700 text-white h-7 text-xs" placeholder="展示名" value={vipForm.vipName} onChange={(e) => setVipForm((f) => ({ ...f, vipName: e.target.value }))} />
                      </div>
                      <div className="space-y-0.5">
                        <Label className="text-gray-500 text-[10px]">项目</Label>
                        <Input className="bg-[#162840] border-gray-700 text-white h-7 text-xs" placeholder="项目" value={vipForm.vipProject} onChange={(e) => setVipForm((f) => ({ ...f, vipProject: e.target.value }))} />
                      </div>
                      <div className="space-y-0.5">
                        <Label className="text-gray-500 text-[10px]">联系方式</Label>
                        <Input className="bg-[#162840] border-gray-700 text-white h-7 text-xs" placeholder="微信/手机" value={vipForm.vipContact} onChange={(e) => setVipForm((f) => ({ ...f, vipContact: e.target.value }))} />
                      </div>
                      <div className="space-y-0.5 sm:col-span-2">
                        <Label className="text-gray-500 text-[10px]">简介</Label>
                        <Input className="bg-[#162840] border-gray-700 text-white h-7 text-xs" placeholder="简短介绍" value={vipForm.vipBio} onChange={(e) => setVipForm((f) => ({ ...f, vipBio: e.target.value }))} />
                      </div>
                    </div>
                  )}
                </div>

                <div className="p-2 rounded-lg bg-[#0a1628] border border-[#38bdac]/20">
                  <div className="flex items-center gap-1.5 mb-1.5">
                    <Zap className="w-3.5 h-3.5 text-[#38bdac]" />
                    <span className="text-white text-xs font-medium">外部资料 · 神射手 / 存客宝（与上方基础信息联动）</span>
                  </div>
                  <div className="grid grid-cols-3 gap-1.5 mb-1.5">
                    <Input className="bg-[#162840] border-gray-700 text-white h-7 text-xs" placeholder="查：手机" value={sssQueryPhone} onChange={(e) => setSssQueryPhone(e.target.value)} />
                    <Input className="bg-[#162840] border-gray-700 text-white h-7 text-xs" placeholder="查：微信号" value={sssQueryWechatId} onChange={(e) => setSssQueryWechatId(e.target.value)} />
                    <Input className="bg-[#162840] border-gray-700 text-white h-7 text-xs" placeholder="查：OpenID" value={sssQueryOpenId} onChange={(e) => setSssQueryOpenId(e.target.value)} />
                  </div>
                  <div className="flex flex-wrap gap-1">
                    <Button size="sm" className="h-7 text-[11px] px-2 bg-[#38bdac] hover:bg-[#2da396]" onClick={handleSSSQuery} disabled={sssLoading}>
                      {sssLoading ? <RefreshCw className="w-3 h-3 animate-spin" /> : <Search className="w-3 h-3 mr-0.5" />}
                      查询回填
                    </Button>
                    <Button size="sm" variant="outline" className="h-7 text-[11px] px-2 border-purple-500/40 text-purple-300" onClick={handleSSSIngest} disabled={batchIngestLoading || !user.phone}>
                      {batchIngestLoading ? '推送…' : '推神射手'}
                    </Button>
                    <Button size="sm" variant="outline" className="h-7 text-[11px] px-2" onClick={handleSyncCKB} disabled={syncing || !user.phone}>
                      {syncing ? '同步…' : '存客宝同步'}
                    </Button>
                  </div>
                  {user.ckbSyncedAt && <p className="text-[10px] text-gray-500 mt-1">最近存客宝同步：{new Date(user.ckbSyncedAt).toLocaleString()}</p>}
                  {sssError && <p className="mt-1 text-red-400 text-[11px]">{sssError}</p>}
                  {sssData && (
                    <div className="mt-1.5 grid grid-cols-2 gap-1.5">
                      <div className="p-1.5 bg-[#162840] rounded text-[11px]">
                        <span className="text-gray-500">RFM</span> <span className="text-[#38bdac] font-semibold">{sssData.rfm_score ?? '—'}</span>
                      </div>
                      <div className="p-1.5 bg-[#162840] rounded text-[11px]">
                        <span className="text-gray-500">等级</span> <span className="text-white font-semibold">{sssData.user_level ?? '—'}</span>
                      </div>
                    </div>
                  )}
                  {batchIngestResult && (
                    <p className="mt-1 text-[11px]">{batchIngestResult.error ? <span className="text-red-400">{String(batchIngestResult.error)}</span> : <span className="text-green-400">推送成功</span>}</p>
                  )}
                </div>

                <div className="p-2 rounded-lg bg-[#0a1628] border border-gray-700/50">
                  <div className="flex items-center gap-1.5 mb-1.5">
                    <Key className="w-3.5 h-3.5 text-yellow-400" />
                    <span className="text-white text-xs font-medium">修改密码</span>
                  </div>
                  <div className="flex flex-col sm:flex-row gap-1.5 sm:items-center">
                    <Input type="password" className="bg-[#162840] border-gray-700 text-white h-7 text-xs flex-1" placeholder="新密码 ≥6 位" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} />
                    <Input type="password" className="bg-[#162840] border-gray-700 text-white h-7 text-xs flex-1" placeholder="确认密码" value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} />
                    <Button size="sm" className="h-7 text-[11px] shrink-0 bg-yellow-500/20 text-yellow-300 border border-yellow-500/35 hover:bg-yellow-500/30" onClick={handleSavePassword} disabled={passwordSaving || !newPassword || !confirmPassword}>
                      {passwordSaving ? '保存中' : '确认修改'}
                    </Button>
                  </div>
                </div>
              </TabsContent>

              {/* ===== 用户旅程 + 行为轨迹 ===== */}
              <TabsContent value="journey" className="flex-1 min-h-0 overflow-y-auto space-y-2 pr-0.5">
                {purchaseList.length > 0 && (
                  <div className="p-2 bg-[#0a1628] rounded-lg border border-amber-500/20">
                    <div className="flex items-center gap-1.5 mb-1.5">
                      <ShoppingBag className="w-3.5 h-3.5 text-amber-400" />
                      <span className="text-white text-xs font-medium">购买清单（{purchaseList.length} 笔）</span>
                    </div>
                    <div className="space-y-1 max-h-[120px] overflow-y-auto">
                      {purchaseList.map((o, i) => (
                        <div key={o.orderSn || i} className="flex items-center justify-between p-1.5 bg-[#162840] rounded text-[11px]">
                          <div className="min-w-0">
                            <span className="text-amber-300">
                              {o.productType === 'fullbook' || o.productType === 'vip' ? '全书/VIP' : `章节 ${o.productId || ''}`}
                            </span>
                            <span className="text-gray-500 ml-2">¥{Number(o.amount || 0).toFixed(2)}</span>
                          </div>
                          <span className="text-gray-500 text-[10px] shrink-0">{o.createdAt ? new Date(o.createdAt).toLocaleString('zh-CN') : ''}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                )}
                <div className="p-2 bg-[#0a1628] rounded-lg flex flex-col gap-1.5 text-[11px]">
                  <div className="flex items-center gap-1.5 text-gray-400">
                    <Navigation className="w-3.5 h-3.5 text-[#38bdac] shrink-0" />
                    <span>全站埋点共 {tracks.length} 条；用于 RFM 与「标签体系」旅程推断</span>
                  </div>
                  {Object.keys(trackStats).length > 0 && (
                    <div className="flex flex-wrap gap-1 pt-1 border-t border-gray-700/40">
                      {Object.entries(trackStats)
                        .sort((a, b) => b[1] - a[1])
                        .map(([act, n]) => (
                          <Badge key={act} variant="outline" className="text-[10px] border-gray-600 text-gray-300 bg-[#162840] py-0 h-5">
                            {labelTrackAction(act)} ×{n}
                          </Badge>
                        ))}
                    </div>
                  )}
                </div>
                <div className="space-y-1.5">
                  {tracks.length > 0 ? (
                    tracks.map((track, idx) => (
                      <div key={track.id} className="flex items-start gap-2 p-2 bg-[#0a1628] rounded-lg">
                        <div className="flex flex-col items-center shrink-0">
                          <div className="w-7 h-7 rounded-full bg-[#38bdac]/20 flex items-center justify-center text-[#38bdac]">{getActionIcon(track.action)}</div>
                          {idx < tracks.length - 1 && <div className="w-0.5 h-3 bg-gray-700/50 mt-0.5" />}
                        </div>
                        <div className="flex-1 pb-0.5 min-w-0 text-xs">
                          <div className="flex items-center gap-1.5 flex-wrap">
                            <span className="text-white font-medium">{track.actionLabel || track.action}</span>
                            {track.moduleLabel && <span className="text-[#38bdac]/90">· {track.moduleLabel}</span>}
                            {track.chapterTitle && <span className="text-gray-500">· {track.chapterTitle}</span>}
                          </div>
                          {track.target &&
                            track.target !== track.chapterTitle &&
                            !trackTargetIsOpaqueId(track.target) && (
                              <p className="text-gray-600 text-[10px] mt-0.5 break-all">详情: {track.target}</p>
                            )}
                          <p className="text-gray-500 text-[10px] mt-0.5">
                            <Clock className="w-3 h-3 inline mr-0.5" />
                            {track.timeAgo ? `${track.timeAgo} · ` : ''}
                            {track.createdAt ? new Date(track.createdAt).toLocaleString() : ''}
                          </p>
                        </div>
                      </div>
                    ))
                  ) : (
                    <div className="text-center py-8 text-gray-500 text-sm">
                      <Navigation className="w-8 h-8 text-[#38bdac]/40 mx-auto mb-2" />
                      暂无旅程记录
                    </div>
                  )}
                </div>
              </TabsContent>

              {/* ===== 关系链路 ===== */}
              <TabsContent value="relations" className="flex-1 min-h-0 overflow-y-auto space-y-2 pr-0.5">
                <div className="p-2 bg-[#0a1628] rounded-lg border border-[#38bdac]/25">
                  <div className="flex items-center justify-between mb-2">
                    <div className="flex items-center gap-1.5">
                      <Link2 className="w-3.5 h-3.5 text-[#38bdac]" />
                      <span className="text-white text-sm font-medium">入站关系链路</span>
                    </div>
                    <Badge className="bg-[#38bdac]/20 text-[#38bdac] border-0 text-[10px]">
                      点击 {inboundSource?.totalVisits || 0} 次
                    </Badge>
                  </div>
                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 mb-2">
                    <div className="p-1.5 bg-[#162840] rounded text-xs">
                      <p className="text-gray-500">首次来自</p>
                      <p className="text-white mt-0.5">
                        {inboundSource?.firstVisit?.referrerNickname || '—'}
                        {inboundSource?.firstVisit?.referrerId ? `（${inboundSource.firstVisit.referrerId}）` : ''}
                      </p>
                    </div>
                    <div className="p-1.5 bg-[#162840] rounded text-xs">
                      <p className="text-gray-500">最近来自</p>
                      <p className="text-white mt-0.5">
                        {inboundSource?.latestVisit?.referrerNickname || '—'}
                        {inboundSource?.latestVisit?.referrerId ? `（${inboundSource.latestVisit.referrerId}）` : ''}
                      </p>
                    </div>
                  </div>
                  {inboundSource?.activeBinding?.referrerId ? (
                    <div className="p-1.5 bg-amber-500/10 border border-amber-500/30 rounded text-xs mb-2">
                      <p className="text-amber-300">
                        当前绑定：
                        {inboundSource.activeBinding.referrerNickname || '微信用户'}
                        {`（${inboundSource.activeBinding.referrerId}）`}
                      </p>
                    </div>
                  ) : null}
                  <div className="space-y-1 max-h-[160px] overflow-y-auto">
                    {(inboundSource?.visits || []).length > 0 ? (
                      (inboundSource?.visits || []).map((v, i) => (
                        <div key={`${v.referrerId || 'unknown'}_${i}`} className="flex items-center justify-between p-1.5 bg-[#162840] rounded text-xs">
                          <div className="min-w-0">
                            <p className="text-white truncate">
                              第 {v.seq || i + 1} 次 · {v.referrerNickname || '微信用户'}
                              {v.referrerId ? `（${v.referrerId}）` : ''}
                            </p>
                            {v.page ? <p className="text-gray-500 text-[10px] truncate">{v.page}</p> : null}
                          </div>
                          <span className="text-gray-500 text-[10px] shrink-0">
                            {v.visitedAt ? new Date(v.visitedAt).toLocaleString() : ''}
                          </span>
                        </div>
                      ))
                    ) : (
                      <p className="text-gray-500 text-sm text-center py-2">暂无来源点击记录</p>
                    )}
                  </div>
                </div>
                <div className="p-2 bg-[#0a1628] rounded-lg">
                  <div className="flex items-center justify-between mb-2">
                    <div className="flex items-center gap-1.5">
                      <Link2 className="w-3.5 h-3.5 text-[#38bdac]" />
                      <span className="text-white text-sm font-medium">推荐的用户</span>
                    </div>
                    <Badge className="bg-[#38bdac]/20 text-[#38bdac] border-0 text-[10px]">共 {referrals.length} 人</Badge>
                  </div>
                  <div className="space-y-1 max-h-[min(280px,40vh)] overflow-y-auto">
                    {referrals.length > 0 ? (
                      referrals.map((ref: unknown, i: number) => {
                        const r = ref as { id?: string; nickname?: string; status?: string; createdAt?: string }
                        return (
                          <div key={r.id || i} className="flex items-center justify-between p-1.5 bg-[#162840] rounded text-xs">
                            <div className="flex items-center gap-1.5 min-w-0">
                              <div className="w-6 h-6 rounded-full bg-[#38bdac]/20 flex items-center justify-center text-[10px] text-[#38bdac] shrink-0">{r.nickname?.charAt(0) || '?'}</div>
                              <span className="text-white truncate">{r.nickname}</span>
                            </div>
                            <div className="flex items-center gap-1.5 shrink-0">
                              {r.status === 'vip' && <Badge className="bg-green-500/20 text-green-400 border-0 text-[10px] py-0">已购</Badge>}
                              <span className="text-gray-500 text-[10px]">{r.createdAt ? new Date(r.createdAt).toLocaleDateString() : ''}</span>
                            </div>
                          </div>
                        )
                      })
                    ) : (
                      <p className="text-gray-500 text-sm text-center py-3">暂无推荐用户</p>
                    )}
                  </div>
                </div>
              </TabsContent>

              {/* ===== 标签体系 ===== */}
              <TabsContent value="tags" className="flex-1 min-h-0 overflow-y-auto space-y-3 pr-0.5">
                <div className="p-2.5 bg-[#0a1628] rounded-lg">
                  <div className="flex items-center gap-2 mb-2 flex-wrap">
                    <Tag className="w-4 h-4 text-[#38bdac]" />
                    <span className="text-white text-sm font-medium">用户标签</span>
                    <span className="text-gray-500 text-[11px]">《一场 Soul 的创业实验》维度</span>
                  </div>
                  <div className="mb-2 p-2 bg-[#38bdac]/5 border border-[#38bdac]/20 rounded-lg flex items-start gap-2 text-[11px] text-gray-400">
                    <CheckCircle2 className="w-3.5 h-3.5 text-[#38bdac] shrink-0 mt-0.5" />
                    预设可点选；下方「旅程推断」由轨迹+资料自动算出，可一键并入已选后点弹窗底部保存。
                  </div>
                  <div className="mb-3 p-2 rounded-lg bg-[#162840]/80 border border-cyan-500/20">
                    <div className="flex flex-wrap items-center justify-between gap-2 mb-1.5">
                      <span className="text-cyan-300/90 text-xs font-medium">旅程推断标签</span>
                      <Button
                        type="button"
                        size="sm"
                        variant="outline"
                        className="h-7 text-[11px] border-cyan-500/40 text-cyan-200 hover:bg-cyan-500/10"
                        disabled={journeyInferredTags.length === 0}
                        onClick={mergeJourneyTagsIntoSelected}
                      >
                        合并到已选
                      </Button>
                    </div>
                    {journeyInferredTags.length > 0 ? (
                      <div className="flex flex-wrap gap-1">
                        {journeyInferredTags.map((t) => (
                          <Badge
                            key={t}
                            variant="outline"
                            className={`text-[10px] py-0 h-5 border-cyan-500/30 ${editTags.includes(t) ? 'bg-cyan-500/15 text-cyan-200' : 'text-gray-300'}`}
                          >
                            {editTags.includes(t) ? '✓ ' : ''}
                            {t}
                          </Badge>
                        ))}
                      </div>
                    ) : (
                      <p className="text-[11px] text-gray-500">暂无推断（无轨迹或行为未命中规则）</p>
                    )}
                  </div>
                  <div className="mb-3 space-y-2">
                    {[
                      {
                        category: '身份类型',
                        tags: ['创业者', '打工人', '自由职业', '学生', '投资人', '合伙人'],
                      },
                      {
                        category: '行业背景',
                        tags: ['电商', '内容', '传统行业', '科技/AI', '金融', '教育', '餐饮'],
                      },
                      {
                        category: '痛点标签',
                        tags: ['找资源', '找方向', '找合伙人', '想赚钱', '想学习', '找情感出口'],
                      },
                      {
                        category: '付费意愿',
                        tags: ['高意向', '已付费', '观望中', '薅羊毛'],
                      },
                      {
                        category: 'MBTI',
                        tags: ['ENTJ', 'INTJ', 'ENFP', 'INFP', 'ENTP', 'INTP', 'ESTJ', 'ISFJ'],
                      },
                    ].map((group) => (
                      <div key={group.category}>
                        <p className="text-gray-500 text-[11px] mb-1">{group.category}</p>
                        <div className="flex flex-wrap gap-1">
                          {group.tags.map((tag) => (
                            <button
                              key={tag}
                              type="button"
                              onClick={() => {
                                if (editTags.includes(tag)) removeTag(tag)
                                else setEditTags([...editTags, tag])
                              }}
                              className={`px-1.5 py-0.5 rounded text-[11px] border transition-all ${
                                editTags.includes(tag)
                                  ? 'bg-[#38bdac]/20 border-[#38bdac]/50 text-[#38bdac]'
                                  : 'bg-transparent border-gray-700 text-gray-500 hover:border-gray-500 hover:text-gray-300'
                              }`}
                            >
                              {editTags.includes(tag) ? '✓ ' : ''}{tag}
                            </button>
                          ))}
                        </div>
                      </div>
                    ))}
                  </div>
                  <div className="border-t border-gray-700/50 pt-2">
                    <p className="text-gray-500 text-[11px] mb-1.5">已选标签（需保存修改写入库）</p>
                    <div className="flex flex-wrap gap-1.5 mb-2 min-h-[28px]">
                      {editTags.map((tag, i) => (
                        <Badge key={i} className="bg-[#38bdac]/20 text-[#38bdac] border-0 pr-1 text-[11px] py-0">
                          {tag}
                          <button type="button" onClick={() => removeTag(tag)} className="ml-1 hover:text-red-400">
                            <X className="w-3 h-3" />
                          </button>
                        </Badge>
                      ))}
                      {editTags.length === 0 && <span className="text-gray-600 text-xs">暂未选择</span>}
                    </div>
                    <div className="flex gap-1.5">
                      <Input
                        className="bg-[#162840] border-gray-700 text-white flex-1 h-8 text-xs"
                        placeholder="自定义标签，回车添加"
                        value={newTag}
                        onChange={(e) => setNewTag(e.target.value)}
                        onKeyDown={(e) => e.key === 'Enter' && addTag()}
                      />
                      <Button onClick={addTag} className="bg-[#38bdac] hover:bg-[#2da396] h-8 text-xs px-3">
                        添加
                      </Button>
                    </div>
                  </div>
                </div>
                {/* 存客宝标签（与用户标签共用 ckb_tags，兼容 JSON 与逗号分隔） */}
                {(() => {
                  const raw = user.tags || user.ckbTags || ''
                  let arr: string[] = []
                  try {
                    const parsed = typeof raw === 'string' ? JSON.parse(raw || '[]') : []
                    arr = Array.isArray(parsed) ? parsed : (typeof raw === 'string' ? raw.split(',') : [])
                  } catch {
                    arr = typeof raw === 'string' ? raw.split(',') : []
                  }
                  const tags = arr.map((t) => String(t).trim()).filter(Boolean)
                  if (tags.length === 0) return null
                  return (
                    <div className="p-2.5 bg-[#0a1628] rounded-lg">
                      <div className="flex items-center gap-2 mb-1.5">
                        <Tag className="w-3.5 h-3.5 text-purple-400" />
                        <span className="text-white text-sm font-medium">存客宝标签</span>
                      </div>
                      <div className="flex flex-wrap gap-1">
                        {tags.map((tag, i) => (
                          <Badge key={i} className="bg-purple-500/20 text-purple-400 border-0 text-[11px] py-0">
                            {tag}
                          </Badge>
                        ))}
                      </div>
                    </div>
                  )
                })()}
              </TabsContent>

            </Tabs>

            <div className="flex justify-end gap-2 pt-3 border-t border-gray-700 mt-3 shrink-0">
              <Button
                variant="outline"
                onClick={onClose}
                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={handleSave} disabled={saving} className="bg-[#38bdac] hover:bg-[#2da396] text-white">
                <Save className="w-4 h-4 mr-2" />
                {saving ? '保存中...' : '保存修改'}
              </Button>
            </div>
          </div>
        ) : (
          <div className="text-center py-12 text-gray-500">用户不存在</div>
        )}
      </DialogContent>
    </Dialog>

    <Dialog open={adjustBalanceOpen} onOpenChange={setAdjustBalanceOpen}>
      <DialogContent className="bg-[#0f2137] border-gray-700 text-white" showCloseButton>
        <DialogHeader>
          <DialogTitle>调整余额</DialogTitle>
        </DialogHeader>
        <div className="space-y-4 py-4">
          <div>
            <Label className="text-gray-300 text-sm">调整金额（元）</Label>
            <Input
              type="number"
              step="0.01"
              className="bg-[#0a1628] border-gray-700 text-white mt-1"
              placeholder="正数增加，负数扣减，如 10 或 -5"
              value={adjustAmount}
              onChange={(e) => setAdjustAmount(e.target.value)}
            />
          </div>
          <div>
            <Label className="text-gray-300 text-sm">备注（可选）</Label>
            <Input
              className="bg-[#0a1628] border-gray-700 text-white mt-1"
              placeholder="如：活动补偿"
              value={adjustRemark}
              onChange={(e) => setAdjustRemark(e.target.value)}
            />
          </div>
        </div>
        <div className="flex justify-end gap-2">
          <Button variant="outline" onClick={() => setAdjustBalanceOpen(false)} className="border-gray-600 text-gray-300">
            取消
          </Button>
          <Button onClick={handleAdjustBalance} disabled={adjustLoading} className="bg-[#38bdac] hover:bg-[#2da396] text-white">
            {adjustLoading ? '提交中...' : '确认调整'}
          </Button>
        </div>
      </DialogContent>
    </Dialog>
    </>
  )
}
