<template>
  <div class="upgrade-module-container">
    <div class="status-card upgrade-module" :class="{ 'is-running': isRunning }">
      <div class="card-header">
        <div class="icon-wrapper">
          <img
            src="/icons/book.jpg"
            alt="升级图标"
            class="status-icon"
          >
          <div class="icon-glow"></div>
        </div>
        <div class="status-info">
          <h3>咸将升级模块</h3>
          <p>批量咸将升星与图鉴升级</p>
        </div>
        <div
          class="status-badge"
          :class="{ active: isRunning }"
        >
          <div class="status-dot" />
          <span>{{ isRunning ? '升级中' : '待升级' }}</span>
        </div>
      </div>
      <div class="card-content">
        <div
          v-if="isRunning"
          class="progress-container"
        >
          <div class="progress-info">
            <div class="progress-stats">
              <div class="stat-item">
                <span class="stat-value">{{ current }}</span>
                <span class="stat-label">已完成</span>
              </div>
              <div class="stat-divider"></div>
              <div class="stat-item">
                <span class="stat-value">{{ total }}</span>
                <span class="stat-label">总任务</span>
              </div>
              <div class="stat-divider"></div>
              <div class="stat-item">
                <span class="stat-value">{{ Math.round(progress) }}%</span>
                <span class="stat-label">进度</span>
              </div>
            </div>
          </div>
          <div class="progress-bar-container">
            <div class="progress-bar">
              <div
                class="progress-fill"
                :style="{ width: progress + '%' }"
              />
              <div class="progress-shine" :style="{ width: progress + '%' }"></div>
            </div>
          </div>
          <div class="current-operation">
            <div class="operation-icon">
              <div class="pulse-dot"></div>
            </div>
            <p>{{ currentOperation }}</p>
          </div>
        </div>
        
        <div class="upgrade-options">
          <div class="option-group">
            <div class="group-header">
              <h4>升级选项</h4>
              <div class="header-decoration"></div>
            </div>
            <div class="settings-grid">
              <div class="setting-item">
                <div class="setting-header">
                  <div class="setting-icon hero-icon"></div>
                  <label>升星次数</label>
                </div>
                <div class="input-wrapper">
                  <input
                    v-model.number="heroUpgradeTimes"
                    type="number"
                    min="1"
                    max="100"
                    class="setting-input"
                  >
                  <div class="input-decoration"></div>
                </div>
              </div>
              <div class="setting-item">
                <div class="setting-header">
                  <div class="setting-icon book-icon"></div>
                  <label>图鉴升级次数</label>
                </div>
                <div class="input-wrapper">
                  <input
                    v-model.number="bookUpgradeTimes"
                    type="number"
                    min="1"
                    max="100"
                    class="setting-input"
                  >
                  <div class="input-decoration"></div>
                </div>
              </div>
              <div class="setting-item checkbox-item">
                <div class="setting-header">
                  <div class="setting-icon reward-icon"></div>
                  <label>领取图鉴奖励</label>
                </div>
                <label class="checkbox-wrapper">
                  <input
                    v-model="claimReward"
                    type="checkbox"
                    class="setting-checkbox"
                  >
                  <div class="checkbox-decoration">
                    <div class="checkbox-checkmark"></div>
                  </div>
                  <span class="checkbox-label">{{ claimReward ? '已开启' : '已关闭' }}</span>
                </label>
              </div>
              <div class="setting-item" v-if="claimReward">
                <div class="setting-header">
                  <div class="setting-icon reward-times-icon"></div>
                  <label>领取奖励次数</label>
                </div>
                <div class="input-wrapper">
                  <input
                    v-model.number="claimRewardTimes"
                    type="number"
                    min="1"
                    max="100"
                    class="setting-input"
                  >
                  <div class="input-decoration"></div>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        <div class="action-buttons">
          <button 
            class="action-button primary"
            :disabled="isRunning"
            @click="startUpgrade"
          >
            <div class="button-content">
              <div class="button-icon" v-if="!isRunning">
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path d="M8 5V19L19 12L8 5Z" fill="currentColor"/>
                </svg>
              </div>
              <div class="button-spinner" v-else>
                <div class="spinner"></div>
              </div>
              <span>{{ isRunning ? '升级中...' : '开始升级' }}</span>
            </div>
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useTokenStore } from '@/stores/tokenStore'
import { useMessage } from 'naive-ui'

const tokenStore = useTokenStore()
const message = useMessage()

// 响应式数据
const isRunning = ref(false)
const progress = ref(0)
const total = ref(0)
const current = ref(0)
const heroUpgradeTimes = ref(5)
const bookUpgradeTimes = ref(5)
const claimRewardTimes = ref(5)
const claimReward = ref(true)
const executionOrder = ref('hero-first') // 固定为'hero-first'，先升星后图鉴
const currentOperation = ref('')

// 咸将ID范围
const heroRanges = [
  [101, 120],
  [201, 228],
  [301, 314]
]

// 开始升级
const startUpgrade = async () => {
  if (!tokenStore.selectedToken || isRunning.value) return
  
  try {
    isRunning.value = true
    progress.value = 0
    current.value = 0
    
    // 计算总任务数
    let totalHeroes = 0
    for (const [rangeStart, rangeEnd] of heroRanges) {
      totalHeroes += (rangeEnd - rangeStart + 1)
    }
    
    // 固定执行顺序为"先升星后图鉴"
    total.value = totalHeroes * heroUpgradeTimes.value + totalHeroes * bookUpgradeTimes.value
    
    if (claimReward.value) {
      total.value += claimRewardTimes.value // 领取奖励次数可配置
    }
    
    message.info('开始咸将升级任务...')
    
    const tokenId = tokenStore.selectedToken.id
    
    // 添加预热请求
    try {
      await tokenStore.sendMessageWithPromise(tokenId, 'role_getroleinfo', {}, 2000)
      console.log('预热请求发送成功')
    } catch (error) {
      console.warn(`预热请求失败: ${error.message}，继续执行升级任务`)
    }
    
    // 固定执行顺序为"先升星后图鉴"
    await executeHeroUpgrade(tokenId)
    await executeBookUpgrade(tokenId)
    
    // 领取图鉴积分奖励
    if (claimReward.value) {
      await claimBookReward(tokenId)
    }
    
    message.success(`咸将升级完成！共发送 ${current.value} 个命令`)
    
  } catch (error) {
    console.error('咸将升级失败:', error)
    message.error('咸将升级失败: ' + error.message)
  } finally {
    isRunning.value = false
    currentOperation.value = ''
  }
}

// 执行咸将升星
const executeHeroUpgrade = async (tokenId) => {
  currentOperation.value = '咸将升星中...'
  
  for (const [rangeStart, rangeEnd] of heroRanges) {
    for (let heroId = rangeStart; heroId <= rangeEnd; heroId++) {
      for (let counter = 0; counter < heroUpgradeTimes.value; counter++) {
        try {
          const debugLog = `准备发送咸将升星请求: ID=${heroId}, 次数=${counter + 1}, 超时=200ms`
          console.log(debugLog)
          
          // 检查WebSocket连接状态
          const connection = tokenStore.wsConnections[tokenId]
          if (!connection || connection.status !== 'connected') {
            const connectionLog = `WebSocket连接状态异常，尝试重新连接...`
            console.warn(connectionLog)
            
            // 尝试重新连接
            await tokenStore.reconnectWebSocket(tokenId)
            await new Promise(resolve => setTimeout(resolve, 1000))
          }
          
          // 记录请求开始时间
          const startTime = Date.now()
          
          // 发送升星请求
          const response = await tokenStore.sendMessageWithPromise(tokenId, 'hero_heroupgradestar', { heroId }, 200)
          
          // 计算请求耗时
          const elapsedTime = Date.now() - startTime
          const timeLog = `咸将ID ${heroId} 第${counter + 1}次升星请求耗时: ${elapsedTime}ms`
          console.log(timeLog)
          
          // 更新进度
          current.value++
          progress.value = Math.floor((current.value / total.value) * 100)
          
          // 记录日志
          const log = `咸将ID ${heroId} 第${counter + 1}次升星命令已发送`
          console.log(log)
          
          // 延迟100ms
          await new Promise(resolve => setTimeout(resolve, 100))
        } catch (error) {
          const errorLog = `咸将ID ${heroId} 第${counter + 1}次升星失败: ${error.message}`
          console.error(errorLog)
          
          // 即使失败也更新进度，因为命令已经发送
          current.value++
          progress.value = Math.floor((current.value / total.value) * 100)
          
          // 如果是超时错误，添加额外信息
          if (error.message.includes('请求超时')) {
            const timeoutLog = `注意: 咸将ID ${heroId} 升星请求超时，可能是网络延迟或服务器响应慢`
            console.warn(timeoutLog)
          }
          
          // 继续下一次升星尝试，不跳出循环
        }
      }
    }
  }
}

// 执行图鉴升级
const executeBookUpgrade = async (tokenId) => {
  currentOperation.value = '图鉴升级中...'
  
  for (const [rangeStart, rangeEnd] of heroRanges) {
    for (let heroId = rangeStart; heroId <= rangeEnd; heroId++) {
      for (let counter = 0; counter < bookUpgradeTimes.value; counter++) {
        try {
          const debugLog = `准备发送图鉴升级请求: ID=${heroId}, 次数=${counter + 1}, 超时=200ms`
          console.log(debugLog)
          
          // 检查WebSocket连接状态
          const connection = tokenStore.wsConnections[tokenId]
          if (!connection || connection.status !== 'connected') {
            const connectionLog = `WebSocket连接状态异常，尝试重新连接...`
            console.warn(connectionLog)
            
            // 尝试重新连接
            await tokenStore.reconnectWebSocket(tokenId)
            await new Promise(resolve => setTimeout(resolve, 1000))
          }
          
          // 记录请求开始时间
          const startTime = Date.now()
          
          // 发送图鉴升级请求
          const response = await tokenStore.sendMessageWithPromise(tokenId, 'book_upgrade', { heroId }, 200)
          
          // 计算请求耗时
          const elapsedTime = Date.now() - startTime
          const timeLog = `咸将ID ${heroId} 第${counter + 1}次图鉴升级请求耗时: ${elapsedTime}ms`
          console.log(timeLog)
          
          // 更新进度
          current.value++
          progress.value = Math.floor((current.value / total.value) * 100)
          
          // 记录日志
          const log = `咸将ID ${heroId} 第${counter + 1}次图鉴升级命令已发送`
          console.log(log)
          
          // 延迟100ms
          await new Promise(resolve => setTimeout(resolve, 100))
        } catch (error) {
          const errorLog = `咸将ID ${heroId} 第${counter + 1}次图鉴升级失败: ${error.message}`
          console.error(errorLog)
          
          // 即使失败也更新进度，因为命令已经发送
          current.value++
          progress.value = Math.floor((current.value / total.value) * 100)
          
          // 如果是超时错误，添加额外信息
          if (error.message.includes('请求超时')) {
            const timeoutLog = `注意: 咸将ID ${heroId} 图鉴升级请求超时，可能是网络延迟或服务器响应慢`
            console.warn(timeoutLog)
          }
          
          // 继续下一次图鉴升级尝试，不跳出循环
        }
      }
    }
  }
}

// 领取图鉴积分奖励
const claimBookReward = async (tokenId) => {
  currentOperation.value = '领取图鉴积分奖励...'
  
  for (let counter = 0; counter < claimRewardTimes.value; counter++) {
    try {
      const debugLog = `准备发送图鉴积分奖励领取请求，第${counter + 1}次，超时=200ms`
      console.log(debugLog)
      
      // 检查WebSocket连接状态
      const connection = tokenStore.wsConnections[tokenId]
      if (!connection || connection.status !== 'connected') {
        const connectionLog = `WebSocket连接状态异常，尝试重新连接...`
        console.warn(connectionLog)
        
        // 尝试重新连接
        await tokenStore.reconnectWebSocket(tokenId)
        await new Promise(resolve => setTimeout(resolve, 1000))
      }
      
      // 记录请求开始时间
      const startTime = Date.now()
      
      // 发送领取奖励请求
      const response = await tokenStore.sendMessageWithPromise(tokenId, 'book_claimpointreward', {}, 200)
      
      // 计算请求耗时
      const elapsedTime = Date.now() - startTime
      const timeLog = `图鉴积分奖励第${counter + 1}次领取请求耗时: ${elapsedTime}ms`
      console.log(timeLog)
      
      // 更新进度
      current.value++
      progress.value = Math.floor((current.value / total.value) * 100)
      
      // 记录日志
      const log = `图鉴积分奖励第${counter + 1}次领取命令已发送`
      console.log(log)
      
      // 延迟100ms
      await new Promise(resolve => setTimeout(resolve, 100))
    } catch (error) {
      const errorLog = `图鉴积分奖励第${counter + 1}次领取失败: ${error.message}`
      console.error(errorLog)
      
      // 即使失败也更新进度，因为命令已经发送
      current.value++
      progress.value = Math.floor((current.value / total.value) * 100)
      
      // 如果是超时错误，添加额外信息
      if (error.message.includes('请求超时')) {
        const timeoutLog = `注意: 图鉴积分奖励第${counter + 1}次领取请求超时，可能是网络延迟或服务器响应慢`
        console.warn(timeoutLog)
      }
      
      // 继续下一次领取尝试，不跳出循环
    }
  }
}
</script>

<style scoped>
.upgrade-module-container {
  width: 100%;
  display: flex;
  justify-content: center;
  padding: 16px;
  background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%);
}

.upgrade-module {
  width: 100%;
  max-width: 800px;
  background: linear-gradient(145deg, #ffffff, #f8fafc);
  border-radius: 16px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  transition: all 0.3s ease;
  position: relative;
}

.upgrade-module.is-running {
  box-shadow: 0 10px 40px rgba(59, 130, 246, 0.2);
  border: 1px solid rgba(59, 130, 246, 0.2);
}

.upgrade-module::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6, #ec4899);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.upgrade-module.is-running::before {
  opacity: 1;
}

.card-header {
  display: flex;
  align-items: center;
  padding: 20px 24px;
  background: linear-gradient(135deg, #3b82f6 0%, #5b21b6 100%);
  color: white;
  position: relative;
  overflow: hidden;
}

.card-header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}

.icon-wrapper {
  position: relative;
  margin-right: 16px;
}

.status-icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  object-fit: cover;
  border: 2px solid rgba(255, 255, 255, 0.2);
  position: relative;
  z-index: 2;
}

.icon-glow {
  position: absolute;
  top: 0;
  left: 0;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.2);
  filter: blur(8px);
  z-index: 1;
}

.status-info {
  flex: 1;
  position: relative;
  z-index: 2;
}

.status-info h3 {
  margin: 0 0 4px 0;
  font-size: 18px;
  font-weight: 600;
}

.status-info p {
  margin: 0;
  font-size: 14px;
  opacity: 0.8;
}

.status-badge {
  display: flex;
  align-items: center;
  background: rgba(255, 255, 255, 0.2);
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 14px;
  font-weight: 500;
  backdrop-filter: blur(10px);
  transition: all 0.3s ease;
  position: relative;
  z-index: 2;
}

.status-badge.active {
  background: rgba(16, 185, 129, 0.3);
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #fff;
  margin-right: 8px;
  opacity: 0.6;
  transition: all 0.3s ease;
}

.status-badge.active .status-dot {
  background: #10b981;
  opacity: 1;
  box-shadow: 0 0 8px rgba(16, 185, 129, 0.6);
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7);
  }
  70% {
    box-shadow: 0 0 0 10px rgba(16, 185, 129, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
  }
}

.card-content {
  padding: 20px;
}

.progress-container {
  margin-bottom: 16px;
  padding: 16px;
  background: linear-gradient(135deg, #f8fafc, #f1f5f9);
  border-radius: 12px;
  border: 1px solid #e2e8f0;
}

.progress-info {
  margin-bottom: 12px;
}

.progress-stats {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.stat-value {
  font-size: 24px;
  font-weight: 700;
  color: #3b82f6;
  line-height: 1;
}

.stat-label {
  font-size: 12px;
  color: #64748b;
  margin-top: 4px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.stat-divider {
  width: 1px;
  height: 40px;
  background: #e2e8f0;
}

.progress-bar-container {
  margin-bottom: 12px;
}

.progress-bar {
  height: 12px;
  background: #e2e8f0;
  border-radius: 6px;
  overflow: hidden;
  position: relative;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #3b82f6, #5b21b6);
  border-radius: 6px;
  transition: width 0.3s ease;
  position: relative;
}

.progress-shine {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
  border-radius: 6px;
  animation: shine 2s infinite;
}

@keyframes shine {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(200%);
  }
}

.current-operation {
  display: flex;
  align-items: center;
  color: #475569;
  font-size: 14px;
}

.operation-icon {
  margin-right: 8px;
  position: relative;
}

.pulse-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #3b82f6;
  animation: pulse 2s infinite;
}

.upgrade-options {
  margin-bottom: 16px;
}

.option-group {
  background: #ffffff;
  border-radius: 12px;
  border: 1px solid #e2e8f0;
  overflow: hidden;
}

.group-header {
  padding: 12px 16px;
  background: linear-gradient(135deg, #f8fafc, #f1f5f9);
  border-bottom: 1px solid #e2e8f0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.group-header h4 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #1e293b;
}

.header-decoration {
  width: 40px;
  height: 4px;
  background: linear-gradient(90deg, #3b82f6, #5b21b6);
  border-radius: 2px;
}

.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1px;
  background: #e2e8f0;
}

.setting-item {
  padding: 16px;
  background: #ffffff;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.setting-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.setting-icon {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.setting-icon::before {
  content: '';
  position: absolute;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #ffffff;
}

.hero-icon {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
}

.hero-icon::after {
  content: '⚔';
  position: absolute;
  font-size: 14px;
  color: white;
}

.book-icon {
  background: linear-gradient(135deg, #8b5cf6, #7c3aed);
}

.book-icon::after {
  content: '📖';
  position: absolute;
  font-size: 14px;
}

.reward-icon {
  background: linear-gradient(135deg, #10b981, #059669);
}

.reward-icon::after {
  content: '🎁';
  position: absolute;
  font-size: 14px;
}

.reward-times-icon {
  background: linear-gradient(135deg, #f59e0b, #d97706);
}

.reward-times-icon::after {
  content: '✨';
  position: absolute;
  font-size: 14px;
}

.setting-header label {
  font-weight: 500;
  color: #1e293b;
  font-size: 14px;
}

.input-wrapper {
  position: relative;
}

.setting-input {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  font-size: 14px;
  transition: all 0.2s ease;
  background: #ffffff;
}

.setting-input:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

.input-decoration {
  position: absolute;
  top: 0;
  right: 0;
  width: 4px;
  height: 100%;
  background: linear-gradient(135deg, #3b82f6, #5b21b6);
  border-radius: 0 8px 8px 0;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.setting-input:focus + .input-decoration {
  opacity: 1;
}

.checkbox-item {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
}

.checkbox-wrapper {
  display: flex;
  align-items: center;
  cursor: pointer;
  position: relative;
  margin-left: auto;
}

.setting-checkbox {
  position: absolute;
  opacity: 0;
  cursor: pointer;
}

.checkbox-decoration {
  width: 44px;
  height: 24px;
  background: #d1d5db;
  border-radius: 12px;
  position: relative;
  margin-right: 10px;
  transition: background 0.3s ease;
}

.setting-checkbox:checked + .checkbox-decoration {
  background: linear-gradient(135deg, #10b981, #059669);
}

.checkbox-checkmark {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background: #ffffff;
  border-radius: 50%;
  transition: transform 0.3s ease;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.setting-checkbox:checked + .checkbox-decoration .checkbox-checkmark {
  transform: translateX(20px);
}

.checkbox-label {
  font-size: 14px;
  font-weight: 500;
  color: #64748b;
  transition: color 0.3s ease;
}

.setting-checkbox:checked ~ .checkbox-label {
  color: #10b981;
}

.action-buttons {
  display: flex;
  gap: 12px;
  margin-bottom: 8px;
}

.action-button {
  flex: 1;
  padding: 0;
  border: none;
  border-radius: 12px;
  font-size: 16px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  overflow: hidden;
  position: relative;
}

.action-button.primary {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  color: white;
}

.action-button.primary:hover:not(:disabled) {
  background: linear-gradient(135deg, #2563eb, #1d4ed8);
  transform: translateY(-2px);
  box-shadow: 0 10px 20px rgba(59, 130, 246, 0.3);
}

.action-button.secondary {
  background: #ffffff;
  color: #475569;
  border: 1px solid #e2e8f0;
}

.action-button.secondary:hover:not(:disabled) {
  background: #f8fafc;
  transform: translateY(-2px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}

.action-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.button-content {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 20px;
  gap: 8px;
}

.button-icon {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.button-spinner {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top: 2px solid #ffffff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .upgrade-module-container {
    padding: 12px;
  }
  
  .card-header {
    padding: 16px;
  }
  
  .status-info h3 {
    font-size: 16px;
  }
  
  .status-info p {
    font-size: 12px;
  }
  
  .card-content {
    padding: 16px;
  }
  
  .progress-stats {
    flex-direction: column;
    gap: 12px;
  }
  
  .stat-divider {
    width: 100%;
    height: 1px;
  }
  
  .settings-grid {
    grid-template-columns: 1fr;
  }
  
  .action-buttons {
    flex-direction: column;
  }
}
</style>