<template>
  <div class="token-manager">
    <div class="header">
      <h3>Token管理器</h3>
      <div class="header-actions">
        <n-button
          size="small"
          @click="refreshTokens"
        >
          <template #icon>
            <n-icon><Refresh /></n-icon>
          </template>
          刷新
        </n-button>
        <n-button
          size="small"
          type="warning"
          @click="exportTokens"
        >
          <template #icon>
            <n-icon><Download /></n-icon>
          </template>
          导出
        </n-button>
        <n-upload 
          :show-file-list="false"
          accept=".json"
          @change="importTokens"
        >
          <n-button
            size="small"
            type="info"
          >
            <template #icon>
              <n-icon><CloudUpload /></n-icon>
            </template>
            导入
          </n-button>
        </n-upload>
      </div>
    </div>

    <!-- 用户Token -->
    <div class="token-section">
      <h4>用户认证Token</h4>
      <div
        v-if="localTokenStore.userToken"
        class="token-item"
      >
        <div class="token-info">
          <span class="token-label">Token:</span>
          <span class="token-value">{{ maskToken(localTokenStore.userToken) }}</span>
        </div>
        <n-button
          size="tiny"
          type="error"
          @click="clearUserToken"
        >
          清除
        </n-button>
      </div>
      <div
        v-else
        class="empty-token"
      >
        <span>未设置用户Token</span>
      </div>
    </div>

    <!-- 游戏Token列表 -->
    <div class="token-section">
      <h4>游戏角色Token ({{ Object.keys(localTokenStore.gameTokens).length }}个)</h4>
      <div class="game-tokens-list">
        <div 
          v-for="(tokenData, roleId) in localTokenStore.gameTokens"
          :key="roleId"
          class="game-token-item"
        >
          <div class="token-header">
            <div class="role-info">
              <span class="role-name">{{ tokenData.roleName }}</span>
              <span class="role-server">{{ tokenData.server }}</span>
            </div>
            <div class="token-actions">
              <n-button 
                size="tiny" 
                :type="getWSStatus(roleId) === 'connected' ? 'success' : 'default'"
                @click="toggleWebSocket(roleId, tokenData)"
                :loading="getWSStatus(roleId) === 'connecting'"
              >
                {{ getWSStatus(roleId) === 'connected' ? '断开WS' : '连接WS' }}
              </n-button>
              
              <n-dropdown 
                :options="getTokenMenuOptions(tokenData)" 
                trigger="click"
                @select="handleTokenAction($event, roleId, tokenData)"
              >
                <n-button
                  size="tiny"
                  type="tertiary"
                >
                  <template #icon>
                    <n-icon><EllipsisHorizontal /></n-icon>
                  </template>
                </n-button>
              </n-dropdown>
            </div>
          </div>
          
          <div class="token-details">
            <div class="detail-item">
              <span class="detail-label">Token:</span>
              <span class="detail-value">{{ maskToken(tokenData.token) }}</span>
            </div>
            <div class="detail-item">
              <span class="detail-label">WebSocket URL:</span>
              <span class="detail-value">{{ tokenData.wsUrl }}</span>
            </div>
            <div class="detail-item">
              <span class="detail-label">创建时间:</span>
              <span class="detail-value">{{ formatTime(tokenData.createdAt) }}</span>
            </div>
            <div class="detail-item">
              <span class="detail-label">最后使用:</span>
              <span class="detail-value">{{ formatTime(tokenData.lastUsed) }}</span>
            </div>
            <div class="detail-item" v-if="tokenData.lastRefreshed">
              <span class="detail-label">最后刷新:</span>
              <span class="detail-value">{{ formatTime(tokenData.lastRefreshed) }}</span>
            </div>
            <div class="detail-item" v-else-if="tokenData.binFileContent">
              <span class="detail-label">最后刷新:</span>
              <span class="detail-value">从未刷新</span>
            </div>
            <div class="detail-item">
              <span class="detail-label">连接状态:</span>
              <n-tag 
                size="small"
                :type="getWSStatusType(getWSStatus(roleId))"
              >
                {{ getWSStatusText(getWSStatus(roleId)) }}
                <n-tooltip v-if="getWSStatus(roleId) === 'error' && getWSError(roleId)" trigger="hover">
                  <template #trigger>
                    <n-icon size="14" style="margin-left: 4px; cursor: pointer;">
                      <AlertCircle />
                    </n-icon>
                  </template>
                  {{ getWSError(roleId) }}
                </n-tooltip>
              </n-tag>
            </div>
            <div class="detail-item" v-if="tokenData.binFileContent">
              <span class="detail-label">Token状态:</span>
              <n-tag 
                size="small"
                :type="getTokenStatusType(tokenData)"
              >
                {{ getTokenStatusText(tokenData) }}
              </n-tag>
              <n-tooltip v-if="tokenData.lastRefreshed" trigger="hover">
                <template #trigger>
                  <n-icon size="14" style="margin-left: 4px; cursor: pointer;">
                    <Time />
                  </n-icon>
                </template>
                最后刷新时间: {{ formatTime(tokenData.lastRefreshed) }}
              </n-tooltip>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 批量操作 -->
    <div class="bulk-actions">
      <n-button
        type="warning"
        @click="cleanExpiredTokens"
      >
        清理过期Token
      </n-button>
      <n-button
        type="error"
        @click="clearAllTokens"
      >
        清除所有Token
      </n-button>
    </div>
  </div>
</template>

<script setup>
import { ref, h } from 'vue'
import { useMessage, useDialog, NIcon } from 'naive-ui'
import { useLocalTokenStore } from '@/stores/localTokenManager'
import { useGameRolesStore } from '@/stores/gameRoles'
import { 
  Refresh, 
  Download, 
  CloudUpload,
  EllipsisHorizontal,
  Create,
  TrashBin,
  SyncCircle,
  CopyOutline,
  Time
} from '@vicons/ionicons5'

const message = useMessage()
const dialog = useDialog()
const localTokenStore = useLocalTokenStore()
const gameRolesStore = useGameRolesStore()

// 方法
const maskToken = (token) => {
  if (!token) return ''
  try {
    // 尝试解析Base64编码的token
    const decodedToken = atob(token)
    try {
      // 尝试解析为JSON
      const tokenData = JSON.parse(decodedToken)
      // 将JSON对象转换为字符串并遮蔽
      const tokenStr = JSON.stringify(tokenData)
      if (tokenStr.length <= 16) {
        return tokenStr
      }
      // 保留前8个字符和后8个字符，中间用***代替
      return tokenStr.substring(0, 8) + '***' + tokenStr.substring(tokenStr.length - 8)
    } catch (jsonError) {
      // 如果不是JSON格式，直接处理解码后的字符串
      if (decodedToken.length <= 16) {
        return decodedToken
      }
      return decodedToken.substring(0, 8) + '***' + decodedToken.substring(decodedToken.length - 8)
    }
  } catch (error) {
    // 如果不是Base64编码，直接处理原始字符串
    const len = token.length
    if (len <= 16) return token
    return token.substring(0, 8) + '***' + token.substring(len - 8)
  }
}

const formatTime = (timestamp) => {
  return new Date(timestamp).toLocaleString('zh-CN')
}

const getWSStatus = (roleId) => {
  return localTokenStore.getWebSocketStatus(roleId)
}

const getWSStatusType = (status) => {
  switch (status) {
    case 'connected': return 'success'
    case 'error': return 'error'
    case 'connecting': return 'warning'
    default: return 'default'
  }
}

const getWSStatusText = (status) => {
  switch (status) {
    case 'connected': return '已连接'
    case 'error': return '连接错误'
    case 'connecting': return '连接中'
    default: return '未连接'
  }
}

// 获取WebSocket错误信息
const getWSError = (roleId) => {
  return localTokenStore.getWebSocketError(roleId)
}

// 获取WebSocket错误时间
const getWSErrorTime = (roleId) => {
  return localTokenStore.getWebSocketErrorTime(roleId)
}

// 获取Token状态文本
const getTokenStatusText = (tokenData) => {
  if (!tokenData.binFileContent && tokenData.importMethod === 'bin') return '需要重新导入'
  if (!tokenData.binFileContent) return '无Bin文件'
  if (tokenData.lastRefreshed) {
    // 检查是否在最近5分钟内刷新过
    const now = new Date()
    const refreshTime = new Date(tokenData.lastRefreshed)
    const diffMinutes = (now - refreshTime) / (1000 * 60)
    
    if (diffMinutes < 5) {
      return '刚刚刷新'
    } else if (diffMinutes < 60) {
      return `${Math.floor(diffMinutes)}分钟前刷新`
    } else if (diffMinutes < 24 * 60) {
      return `${Math.floor(diffMinutes / 60)}小时前刷新`
    } else {
      return '已刷新'
    }
  }
  return '待刷新'
}

// 获取Token状态类型
const getTokenStatusType = (tokenData) => {
  if (!tokenData.binFileContent && tokenData.importMethod === 'bin') return 'error'
  if (!tokenData.binFileContent) return 'default'
  if (!tokenData.lastRefreshed) return 'warning'
  
  // 检查是否在最近5分钟内刷新过
  const now = new Date()
  const refreshTime = new Date(tokenData.lastRefreshed)
  const diffMinutes = (now - refreshTime) / (1000 * 60)
  
  if (diffMinutes < 5) {
    return 'success'
  } else if (diffMinutes < 60) {
    return 'info'
  } else if (diffMinutes < 24 * 60) {
    return 'warning'
  } else {
    return 'error'
  }
}



    // 获取Token菜单选项
    const getTokenMenuOptions = (tokenData) => {
      const options = [
        {
          label: '编辑',
          key: 'edit',
          icon: () => h(NIcon, null, { default: () => h(Create) })
        },
        {
          label: '复制',
          key: 'copy',
          icon: () => h(NIcon, null, { default: () => h(CopyOutline) })
        }
      ]

      // 如果是URL获取的Token，显示刷新选项
      if (tokenData.importMethod === 'url' && tokenData.sourceUrl) {
        options.unshift({
          label: '从URL刷新',
          key: 'refresh-url',
          icon: () => h(NIcon, null, { default: () => h(Refresh) })
        })
      }

      // 如果有bin文件内容，显示从bin文件刷新选项
      if (tokenData.binFileContent) {
        options.unshift({
          label: '从Bin文件刷新',
          key: 'refresh-bin',
          icon: () => h(NIcon, null, { default: () => h(SyncCircle) })
        })
      }
      
      // 如果没有bin文件内容但有importMethod为bin，显示从bin文件刷新选项并提示需要重新导入
      if (!tokenData.binFileContent && tokenData.importMethod === 'bin') {
        options.unshift({
          label: '从Bin文件刷新(需要重新导入)',
          key: 'refresh-bin',
          icon: () => h(NIcon, null, { default: () => h(SyncCircle) }),
          disabled: true
        })
      }

      // 手动添加的Token显示重新生成选项
      if (!tokenData.importMethod && !tokenData.binFileContent) {
        options.unshift({
          label: '刷新Token',
          key: 'refresh',
          icon: () => h(NIcon, null, { default: () => h(Refresh) })
        })
      }

      // 添加删除选项
      options.push({
        label: '删除',
        key: 'delete',
        icon: () => h(NIcon, null, { default: () => h(TrashBin) })
      })

      return options
    }

    // 处理Token菜单操作
    const handleTokenAction = async (action, roleId, tokenData) => {
      switch (action) {
        case 'edit':
          editToken(roleId, tokenData)
          break
        case 'copy':
          copyToken(tokenData.token)
          break
        case 'refresh':
          regenerateToken(roleId)
          break
        case 'refresh-url':
          refreshTokenFromUrl(roleId, tokenData)
          break
        case 'refresh-bin':
          await refreshTokenFromBin(roleId, tokenData)
          break
        case 'delete':
          removeToken(roleId)
          break
      }
    }

    // 刷新所有Token
    const refreshTokens = () => {
      localTokenStore.initTokenManager()
      message.success('Token数据已刷新')
    }

    // 清除用户Token
    const clearUserToken = () => {
      dialog.warning({
        title: '清除用户Token',
        content: '确定要清除用户认证Token吗？这将会退出登录。',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: () => {
          localTokenStore.clearUserToken()
          message.success('用户Token已清除')
        }
      })
    }

    // 切换WebSocket连接
    const toggleWebSocket = async (roleId, tokenData) => {
      const status = getWSStatus(roleId)
      
      if (status === 'connected') {
        localTokenStore.closeWebSocketConnection(roleId)
        message.info('WebSocket连接已断开')
      } else {
        try {
          // 检查是否有bin文件内容，如果有则先尝试刷新token
          if (tokenData.binFileContent) {
            console.log(`🔄 检测到bin文件，连接前尝试刷新token`)
            const refreshResult = await localTokenStore.refreshTokenFromBin(roleId)
            
            if (refreshResult.success) {
              message.success('Token已刷新，正在建立WebSocket连接...')
              // 获取更新后的token数据
              const updatedTokenData = localTokenStore.getGameToken(roleId)
              if (updatedTokenData) {
                tokenData = updatedTokenData
              }
            } else {
              message.warning(`Token刷新失败，使用原有token连接: ${refreshResult.error}`)
            }
          }
          
          localTokenStore.createWebSocketConnection(roleId, tokenData.token, tokenData.wsUrl)
          message.success('正在建立WebSocket连接...')
        } catch (error) {
      console.error(`WebSocket操作失败 [${roleId}]:`, error)
      // 添加更详细的错误信息
      const errorMessage = error.message || error.toString() || '未知WebSocket错误'
      const errorDetails = error.details || {}
      
      console.error(`WebSocket操作失败详情 [${roleId}]:`, {
        message: errorMessage,
        stack: error.stack,
        details: errorDetails,
        timestamp: new Date().toISOString()
      })
      
      message.error(`WebSocket操作失败: ${errorMessage}`)
    }
      }
    }

    // 重新生成Token
    const regenerateToken = (roleId) => {
        const oldTokenData = localTokenStore.getGameToken(roleId)
        if (!oldTokenData) {
            message.error('找不到对应的Token数据')
            return
        }

        // 检查是否有源URL可以重新获取
        if (!oldTokenData.sourceUrl) {
            message.warning('该Token没有配置源地址，无法重新生成。请手动重新导入Token。')
            return
        }

        dialog.info({
            title: '重新获取Token', 
            content: '确定要从源地址重新获取此角色的Token吗？',
            positiveText: '确定',
            negativeText: '取消',
            onPositiveClick: async () => {
                try {
                    // 显示加载状态
                    const loadingMsg = message.loading('正在重新获取Token...', { duration: 0 })
                    
                    // 从源URL重新获取token
                    let response
                    const sourceUrl = oldTokenData.sourceUrl
                    
                    // 使用与TokenImport相同的跨域处理逻辑
                    const isLocalUrl = sourceUrl.startsWith(window.location.origin) || 
                                    sourceUrl.startsWith('/') ||
                                    sourceUrl.startsWith('http://localhost') ||
                                    sourceUrl.startsWith('http://127.0.0.1')
                    
                    if (isLocalUrl) {
                        response = await fetch(sourceUrl)
                    } else {
                        try {
                            response = await fetch(sourceUrl, {
                                method: 'GET',
                                headers: {
                                    'Accept': 'application/json',
                                },
                                mode: 'cors'
                            })
                        } catch (corsError) {
                            throw new Error(`跨域请求被阻止。请确保目标服务器支持CORS。错误详情: ${corsError.message}`)
                        }
                    }

                    if (!response.ok) {
                        throw new Error(`请求失败: ${response.status} ${response.statusText}`)
                    }
                    
                    const data = await response.json()
                    
                    if (!data.token) {
                        throw new Error('返回数据中未找到token字段')
                    }

                    // 更新token
                    localTokenStore.updateGameToken(roleId, {
                        token: data.token,
                        server: data.server || oldTokenData.server,
                        regeneratedAt: new Date().toISOString(),
                        lastRefreshed: new Date().toISOString()
                    })

                    // 如果当前token有连接，需要重新连接
                    if (localTokenStore.getWebSocketStatus(roleId) === 'connected') {
                        localTokenStore.closeWebSocketConnection(roleId)
                        setTimeout(() => {
                            localTokenStore.createWebSocketConnection(roleId, data.token, oldTokenData.wsUrl)
                        }, 500)
                    }

                    loadingMsg.destroy()
                    message.success('Token已成功重新获取')
                } catch (error) {
                    console.error('重新获取Token失败:', error)
                    message.error(error.message || 'Token重新获取失败')
                }
            }
        })
    }

    // 删除Token
    const removeToken = (roleId) => {
        dialog.warning({
            title: '删除Token',
            content: '确定要删除此角色的游戏Token吗？这将断开相关的WebSocket连接。',
            positiveText: '确定删除',
            negativeText: '取消',
            onPositiveClick: () => {
                localTokenStore.removeGameToken(roleId)
                message.success('Token已删除')
            }
        })
    }

    // 编辑Token（暂时显示提示信息，后续可以实现编辑功能）
    const editToken = (roleId, tokenData) => {
        message.info('编辑功能正在开发中')
    }

    // 复制Token到剪贴板
    const copyToken = async (token) => {
        try {
            await navigator.clipboard.writeText(token)
            message.success('Token已复制到剪贴板')
        } catch (error) {
            // 降级方案
            const textArea = document.createElement('textarea')
            textArea.value = token
            document.body.appendChild(textArea)
            textArea.select()
            document.execCommand('copy')
            document.body.removeChild(textArea)
            message.success('Token已复制到剪贴板')
        }
    }

    // 从URL刷新Token
    const refreshTokenFromUrl = async (roleId, tokenData) => {
        if (!tokenData.sourceUrl) {
            message.warning('该Token没有配置源URL')
            return
        }

        dialog.info({
            title: '从URL刷新Token',
            content: `确定要从源URL重新获取Token吗？\n源地址：${tokenData.sourceUrl}`,
            positiveText: '确定',
            negativeText: '取消',
            onPositiveClick: async () => {
                try {
                    const loadingMsg = message.loading('正在从URL获取新Token...', { duration: 0 })
                    
                    // 使用与TokenImport相同的逻辑获取Token
                    let response
                    const isLocalUrl = tokenData.sourceUrl.startsWith(window.location.origin) || 
                                    tokenData.sourceUrl.startsWith('/') ||
                                    tokenData.sourceUrl.startsWith('http://localhost') ||
                                    tokenData.sourceUrl.startsWith('http://127.0.0.1')
                    
                    if (isLocalUrl) {
                        response = await fetch(tokenData.sourceUrl)
                    } else {
                        // 跨域请求，使用代理
                        const proxyUrl = `/api/proxy?url=${encodeURIComponent(tokenData.sourceUrl)}`
                        response = await fetch(proxyUrl)
                    }

                    if (!response.ok) {
                        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
                    }

                    const data = await response.json()
                    if (!data.token) {
                        throw new Error('返回数据中未找到token字段')
                    }

                    // 更新Token
                    localTokenStore.updateGameToken(roleId, {
                        token: data.token,
                        lastUsed: new Date().toISOString()
                    })

                    loadingMsg.destroy()
                    message.success('Token刷新成功')
                } catch (error) {
                    console.error('URL刷新Token失败:', error)
                    message.error('刷新失败: ' + error.message)
                }
            }
        })
    }

    // 从bin文件刷新token
    const refreshTokenFromBin = async (token) => {
        try {
            console.log(`[TokenManager] 开始从bin文件刷新token，角色ID: ${token.roleId}`)
            
            // 检查token是否有bin文件内容
            if (!token.binFileContent) {
                console.error(`[TokenManager] 错误: 该Token没有bin文件内容`)
                message.error('该Token没有bin文件内容，无法刷新')
                return false
            }
            
            // 检查bin文件内容是否为空
            if (token.binFileContent === '' || token.binFileContent.length === 0) {
                console.error(`[TokenManager] 错误: 该Token的bin文件内容为空`)
                message.error('该Token的bin文件内容为空，请重新导入带有bin文件内容的Token')
                return false
            }

            // 记录原始token数据
            console.log(`[TokenManager] 原始token数据:`, {
                roleId: token.roleId,
                token: token.token ? token.token.substring(0, 20) + '...' : 'N/A',
                roleToken: token.roleToken ? token.roleToken.substring(0, 20) + '...' : 'N/A',
                binFileContentLength: token.binFileContent ? token.binFileContent.length : 0
            })

            // 调用localTokenStore的刷新方法
            const result = await localTokenStore.refreshTokenFromBin(token.roleId, token)
            
            if (result.success) {
                console.log(`[TokenManager] Token刷新成功`)
                message.success('Token刷新成功')
                
                // 更新localStorage
                localStorage.setItem('gameTokens', JSON.stringify(localTokenStore.gameTokens))
                
                // 验证roleToken是否正确更新
                const updatedToken = localTokenStore.gameTokens[token.roleId]
                if (updatedToken && updatedToken.roleToken) {
                    console.log(`[TokenManager] roleToken已更新: ${updatedToken.roleToken.substring(0, 20)}...`)
                } else {
                    console.error(`[TokenManager] roleToken更新失败`)
                    message.error('Token刷新失败: roleToken更新失败')
                    return false
                }
                
                // 重新建立WebSocket连接
                if (localTokenStore.wsConnections[token.roleId]) {
                    console.log(`[TokenManager] 关闭旧的WebSocket连接`)
                    localTokenStore.closeWebSocketConnection(token.roleId)
                }
                
                console.log(`[TokenManager] 创建新的WebSocket连接`)
                localTokenStore.createWebSocketConnection(token.roleId)
                
                // 强制刷新UI
                forceUpdate.value = !forceUpdate.value
                
                return true
            } else {
                console.error(`[TokenManager] Token刷新失败:`, result.error)
                message.error(`Token刷新失败: ${result.error}`)
                return false
            }
        } catch (error) {
            console.error(`[TokenManager] 从bin文件刷新token失败:`, error)
            message.error(`Token刷新失败: ${error.message}`)
            return false
        }
    }

// 导出Token
const exportTokens = () => {
    try {
        const tokenData = localTokenStore.exportTokens()
        const dataStr = JSON.stringify(tokenData, null, 2)
        const dataBlob = new Blob([dataStr], { type: 'application/json' })
        
        const link = document.createElement('a')
        link.href = URL.createObjectURL(dataBlob)
        link.download = `tokens_backup_${new Date().toISOString().split('T')[0]}.json`
        link.click()
        
        message.success('Token数据已导出')
    } catch (error) {
        message.error('导出失败: ' + error.message)
    }
}

// 导入Token
const importTokens = ({ file }) => {
    const reader = new FileReader()
    reader.onload = (e) => {
        try {
            const tokenData = JSON.parse(e.target.result)
            const result = localTokenStore.importTokens(tokenData)
            
            if (result.success) {
                message.success(result.message)
                // 刷新游戏角色数据
                gameRolesStore.fetchGameRoles()
            } else {
                message.error(result.message)
            }
        } catch (error) {
            message.error('导入失败：文件格式错误')
        }
    }
    reader.readAsText(file.file)
}

// 清理过期Token
const cleanExpiredTokens = () => {
    dialog.info({
        title: '清理过期Token',
        content: '确定要清理超过24小时未使用的Token吗？',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: () => {
            const cleanedCount = localTokenStore.cleanExpiredTokens()
            message.success(`已清理 ${cleanedCount} 个过期Token`)
        }
    })
}

// 清除所有Token
const clearAllTokens = () => {
    dialog.error({
        title: '清除所有Token',
        content: '确定要清除所有游戏Token吗？这将断开所有WebSocket连接。此操作不可恢复！',
        positiveText: '确定清除',
        negativeText: '取消',
        onPositiveClick: () => {
            localTokenStore.clearAllGameTokens()
            message.success('所有游戏Token已清除')
        }
    })
}
</script>

<style scoped lang="scss">
.token-manager {
  background: white;
  border-radius: var(--border-radius-large);
  padding: 12px; /* 减小内边距 */
  margin: 8px 0; /* 减小外边距 */
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--spacing-lg);
  
  h3 {
    margin: 0;
    color: var(--text-primary);
    font-size: var(--font-size-lg);
  }
}

.header-actions {
  display: flex;
  gap: var(--spacing-sm);
}

.token-section {
  margin-bottom: 16px; /* 减小间距 */
  
  h4 {
    margin: 0 0 8px 0; /* 减小间距 */
    color: var(--text-primary);
    font-size: var(--font-size-md);
  }
}

.token-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--spacing-md);
  background: var(--bg-tertiary);
  border-radius: var(--border-radius-medium);
}

.token-info {
  display: flex;
  gap: var(--spacing-md);
}

.token-label {
  color: var(--text-secondary);
  font-weight: var(--font-weight-medium);
}

.token-value {
  font-family: monospace;
  color: var(--text-primary);
}

.empty-token {
  padding: var(--spacing-md);
  text-align: center;
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  border-radius: var(--border-radius-medium);
}

.game-tokens-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}

/* 响应式布局：7个不同档次 */
@media (min-width: 2400px) {
  .game-tokens-list {
    grid-template-columns: repeat(7, 1fr); /* 超宽屏：7列 */
  }
}

@media (min-width: 2000px) and (max-width: 2399px) {
  .game-tokens-list {
    grid-template-columns: repeat(6, 1fr); /* 宽屏：6列 */
  }
}

@media (min-width: 1600px) and (max-width: 1999px) {
  .game-tokens-list {
    grid-template-columns: repeat(5, 1fr); /* 大屏：5列 */
  }
}

@media (min-width: 1280px) and (max-width: 1599px) {
  .game-tokens-list {
    grid-template-columns: repeat(4, 1fr); /* 中屏：4列 */
  }
}

@media (min-width: 1024px) and (max-width: 1279px) {
  .game-tokens-list {
    grid-template-columns: repeat(3, 1fr); /* 小屏：3列 */
  }
}

@media (min-width: 768px) and (max-width: 1023px) {
  .game-tokens-list {
    grid-template-columns: repeat(2, 1fr); /* 平板：2列 */
  }
}

@media (max-width: 767px) {
  .game-tokens-list {
    grid-template-columns: 1fr; /* 手机：1列 */
  }
}

.game-token-item {
  border: 1px solid var(--border-light);
  border-radius: var(--border-radius-medium);
  padding: 12px;
  overflow: hidden; /* 防止内容溢出 */
}

.token-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--spacing-md);
}

.role-info {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
}

.role-name {
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.role-server {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

.token-actions {
  display: flex;
  gap: var(--spacing-xs);
}

.token-details {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--spacing-sm);
}

.detail-item {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
}

.detail-label {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

.detail-value {
  font-size: var(--font-size-sm);
  color: var(--text-primary);
  font-family: monospace;
  overflow: hidden; /* 隐藏溢出 */
  text-overflow: ellipsis; /* 显示省略号 */
  white-space: nowrap; /* 单行显示 */
  max-width: 100%; /* 限制最大宽度 */
}

.bulk-actions {
  display: flex;
  gap: var(--spacing-md);
  justify-content: center;
  padding-top: var(--spacing-lg);
  border-top: 1px solid var(--border-light);
}

@media (max-width: 768px) {
  .header {
    flex-direction: column;
    gap: var(--spacing-md);
    align-items: stretch;
  }
  
  .token-item {
    flex-direction: column;
    gap: var(--spacing-md);
    align-items: stretch;
  }
  
  .token-header {
    flex-direction: column;
    gap: var(--spacing-sm);
    align-items: stretch;
  }
  
  .token-details {
    grid-template-columns: 1fr;
  }
  
  .bulk-actions {
    flex-direction: column;
  }
}
</style>