<template>
  <div class="app-container">
    <div class="page-header">
      <div>
        <h2><i class="el-icon-s-data"></i> 爆品分析</h2>
        <p class="page-desc">支持在 SKU 和 SPU 两个维度查看爆品分析结果</p>
      </div>
      <div class="analysis-switch">
        <button
          v-for="item in analysisTabs"
          :key="item.value"
          type="button"
          class="switch-btn"
          :class="{ active: activeView === item.value }"
          @click="switchAnalysis(item.value)"
        >
          {{ item.label }}
        </button>
      </div>
    </div>

    <div class="upload-toolbar">
      <div class="toolbar-left">
        <el-upload
          ref="toolbarUpload"
          class="toolbar-upload"
          :limit="1"
          accept=".xlsx,.xls,.csv"
          :http-request="customUpload"
          :disabled="loading"
          :on-change="handleFileChange"
          :before-upload="beforeUpload"
          :auto-upload="false"
          :show-file-list="false"
        >
          <el-button plain>上传文件</el-button>
        </el-upload>
        <el-button :loading="loading" type="primary" @click="submitUpload">
          {{ loading ? '分析中...' : '开始分析' }}
        </el-button>
        <el-button type="success" :disabled="!hasResults" @click="exportResults">导出分析</el-button>
      </div>
      <div class="toolbar-status" v-if="upload.fileName">已上传：{{ upload.fileName }}</div>
      <div class="toolbar-status" v-else-if="upload.pendingFileName">已选择：{{ upload.pendingFileName }}</div>
      <div class="toolbar-status muted" v-else>未上传</div>
    </div>

    <div v-if="error" class="error-alert">
      <i class="el-icon-warning"></i>
      {{ error }}
    </div>

    <div class="stats-grid mb-20">
      <div class="stat-card">
        <div class="stat-header">
          <div>
            <p class="stat-label">总{{ currentConfig.entityName }}数</p>
            <p class="stat-value">{{ totalEntityCount }}</p>
          </div>
          <div class="stat-icon bg-blue">
            <i class="el-icon-files"></i>
          </div>
        </div>
        <div class="stat-footer">分析对象</div>
      </div>

      <div class="stat-card">
        <div class="stat-header">
          <div>
            <p class="stat-label">平均爆款系数</p>
            <p class="stat-value">{{ summary.avg_score || '-' }}</p>
          </div>
          <div class="stat-icon bg-green">
            <i class="el-icon-trend-charts"></i>
          </div>
        </div>
        <div class="stat-footer success">整体表现</div>
      </div>

      <div class="stat-card">
        <div class="stat-header">
          <div>
            <p class="stat-label">最高系数</p>
            <p class="stat-value">{{ summary.max_score || '-' }}</p>
          </div>
          <div class="stat-icon bg-yellow">
            <i class="el-icon-trophy"></i>
          </div>
        </div>
        <div class="stat-footer warning">顶尖表现</div>
      </div>

      <div class="stat-card">
        <div class="stat-header">
          <div>
            <p class="stat-label">超级爆款数</p>
            <p class="stat-value">{{ levelDistribution['超级爆款'] || 0 }}</p>
          </div>
          <div class="stat-icon bg-red">
            <i class="el-icon-star-on"></i>
          </div>
        </div>
        <div class="stat-footer danger">明星产品</div>
      </div>
    </div>

    <div class="charts-grid mb-20">
      <div class="chart-card">
        <div class="chart-header">
          <h3 class="chart-title">爆款等级分布</h3>
          <div class="chart-subtitle">按{{ currentConfig.entityName }}数量统计</div>
        </div>
        <div class="chart-container h-80">
          <canvas ref="levelDistChartRef"></canvas>
        </div>
      </div>

      <div class="chart-card">
        <div class="chart-header">
          <h3 class="chart-title">五维指标平均对比</h3>
          <div class="chart-subtitle">各等级指标表现</div>
        </div>
        <div class="chart-container h-80">
          <canvas ref="metricsCompareChartRef"></canvas>
        </div>
      </div>
    </div>

    <div class="table-card mb-20">
      <div class="table-header">
        <h3 class="table-title">{{ currentConfig.entityName }}详情列表</h3>
        <div class="table-filters">
          <el-select v-model="filterLevel" placeholder="全部等级" clearable size="small" class="filter-select">
            <el-option v-for="level in hotProductLevels" :key="level" :value="level" :label="level"></el-option>
          </el-select>
          <el-input
            v-model="searchKeyword"
            :placeholder="`搜索${currentConfig.entityName}或商品名称...`"
            size="small"
            prefix-icon="el-icon-search"
            class="filter-input"
            clearable
          />
        </div>
      </div>

      <div class="table-wrapper">
        <table class="data-table">
          <thead>
            <tr>
              <th @click="sortBy('hotproduct_score')" class="sortable">
                爆款系数
                <i :class="getSortIcon('hotproduct_score')"></i>
              </th>
              <th>等级</th>
              <th>{{ currentConfig.entityName }} ID</th>
              <th>商品名称</th>
              <th @click="sortBy('total_quantity')" class="sortable">
                总销量
                <i :class="getSortIcon('total_quantity')"></i>
              </th>
              <th @click="sortBy('total_revenue')" class="sortable">
                总销售额
                <i :class="getSortIcon('total_revenue')"></i>
              </th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="item in filteredAndSortedItems" :key="getEntityId(item)" class="data-row">
              <td>
                <div class="score-cell">
                  <div class="score-value">{{ item.hotproduct_score || '-' }}</div>
                  <div class="score-bar">
                    <div
                      class="score-progress"
                      :class="getScoreColorClass(item.hotproduct_score)"
                      :style="{ width: getScorePercent(item.hotproduct_score) + '%' }"
                    ></div>
                  </div>
                </div>
              </td>
              <td>
                <span class="level-badge" :class="getLevelBadgeClass(item.hotproduct_level)">
                  {{ item.hotproduct_level || '-' }}
                </span>
              </td>
              <td class="text-sm">{{ getEntityId(item) || '-' }}</td>
              <td class="text-sm product-title" :title="item.product_title">
                {{ item.product_title || '-' }}
              </td>
              <td class="text-sm">{{ getRawData(item, 'total_quantity') }}</td>
              <td class="text-sm">{{ formatCurrency(getRawData(item, 'total_revenue')) }}</td>
              <td>
                <el-button type="text" size="small" class="action-btn" @click="showDetail(item)">
                  查看详情
                </el-button>
              </td>
            </tr>
            <tr v-if="filteredAndSortedItems.length === 0">
              <td colspan="7" class="empty-state">
                <i class="el-icon-inbox"></i>
                <p>未找到符合条件的{{ currentConfig.entityName }}</p>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <el-dialog
      :visible.sync="detailVisible"
      :title="selectedItem ? selectedItem.product_title : ''"
      width="80%"
      top="5vh"
      custom-class="detail-dialog"
      :close-on-click-modal="false"
    >
      <div v-if="selectedItem" class="detail-content">
        <div class="detail-info mb-6">
          <p class="info-label">
            {{ currentConfig.entityName }} ID:
            <span class="info-value">{{ getEntityId(selectedItem) }}</span>
          </p>
        </div>

        <div class="detail-stats mb-6">
          <div class="detail-stat-card bg-blue-gradient">
            <p class="detail-stat-label">爆款系数</p>
            <p class="detail-stat-value">{{ selectedItem.hotproduct_score || '-' }}</p>
          </div>
          <div class="detail-stat-card bg-purple-gradient">
            <p class="detail-stat-label">爆款等级</p>
            <p class="detail-stat-value" :class="getLevelTextColor(selectedItem.hotproduct_level)">
              {{ selectedItem.hotproduct_level || '-' }}
            </p>
          </div>
        </div>

        <div class="detail-section mb-6">
          <h4 class="section-title">五维指标雷达图</h4>
          <div class="chart-container h-80">
            <canvas ref="radarChartRef"></canvas>
          </div>
        </div>

        <div class="detail-section mb-6">
          <h4 class="section-title">指标详情</h4>
          <div class="metrics-grid">
            <div v-for="metric in metricDefinitions" :key="metric.key" class="metric-item">
              <div class="metric-header">
                <span class="metric-name">{{ metric.label }}</span>
                <span class="metric-score">{{ getMetricValue(selectedItem, metric.key) }}</span>
              </div>
              <div class="metric-bar">
                <div
                  class="metric-progress"
                  :class="metric.className"
                  :style="{ width: getMetricPercentWidth(selectedItem, metric.key) + '%' }"
                ></div>
              </div>
              <p class="metric-weight">权重: {{ metric.weight }}</p>
            </div>
          </div>
        </div>

        <div class="detail-section mb-6">
          <h4 class="section-title">原始数据</h4>
          <div class="raw-data-grid">
            <div class="raw-data-item">
              <p class="raw-data-label">总销量</p>
              <p class="raw-data-value">{{ getRawData(selectedItem, 'total_quantity') }}</p>
            </div>
            <div class="raw-data-item">
              <p class="raw-data-label">总销售额</p>
              <p class="raw-data-value">{{ formatCurrency(getRawData(selectedItem, 'total_revenue')) }}</p>
            </div>
            <div class="raw-data-item">
              <p class="raw-data-label">平均价格</p>
              <p class="raw-data-value">{{ formatCurrency(getRawData(selectedItem, 'avg_price')) }}</p>
            </div>
            <div class="raw-data-item">
              <p class="raw-data-label">天数跨度</p>
              <p class="raw-data-value">{{ getRawData(selectedItem, 'days_span') }}天</p>
            </div>
            <div class="raw-data-item">
              <p class="raw-data-label">日均销量</p>
              <p class="raw-data-value">{{ getRawData(selectedItem, 'daily_sales') }}</p>
            </div>
            <div class="raw-data-item">
              <p class="raw-data-label">独立买家数</p>
              <p class="raw-data-value">{{ getRawData(selectedItem, 'unique_buyers') }}</p>
            </div>
            <div class="raw-data-item">
              <p class="raw-data-label">复购买家数</p>
              <p class="raw-data-value">{{ getRawData(selectedItem, 'repurchase_buyers') }}</p>
            </div>
            <div class="raw-data-item">
              <p class="raw-data-label">退款率</p>
              <p class="raw-data-value">{{ formatPercent(getRawData(selectedItem, 'refund_rate') * 100) }}</p>
            </div>
          </div>
        </div>

        <div class="advice-box">
          <h4 class="advice-title">
            <i class="el-icon-light-rain"></i>
            运营建议
          </h4>
          <p class="advice-content">{{ getOperationAdvice(selectedItem.hotproduct_level) }}</p>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { Chart } from 'chart.js'
import {
  analyzeHotProductWithFile,
  analyzeSpuHotProductWithFile,
  getHotProductResults,
  getSpuHotProductResults
} from '@/api/lifecycle'

const STORAGE_KEY = 'hotproduct_analysis_active_view'
const CACHE_CONFIG = {
  sku: {
    resultsKey: 'hotproduct_analysis_sku_results'
  },
  spu: {
    resultsKey: 'hotproduct_analysis_spu_results'
  }
}
const hotProductLevels = ['超级爆款', '潜力爆款', '常规款', '清货款']
const metricDefinitions = [
  { key: 'sales_heat', label: '销售热度（单位时间销量）', weight: '40%', className: 'bg-blue' },
  { key: 'price_acceptance', label: '价格接受度（实收率）', weight: '30%', className: 'bg-green' },
  { key: 'refund_stability', label: '退款稳定性（1-退款率）', weight: '10%', className: 'bg-yellow' },
  { key: 'repurchase_rate', label: '复购热度（复购率）', weight: '10%', className: 'bg-purple' },
  { key: 'night_burst', label: '夜间爆发力（0-6点占比）', weight: '10%', className: 'bg-indigo' }
]

const ANALYSIS_CONFIG = {
  sku: {
    label: 'SKU分析',
    entityName: 'SKU',
    resultKey: 'sku_results',
    idKey: 'sku_id',
    summaryCountKey: 'total_sku_count',
    exportPrefix: 'sku_hotproduct_results',
    analyze: analyzeHotProductWithFile,
    fetchResults: getHotProductResults
  },
  spu: {
    label: 'SPU分析',
    entityName: 'SPU',
    resultKey: 'spu_results',
    idKey: 'spu_id',
    summaryCountKey: 'total_spu_count',
    exportPrefix: 'spu_hotproduct_results',
    analyze: analyzeSpuHotProductWithFile,
    fetchResults: getSpuHotProductResults
  }
}

function createUploadState() {
  return {
    fileName: '',
    pendingFileName: '',
    ignoreFileChange: false
  }
}

function loadCachedResults(view) {
  const config = CACHE_CONFIG[view]
  try {
    const rawResults = localStorage.getItem(config.resultsKey)
    return rawResults ? JSON.parse(rawResults) : null
  } catch (e) {
    return null
  }
}

export default {
  name: 'HotProductAnalysis',
  data() {
    return {
      activeView: localStorage.getItem(STORAGE_KEY) === 'spu' ? 'spu' : 'sku',
      loadingByView: {
        sku: false,
        spu: false
      },
      errorByView: {
        sku: '',
        spu: ''
      },
      resultsByView: {
        sku: loadCachedResults('sku'),
        spu: loadCachedResults('spu')
      },
      uploadByView: {
        sku: createUploadState(),
        spu: createUploadState()
      },
      selectedItem: null,
      detailVisible: false,
      filterLevel: '',
      searchKeyword: '',
      sortColumn: 'hotproduct_score',
      sortOrder: 'desc',
      levelDistChart: null,
      metricsCompareChart: null,
      radarChart: null
    }
  },
  computed: {
    analysisTabs() {
      return [
        { label: 'SKU分析', value: 'sku' },
        { label: 'SPU分析', value: 'spu' }
      ]
    },
    currentConfig() {
      return ANALYSIS_CONFIG[this.activeView]
    },
    upload() {
      return this.uploadByView[this.activeView]
    },
    loading() {
      return this.loadingByView[this.activeView]
    },
    error() {
      return this.errorByView[this.activeView]
    },
    results() {
      return this.resultsByView[this.activeView]
    },
    hasResults() {
      return this.results !== null && Object.keys(this.results).length > 0
    },
    summary() {
      return (this.results && this.results.summary) || {}
    },
    levelDistribution() {
      return (this.summary && this.summary.level_distribution) || {}
    },
    totalEntityCount() {
      return this.summary[this.currentConfig.summaryCountKey] || this.itemList.length || 0
    },
    itemList() {
      if (!this.results || !this.results[this.currentConfig.resultKey]) return []
      return Object.values(this.results[this.currentConfig.resultKey])
    },
    filteredAndSortedItems() {
      let list = this.itemList.slice()

      if (this.filterLevel) {
        list = list.filter(item => item.hotproduct_level === this.filterLevel)
      }

      if (this.searchKeyword) {
        const keyword = String(this.searchKeyword).toLowerCase()
        list = list.filter(item => {
          const id = String(this.getEntityId(item) || '').toLowerCase()
          const title = String(item.product_title || '').toLowerCase()
          return id.includes(keyword) || title.includes(keyword)
        })
      }

      const column = this.sortColumn
      const order = this.sortOrder
      list.sort((a, b) => {
        let aValue = 0
        let bValue = 0

        if (column === 'hotproduct_score') {
          aValue = Number(a.hotproduct_score) || 0
          bValue = Number(b.hotproduct_score) || 0
        } else if (column === 'total_quantity') {
          aValue = Number(a.raw_data && a.raw_data.total_quantity) || 0
          bValue = Number(b.raw_data && b.raw_data.total_quantity) || 0
        } else if (column === 'total_revenue') {
          aValue = Number(a.raw_data && a.raw_data.total_revenue) || 0
          bValue = Number(b.raw_data && b.raw_data.total_revenue) || 0
        }

        return order === 'asc' ? aValue - bValue : bValue - aValue
      })

      return list
    },
    hotProductLevels() {
      return hotProductLevels
    },
    metricDefinitions() {
      return metricDefinitions
    }
  },
  watch: {
    activeView() {
      localStorage.setItem(STORAGE_KEY, this.activeView)
      this.closeDetail()
      this.resetUploaderSelection()
      this.fetchCurrentResults()
      this.$nextTick(() => {
        this.renderCharts()
      })
    },
    results() {
      this.$nextTick(() => {
        this.renderCharts()
      })
    },
    detailVisible(value) {
      if (!value && this.radarChart) {
        this.radarChart.destroy()
        this.radarChart = null
      } else if (value && this.selectedItem) {
        this.$nextTick(() => {
          this.renderRadarChart()
        })
      }
    }
  },
  mounted() {
    this.fetchCurrentResults()
    this.$nextTick(() => {
      this.renderCharts()
    })
  },
  beforeDestroy() {
    this.destroyCharts()
  },
  methods: {
    switchAnalysis(view) {
      if (view === this.activeView) return
      this.activeView = view
    },
    setError(value) {
      this.$set(this.errorByView, this.activeView, value || '')
    },
    setViewLoading(view, value) {
      this.$set(this.loadingByView, view, value)
    },
    setViewError(view, value) {
      this.$set(this.errorByView, view, value || '')
    },
    setViewResults(view, value) {
      this.$set(this.resultsByView, view, value || {})
      this.persistViewResults(view)
    },
    persistViewResults(view) {
      const config = CACHE_CONFIG[view]
      try {
        localStorage.setItem(config.resultsKey, JSON.stringify(this.resultsByView[view] || {}))
      } catch (e) {}
    },
    extractResultsPayload(response) {
      if (!response) return null
      if (response.success && response.data) return response.data
      if (response.data && typeof response.data === 'object') return response.data
      if (!response.message && !response.msg && typeof response === 'object') return response
      return null
    },
    fetchCurrentResults() {
      if (this.resultsByView[this.activeView]) return

      this.fetchResultsByView(this.activeView).catch(() => {})
    },
    fetchResultsByView(view) {
      const config = ANALYSIS_CONFIG[view]
      return config.fetchResults().then(response => {
        const results = this.extractResultsPayload(response)
        if (results) {
          this.setViewResults(view, results)
        }
        return results
      })
    },
    refreshAllResults() {
      return Promise.all(['sku', 'spu'].map(view => this.fetchResultsByView(view).catch(() => null)))
    },
    analyzeAllWithFile(file) {
      const tasks = ['sku', 'spu'].map(view => {
        const config = ANALYSIS_CONFIG[view]
        this.setViewLoading(view, true)
        this.setViewError(view, '')
        return config.analyze(file).then(response => {
          if (response && response.success) {
            this.setViewResults(view, response.data || {})
            return { view, success: true, response }
          }

          const message = response && (response.message || response.msg) ? response.message || response.msg : '分析失败'
          this.setViewError(view, message)
          return { view, success: false, message }
        }).catch(error => {
          const message = (error && error.response && error.response.data && error.response.data.message) ||
            (error && error.message) ||
            '文件上传失败，请重试'
          this.setViewError(view, message)
          return { view, success: false, error, message }
        }).finally(() => {
          this.setViewLoading(view, false)
        })
      })

      return Promise.all(tasks)
    },
    handleFileChange(file, fileList) {
      const upload = this.upload
      if (upload.ignoreFileChange) return
      if (!fileList || fileList.length === 0 || !file || !file.raw) return

      upload.pendingFileName = file.name
      upload.fileName = ''
    },
    beforeUpload(file) {
      const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
        file.type === 'application/vnd.ms-excel' ||
        file.type === 'text/csv' ||
        file.name.endsWith('.xlsx') ||
        file.name.endsWith('.xls') ||
        file.name.endsWith('.csv')
      const isLt500M = file.size / 1024 / 1024 < 500

      if (!isExcel) {
        this.$message.error('上传文件只能是 xlsx/xls/csv 格式')
        return false
      }
      if (!isLt500M) {
        this.$message.error('上传文件大小不能超过 500MB')
        return false
      }
      return true
    },
    uploadAllHotProductLevels(options) {
      const file = options.file
      const upload = this.upload

      return this.analyzeAllWithFile(file).then(results => {
        const failed = results.filter(item => !item.success)
        const succeeded = results.filter(item => item.success)

        if (succeeded.length > 0) {
          ;['sku', 'spu'].forEach(view => {
            this.uploadByView[view].fileName = upload.pendingFileName || file.name
            this.uploadByView[view].pendingFileName = ''
          })

          if (failed.length === 0) {
            this.$message.success('SKU/SPU爆品分析完成')
          } else {
            this.$message.warning(failed.map(item => `${ANALYSIS_CONFIG[item.view].entityName}: ${item.message}`).join('；'))
          }

          return this.refreshAllResults().then(() => results)
        }

        const message = failed.map(item => `${ANALYSIS_CONFIG[item.view].entityName}: ${item.message}`).join('；') || '分析失败'
        this.setError(message)
        this.$message.error(message)
        throw new Error(message)
      }).then(results => {
        if (results.some(item => item.success)) {
          this.$nextTick(() => {
            this.renderCharts()
          })
          options.onSuccess({ success: results.every(item => item.success), data: this.resultsByView })
        }
      }).catch(error => {
        options.onError(error)
      }).finally(() => {
        this.resetUploaderSelection()
      })
    },
    customUpload(options) {
      return this.uploadAllHotProductLevels(options)
    },
    submitUpload() {
      const target = this.$refs.toolbarUpload
      const fileList = target && target.uploadFiles ? target.uploadFiles : []
      if (!fileList || fileList.length === 0) {
        this.$message.error('请选择要上传的文件')
        return
      }
      target.submit()
    },
    resetUploaderSelection() {
      if (!this.$refs.toolbarUpload) return
      const upload = this.upload
      upload.ignoreFileChange = true
      this.$refs.toolbarUpload.clearFiles()
      this.$nextTick(() => {
        upload.ignoreFileChange = false
      })
    },
    renderCharts() {
      this.renderLevelDistChart()
      this.renderMetricsCompareChart()
    },
    renderLevelDistChart() {
      if (this.levelDistChart) {
        this.levelDistChart.destroy()
        this.levelDistChart = null
      }

      const canvas = this.$refs.levelDistChartRef
      if (!canvas) return

      const data = hotProductLevels.map(level => this.levelDistribution[level] || 0)
      const colors = ['#ef4444', '#f59e0b', '#10b981', '#6b7280']

      this.levelDistChart = new Chart(canvas, {
        type: 'doughnut',
        data: {
          labels: hotProductLevels,
          datasets: [{
            data,
            backgroundColor: colors,
            borderWidth: 2,
            borderColor: '#fff'
          }]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          legend: {
            position: 'right',
            labels: {
              padding: 15,
              fontSize: 12
            }
          },
          tooltips: {
            callbacks: {
              label(tooltipItem, chartData) {
                const label = chartData.labels[tooltipItem.index] || ''
                const value = chartData.datasets[0].data[tooltipItem.index] || 0
                const total = chartData.datasets[0].data.reduce((sum, item) => sum + item, 0)
                const percentage = total ? (value / total * 100).toFixed(1) : '0.0'
                return `${label}: ${value} (${percentage}%)`
              }
            }
          }
        }
      })
    },
    renderMetricsCompareChart() {
      if (this.metricsCompareChart) {
        this.metricsCompareChart.destroy()
        this.metricsCompareChart = null
      }

      const canvas = this.$refs.metricsCompareChartRef
      if (!canvas) return

      const metricKeys = metricDefinitions.map(metric => metric.key)
      const metricNames = metricDefinitions.map(metric => metric.label)
      const levelMetrics = {}

      hotProductLevels.forEach(level => {
        const items = this.itemList.filter(item => item.hotproduct_level === level)
        if (items.length > 0) {
          levelMetrics[level] = metricKeys.map(key => {
            const sum = items.reduce((total, item) => total + (Number(item.metrics && item.metrics[key]) || 0), 0)
            return sum / items.length
          })
        } else {
          levelMetrics[level] = metricKeys.map(() => 0)
        }
      })

      const baseColors = ['#ef4444', '#f59e0b', '#10b981', '#6b7280']
      const datasets = hotProductLevels.map((level, index) => ({
        label: level,
        data: levelMetrics[level] || [],
        backgroundColor: `${baseColors[index]}33`,
        borderColor: baseColors[index],
        borderWidth: 2,
        pointBackgroundColor: baseColors[index]
      }))

      this.metricsCompareChart = new Chart(canvas, {
        type: 'radar',
        data: {
          labels: metricNames,
          datasets
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          scale: {
            ticks: {
              beginAtZero: true,
              max: 1,
              stepSize: 0.2
            }
          },
          legend: {
            position: 'bottom'
          }
        }
      })
    },
    renderRadarChart() {
      if (!this.selectedItem) return
      if (this.radarChart) {
        this.radarChart.destroy()
        this.radarChart = null
      }

      const canvas = this.$refs.radarChartRef
      if (!canvas) return

      const metricNames = metricDefinitions.map(metric => metric.label)
      const data = metricDefinitions.map(metric => Number(this.selectedItem.metrics && this.selectedItem.metrics[metric.key]) || 0)

      this.radarChart = new Chart(canvas, {
        type: 'radar',
        data: {
          labels: metricNames,
          datasets: [{
            label: '指标得分',
            data,
            backgroundColor: 'rgba(59, 130, 246, 0.2)',
            borderColor: 'rgb(59, 130, 246)',
            borderWidth: 2,
            pointBackgroundColor: 'rgb(59, 130, 246)',
            pointBorderColor: '#fff',
            pointHoverBackgroundColor: '#fff',
            pointHoverBorderColor: 'rgb(59, 130, 246)'
          }]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          scale: {
            ticks: {
              beginAtZero: true,
              max: 1,
              stepSize: 0.2
            }
          },
          legend: {
            display: false
          }
        }
      })
    },
    showDetail(item) {
      this.selectedItem = item
      this.detailVisible = true
    },
    closeDetail() {
      this.detailVisible = false
      this.selectedItem = null
      if (this.radarChart) {
        this.radarChart.destroy()
        this.radarChart = null
      }
    },
    sortBy(column) {
      if (this.sortColumn === column) {
        this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc'
      } else {
        this.sortColumn = column
        this.sortOrder = 'desc'
      }
    },
    getSortIcon(column) {
      if (this.sortColumn !== column) return 'el-icon-d-caret'
      return this.sortOrder === 'asc' ? 'el-icon-caret-top' : 'el-icon-caret-bottom'
    },
    getEntityId(item) {
      return item ? item[this.currentConfig.idKey] : ''
    },
    getScorePercent(score) {
      const value = Number(score) || 0
      return Math.max(0, Math.min(100, value * 100))
    },
    getScoreColorClass(score) {
      const value = Number(score) || 0
      if (value >= 0.8) return 'score-red'
      if (value >= 0.6) return 'score-yellow'
      if (value >= 0.4) return 'score-green'
      return 'score-gray'
    },
    getLevelBadgeClass(level) {
      const classes = {
        '超级爆款': 'badge-red',
        '潜力爆款': 'badge-yellow',
        '常规款': 'badge-green',
        '清货款': 'badge-gray'
      }
      return classes[level] || 'badge-gray'
    },
    getLevelTextColor(level) {
      const colors = {
        '超级爆款': 'text-red',
        '潜力爆款': 'text-yellow',
        '常规款': 'text-green',
        '清货款': 'text-gray'
      }
      return colors[level] || 'text-gray'
    },
    getOperationAdvice(level) {
      const advice = {
        '超级爆款': '建议：立即加大库存备货，增加投流预算，抢占市场份额。该类产品需要重点维护和推广。',
        '潜力爆款': '建议：优化转化链路，提升用户体验，加强营销推广。该类产品有成为爆款的潜力，需要精心培育。',
        '常规款': '建议：维持现状，持续观察市场反馈。可以尝试小规模优化，但不需要大量投入资源。',
        '清货款': '建议：考虑清仓促销或直接下架，避免占用库存和运营资源，将精力投入更有潜力的产品。'
      }
      return advice[level] || '暂无建议'
    },
    getMetricValue(item, key) {
      if (!item || !item.metrics) return '-'
      const value = item.metrics[key]
      if (value == null) return '-'
      const numberValue = Number(value)
      return Number.isNaN(numberValue) ? String(value) : numberValue.toFixed(3)
    },
    getMetricPercentWidth(item, key) {
      if (!item || !item.metrics) return 0
      const value = Number(item.metrics[key]) || 0
      return Math.max(0, Math.min(100, value * 100))
    },
    getRawData(item, key) {
      if (!item || !item.raw_data) return '-'
      const value = item.raw_data[key]
      return value != null ? value : '-'
    },
    formatCurrency(value) {
      if (value == null || value === '-') return '-'
      const numberValue = Number(value)
      if (Number.isNaN(numberValue)) return '-'
      return `￥${numberValue.toFixed(2)}`
    },
    formatPercent(value) {
      if (value == null || value === '-') return '-'
      const numberValue = Number(value)
      if (Number.isNaN(numberValue)) return '-'
      return `${numberValue.toFixed(2)}%`
    },
    exportResults() {
      if (!this.hasResults) {
        this.$message.error('暂无可导出的分析结果')
        return
      }
      const payload = JSON.stringify(this.results, null, 2)
      const blob = new Blob([payload], { type: 'application/json;charset=utf-8' })
      const url = URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = url
      link.download = `${this.currentConfig.exportPrefix}_${new Date().toISOString().slice(0, 10)}.json`
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      URL.revokeObjectURL(url)
    },
    destroyCharts() {
      if (this.levelDistChart) this.levelDistChart.destroy()
      if (this.metricsCompareChart) this.metricsCompareChart.destroy()
      if (this.radarChart) this.radarChart.destroy()
      this.levelDistChart = null
      this.metricsCompareChart = null
      this.radarChart = null
    }
  }
}
</script>

<style scoped lang="scss">
.app-container {
  padding: 20px;
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;

  h2 {
    font-size: 24px;
    font-weight: 600;
    color: #303133;
    margin-bottom: 8px;

    i {
      margin-right: 8px;
      color: #409eff;
    }
  }

  .page-desc {
    color: #909399;
    font-size: 14px;
    margin: 0;
  }
}

.analysis-switch {
  display: inline-flex;
  padding: 4px;
  border-radius: 10px;
  background: #f3f6fb;
  border: 1px solid #dce6f2;
}

.switch-btn {
  border: none;
  background: transparent;
  color: #606266;
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
}

.switch-btn.active {
  background: #ffffff;
  color: #2563eb;
  box-shadow: 0 2px 8px rgba(37, 99, 235, 0.12);
}

.mb-20 { margin-bottom: 20px; }
.mb-6 { margin-bottom: 24px; }

.upload-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #ffffff;
  border: 1px solid #e6eaf2;
  border-radius: 8px;
  padding: 12px 16px;
  margin-bottom: 16px;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.toolbar-upload ::v-deep .el-upload {
  display: inline-flex;
}

.toolbar-status {
  font-size: 13px;
  color: #16a34a;
  background: #f0fdf4;
  border: 1px solid #dcfce7;
  border-radius: 6px;
  padding: 6px 10px;
}

.toolbar-status.muted {
  color: #6b7280;
  background: #f8fafc;
  border-color: #e2e8f0;
}

.error-alert {
  background: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: 8px;
  padding: 12px 16px;
  color: #dc2626;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 8px;

  i {
    font-size: 18px;
  }
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

.stat-card {
  background: #ffffff;
  border: 1px solid #e6eaf2;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
  transition: transform 0.2s ease, box-shadow 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(15, 23, 42, 0.1);
  }
}

.stat-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 12px;
}

.stat-label {
  font-size: 12px;
  color: #909399;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 8px;
}

.stat-value {
  font-size: 28px;
  font-weight: 700;
  color: #303133;
  margin: 0;
}

.stat-icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;

  &.bg-blue {
    background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
    color: #2563eb;
  }

  &.bg-green {
    background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
    color: #059669;
  }

  &.bg-yellow {
    background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
    color: #d97706;
  }

  &.bg-red {
    background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
    color: #dc2626;
  }
}

.stat-footer {
  font-size: 13px;
  color: #606266;

  &.success { color: #16a34a; }
  &.warning { color: #d97706; }
  &.danger { color: #dc2626; }
}

.charts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  gap: 20px;
}

.chart-card {
  background: #ffffff;
  border: 1px solid #e6eaf2;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
}

.chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.chart-title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
  margin: 0;
}

.chart-subtitle {
  font-size: 13px;
  color: #909399;
}

.chart-container {
  position: relative;

  &.h-80 {
    height: 320px;
  }
}

.table-card {
  background: #ffffff;
  border: 1px solid #e6eaf2;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
  flex-wrap: wrap;
  gap: 16px;
}

.table-title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
  margin: 0;
}

.table-filters {
  display: flex;
  gap: 12px;
  align-items: center;
}

.filter-select {
  width: 140px;
}

.filter-input {
  width: 260px;
}

.table-wrapper {
  overflow-x: auto;
}

.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;

  thead {
    background: #f8fafc;

    th {
      padding: 12px 16px;
      text-align: left;
      font-size: 12px;
      font-weight: 600;
      color: #606266;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      border-bottom: 1px solid #e5e7eb;

      &:first-child {
        border-top-left-radius: 8px;
      }

      &:last-child {
        border-top-right-radius: 8px;
      }

      &.sortable {
        cursor: pointer;
        user-select: none;

        &:hover {
          background: #f1f5f9;
        }

        i {
          margin-left: 4px;
          font-size: 14px;
        }
      }
    }
  }

  tbody {
    tr.data-row {
      transition: background-color 0.2s;

      &:hover {
        background: #f9fafb;
      }

      td {
        padding: 16px;
        border-bottom: 1px solid #e5e7eb;
        font-size: 14px;
        color: #303133;

        &.text-sm {
          font-size: 13px;
        }

        &.product-title {
          max-width: 300px;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      }
    }

    tr:last-child td {
      border-bottom: none;
    }
  }
}

.score-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.score-value {
  font-weight: 700;
  min-width: 40px;
}

.score-bar {
  flex: 1;
  height: 8px;
  background: #f3f4f6;
  border-radius: 999px;
  overflow: hidden;
  max-width: 80px;
}

.score-progress {
  height: 100%;
  border-radius: 999px;
  transition: width 0.3s;

  &.score-red { background: #ef4444; }
  &.score-yellow { background: #f59e0b; }
  &.score-green { background: #10b981; }
  &.score-gray { background: #6b7280; }
}

.level-badge {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;

  &.badge-red {
    background: #fee2e2;
    color: #991b1b;
  }

  &.badge-yellow {
    background: #fef3c7;
    color: #92400e;
  }

  &.badge-green {
    background: #d1fae5;
    color: #065f46;
  }

  &.badge-gray {
    background: #f3f4f6;
    color: #374151;
  }
}

.action-btn {
  color: #409eff;
  font-weight: 500;

  &:hover {
    color: #66b1ff;
  }
}

.empty-state {
  padding: 60px 20px !important;
  text-align: center;
  color: #909399;

  i {
    font-size: 48px;
    display: block;
    margin-bottom: 12px;
  }

  p {
    margin: 0;
    font-size: 14px;
  }
}

.detail-dialog ::v-deep .el-dialog__header {
  border-bottom: 1px solid #e5e7eb;
  padding: 20px 24px;
}

.detail-dialog ::v-deep .el-dialog__body {
  padding: 24px;
}

.detail-content {
  max-height: 70vh;
  overflow-y: auto;
}

.detail-info {
  .info-label {
    font-size: 14px;
    color: #606266;
    margin: 0;
  }

  .info-value {
    font-weight: 600;
    color: #303133;
  }
}

.detail-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}

.detail-stat-card {
  padding: 20px;
  border-radius: 8px;

  &.bg-blue-gradient {
    background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
  }

  &.bg-purple-gradient {
    background: linear-gradient(135deg, #f3e8ff 0%, #e9d5ff 100%);
  }
}

.detail-stat-label {
  font-size: 13px;
  color: #606266;
  margin-bottom: 8px;
}

.detail-stat-value {
  font-size: 32px;
  font-weight: 700;
  color: #303133;
  margin: 0;

  &.text-red { color: #dc2626; }
  &.text-yellow { color: #d97706; }
  &.text-green { color: #059669; }
  &.text-gray { color: #6b7280; }
}

.detail-section {
  .section-title {
    font-size: 16px;
    font-weight: 600;
    color: #303133;
    margin-bottom: 16px;
  }
}

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 16px;
}

.metric-item {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 16px;
  background: #f9fafb;
}

.metric-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
  gap: 12px;
}

.metric-name {
  font-size: 13px;
  color: #606266;
}

.metric-score {
  font-size: 16px;
  font-weight: 700;
  color: #303133;
  white-space: nowrap;
}

.metric-bar {
  height: 8px;
  background: #e5e7eb;
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 8px;
}

.metric-progress {
  height: 100%;
  border-radius: 999px;

  &.bg-blue { background: #3b82f6; }
  &.bg-green { background: #10b981; }
  &.bg-yellow { background: #f59e0b; }
  &.bg-purple { background: #8b5cf6; }
  &.bg-indigo { background: #6366f1; }
}

.metric-weight {
  font-size: 12px;
  color: #909399;
  margin: 0;
}

.raw-data-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}

.raw-data-item {
  background: #f9fafb;
  border-radius: 8px;
  padding: 16px;
}

.raw-data-label {
  font-size: 12px;
  color: #909399;
  margin-bottom: 4px;
}

.raw-data-value {
  font-size: 18px;
  font-weight: 700;
  color: #303133;
  margin: 0;
}

.advice-box {
  background: #eff6ff;
  border: 1px solid #bfdbfe;
  border-radius: 8px;
  padding: 16px;
}

.advice-title {
  font-size: 16px;
  font-weight: 600;
  color: #1e40af;
  margin-bottom: 8px;

  i {
    margin-right: 8px;
  }
}

.advice-content {
  font-size: 14px;
  color: #1e3a8a;
  margin: 0;
  line-height: 1.6;
}

@media (max-width: 767px) {
  .page-header,
  .upload-toolbar,
  .table-header,
  .chart-header {
    flex-direction: column;
    align-items: stretch;
  }

  .analysis-switch,
  .toolbar-left,
  .table-filters {
    width: 100%;
  }

  .switch-btn {
    flex: 1;
  }

  .toolbar-left,
  .table-filters {
    flex-wrap: wrap;
  }

  .filter-select,
  .filter-input {
    width: 100%;
  }

  .charts-grid {
    grid-template-columns: 1fr;
  }

  .detail-stats {
    grid-template-columns: 1fr;
  }
}
</style>
