<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="toolbar-card">
      <div class="toolbar-left">
        <el-date-picker
          v-model="dateRange"
          type="daterange"
          unlink-panels
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          value-format="yyyy-MM-dd"
          class="date-picker"
          @change="handleDateChange"
        />
        <el-button type="primary" :loading="loading" @click="refreshAllResults">
          {{ loading ? '加载中...' : '刷新分析' }}
        </el-button>
        <el-button :disabled="!hasResults" @click="exportResults">导出结果</el-button>
      </div>
      <div class="toolbar-status">
        <span v-if="lastUpdated">最近刷新：{{ lastUpdated }}</span>
        <span v-else>尚未加载数据库分析结果</span>
      </div>
    </div>

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

    <template v-if="hasResults">
      <div class="stats-grid mb-20">
        <div class="stat-card">
          <div class="stat-label">总{{ currentConfig.entityName }}数</div>
          <div class="stat-value">{{ totalEntityCount }}</div>
          <div class="stat-desc">分析对象总量</div>
        </div>
        <div class="stat-card">
          <div class="stat-label">平均爆品系数</div>
          <div class="stat-value">{{ formatScore(summary.avg_score) }}</div>
          <div class="stat-desc">整体表现</div>
        </div>
        <div class="stat-card">
          <div class="stat-label">最高系数</div>
          <div class="stat-value">{{ formatScore(summary.max_score) }}</div>
          <div class="stat-desc">头部商品表现</div>
        </div>
        <div class="stat-card accent">
          <div class="stat-label">超级爆款数</div>
          <div class="stat-value">{{ levelDistribution['超级爆款'] || 0 }}</div>
          <div class="stat-desc">重点关注商品</div>
        </div>
      </div>

      <div class="charts-grid mb-20">
        <div class="chart-card">
          <div class="chart-header">
            <h3>爆品等级分布</h3>
            <p>当前{{ currentConfig.entityName }}维度等级构成</p>
          </div>
          <div class="chart-body">
            <canvas ref="levelDistChartRef"></canvas>
          </div>
        </div>
        <div class="chart-card">
          <div class="chart-header">
            <h3>五维指标均值对比</h3>
            <p>各等级商品指标表现</p>
          </div>
          <div class="chart-body">
            <canvas ref="metricsCompareChartRef"></canvas>
          </div>
        </div>
      </div>

      <div class="table-card mb-20">
        <div class="table-header">
          <div>
            <h3>{{ currentConfig.entityName }} 详情列表</h3>
            <p>支持按等级、关键字和分值排序查看。</p>
          </div>
          <div class="table-tools">
            <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-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 class="sortable" @click="sortBy('hotproduct_score')">
                  爆品系数
                  <i :class="getSortIcon('hotproduct_score')"></i>
                </th>
                <th>等级</th>
                <th>{{ currentConfig.entityName }} ID</th>
                <th>商品名称</th>
                <th class="sortable" @click="sortBy('total_quantity')">
                  总销量
                  <i :class="getSortIcon('total_quantity')"></i>
                </th>
                <th class="sortable" @click="sortBy('total_revenue')">
                  总销售额
                  <i :class="getSortIcon('total_revenue')"></i>
                </th>
                <th>操作</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="item in filteredAndSortedItems" :key="getEntityId(item)">
                <td>
                  <div class="score-cell">
                    <span class="score-value">{{ formatScore(item.hotproduct_score) }}</span>
                    <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>{{ getEntityId(item) || '-' }}</td>
                <td class="product-title" :title="item.product_title">{{ item.product_title || '-' }}</td>
                <td>{{ getRawData(item, 'total_quantity') }}</td>
                <td>{{ formatCurrency(getRawData(item, 'total_revenue')) }}</td>
                <td>
                  <el-button type="text" size="small" @click="showDetail(item)">查看详情</el-button>
                </td>
              </tr>
              <tr v-if="filteredAndSortedItems.length === 0">
                <td colspan="7" class="empty-cell">
                  未找到符合条件的{{ currentConfig.entityName }}数据
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </template>

    <div v-else class="empty-state">
      <i class="el-icon-data-board"></i>
      <p>当前没有数据库爆品分析结果，请调整日期范围后刷新。</p>
    </div>

    <el-dialog
      :visible.sync="detailVisible"
      width="80%"
      top="5vh"
      custom-class="detail-dialog"
      :close-on-click-modal="false"
    >
      <template slot="title">
        <span>{{ selectedItem ? selectedItem.product_title : '爆品详情' }}</span>
      </template>

      <div v-if="selectedItem" class="detail-content">
        <div class="detail-top mb-20">
          <div class="detail-hero">
            <p class="detail-id">{{ currentConfig.entityName }} ID：{{ getEntityId(selectedItem) }}</p>
            <div class="detail-score-row">
              <div class="detail-score-card">
                <span>爆品系数</span>
                <strong>{{ formatScore(selectedItem.hotproduct_score) }}</strong>
              </div>
              <div class="detail-score-card">
                <span>爆品等级</span>
                <strong :class="getLevelTextColor(selectedItem.hotproduct_level)">{{ selectedItem.hotproduct_level }}</strong>
              </div>
            </div>
            <p class="detail-advice">{{ getOperationAdvice(selectedItem.hotproduct_level) }}</p>
          </div>
          <div class="detail-radar">
            <canvas ref="radarChartRef"></canvas>
          </div>
        </div>

        <div class="metrics-grid mb-20">
          <div v-for="metric in metricDefinitions" :key="metric.key" class="metric-item">
            <div class="metric-header">
              <span>{{ metric.label }}</span>
              <strong>{{ getMetricValue(selectedItem, metric.key) }}</strong>
            </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 class="raw-grid">
          <div class="raw-item">
            <span>总销量</span>
            <strong>{{ getRawData(selectedItem, 'total_quantity') }}</strong>
          </div>
          <div class="raw-item">
            <span>总销售额</span>
            <strong>{{ formatCurrency(getRawData(selectedItem, 'total_revenue')) }}</strong>
          </div>
          <div class="raw-item">
            <span>平均价格</span>
            <strong>{{ formatCurrency(getRawData(selectedItem, 'avg_price')) }}</strong>
          </div>
          <div class="raw-item">
            <span>跨度天数</span>
            <strong>{{ getRawData(selectedItem, 'days_span') }}</strong>
          </div>
          <div class="raw-item">
            <span>日均销量</span>
            <strong>{{ getRawData(selectedItem, 'daily_sales') }}</strong>
          </div>
          <div class="raw-item">
            <span>近似买家数</span>
            <strong>{{ getRawData(selectedItem, 'unique_buyers') }}</strong>
          </div>
          <div class="raw-item">
            <span>近似复购主体数</span>
            <strong>{{ getRawData(selectedItem, 'repurchase_buyers') }}</strong>
          </div>
          <div class="raw-item">
            <span>退款率</span>
            <strong>{{ formatPercent(Number(getRawData(selectedItem, 'refund_rate')) * 100) }}</strong>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { Chart } from 'chart.js'
import { formatCurrency } from '@/utils/format'
import {
  getLifecycleDatabaseHotProductSkuResults,
  getLifecycleDatabaseHotProductSpuResults
} from '@/api/lifecycleDatabase'

const STORAGE_KEY = 'hotproduct_database_analysis_active_view'
const DATE_RANGE_KEY = 'hotproduct_database_analysis_date_range'
const LAST_UPDATED_KEY = 'hotproduct_database_analysis_last_updated'
const CACHE_CONFIG = {
  sku: {
    resultsKey: 'hotproduct_database_analysis_sku_results'
  },
  spu: {
    resultsKey: 'hotproduct_database_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: '退款稳定性', weight: '10%', className: 'bg-yellow' },
  { key: 'repurchase_rate', label: '复购热度', weight: '10%', className: 'bg-purple' },
  { key: 'night_burst', label: '夜间爆发力', 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_database_results',
    fetchResults: getLifecycleDatabaseHotProductSkuResults
  },
  spu: {
    label: 'SPU 分析',
    entityName: 'SPU',
    resultKey: 'spu_results',
    idKey: 'spu_id',
    summaryCountKey: 'total_spu_count',
    exportPrefix: 'spu_hotproduct_database_results',
    fetchResults: getLifecycleDatabaseHotProductSpuResults
  }
}

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

function loadCachedDateRange() {
  try {
    const raw = localStorage.getItem(DATE_RANGE_KEY)
    return raw ? JSON.parse(raw) : []
  } catch (e) {
    return []
  }
}

export default {
  name: 'HotProductAnalysisDatabase',
  data() {
    return {
      activeView: localStorage.getItem(STORAGE_KEY) === 'spu' ? 'spu' : 'sku',
      dateRange: loadCachedDateRange(),
      lastUpdated: localStorage.getItem(LAST_UPDATED_KEY) || '',
      loadingByView: {
        sku: false,
        spu: false
      },
      errorByView: {
        sku: '',
        spu: ''
      },
      resultsByView: {
        sku: loadCachedResults('sku'),
        spu: loadCachedResults('spu')
      },
      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]
    },
    loading() {
      return this.loadingByView[this.activeView]
    },
    error() {
      return this.errorByView[this.activeView]
    },
    results() {
      return this.resultsByView[this.activeView]
    },
    hasResults() {
      return !!(this.results && this.results[this.currentConfig.resultKey] && Object.keys(this.results[this.currentConfig.resultKey]).length)
    },
    summary() {
      return (this.results && this.results.summary) || {}
    },
    levelDistribution() {
      return this.summary.level_distribution || {}
    },
    itemList() {
      if (!this.results || !this.results[this.currentConfig.resultKey]) {
        return []
      }
      return Object.values(this.results[this.currentConfig.resultKey])
    },
    totalEntityCount() {
      return this.summary[this.currentConfig.summaryCountKey] || this.itemList.length || 0
    },
    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).trim().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)
        })
      }

      list.sort((a, b) => {
        let aValue = 0
        let bValue = 0

        if (this.sortColumn === 'hotproduct_score') {
          aValue = Number(a.hotproduct_score) || 0
          bValue = Number(b.hotproduct_score) || 0
        } else if (this.sortColumn === '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 (this.sortColumn === '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 this.sortOrder === 'asc' ? aValue - bValue : bValue - aValue
      })

      return list
    },
    hotProductLevels() {
      return hotProductLevels
    },
    metricDefinitions() {
      return metricDefinitions
    }
  },
  watch: {
    activeView() {
      localStorage.setItem(STORAGE_KEY, this.activeView)
      this.closeDetail()
      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() {
    if (!this.resultsByView.sku && !this.resultsByView.spu) {
      this.refreshAllResults()
    } else {
      this.$nextTick(() => {
        this.renderCharts()
      })
    }
  },
  beforeDestroy() {
    this.destroyCharts()
  },
  methods: {
    switchAnalysis(view) {
      if (view !== this.activeView) {
        this.activeView = view
      }
    },
    handleDateChange() {
      try {
        localStorage.setItem(DATE_RANGE_KEY, JSON.stringify(this.dateRange || []))
      } catch (e) {}
    },
    buildParams() {
      return {
        startDate: this.dateRange && this.dateRange.length ? this.dateRange[0] : undefined,
        endDate: this.dateRange && this.dateRange.length ? this.dateRange[1] : undefined
      }
    },
    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 || null)
      try {
        localStorage.setItem(CACHE_CONFIG[view].resultsKey, JSON.stringify(value || null))
      } catch (e) {}
    },
    extractPayload(response) {
      if (!response) return null
      if (response.data && typeof response.data === 'object') return response.data
      if (response.success && response.data) return response.data
      return null
    },
    fetchResultsByView(view) {
      const config = ANALYSIS_CONFIG[view]
      this.setViewLoading(view, true)
      this.setViewError(view, '')

      return config.fetchResults(this.buildParams()).then(response => {
        const payload = this.extractPayload(response)
        this.setViewResults(view, payload)
        return payload
      }).catch(error => {
        const message = (error && error.message) || `${config.entityName} 爆品分析加载失败`
        this.setViewError(view, message)
        throw error
      }).finally(() => {
        this.setViewLoading(view, false)
      })
    },
    refreshAllResults() {
      this.handleDateChange()
      return Promise.all([
        this.fetchResultsByView('sku').catch(() => null),
        this.fetchResultsByView('spu').catch(() => null)
      ]).then(results => {
        this.lastUpdated = this.formatDateTime(new Date())
        localStorage.setItem(LAST_UPDATED_KEY, this.lastUpdated)
        this.$nextTick(() => {
          this.renderCharts()
        })
        if (results.some(Boolean)) {
          this.$message.success('数据库爆品分析结果已刷新')
        } else {
          this.$message.error('数据库爆品分析结果加载失败')
        }
      })
    },
    renderCharts() {
      this.renderLevelDistChart()
      this.renderMetricsCompareChart()
    },
    renderLevelDistChart() {
      if (this.levelDistChart) {
        this.levelDistChart.destroy()
        this.levelDistChart = null
      }

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

      const colors = ['#ef4444', '#f59e0b', '#10b981', '#94a3b8']
      this.levelDistChart = new Chart(canvas, {
        type: 'doughnut',
        data: {
          labels: hotProductLevels,
          datasets: [{
            data: hotProductLevels.map(level => this.levelDistribution[level] || 0),
            backgroundColor: colors,
            borderWidth: 2,
            borderColor: '#fff'
          }]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          legend: {
            position: 'right'
          }
        }
      })
    },
    renderMetricsCompareChart() {
      if (this.metricsCompareChart) {
        this.metricsCompareChart.destroy()
        this.metricsCompareChart = null
      }

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

      const colors = ['#ef4444', '#f59e0b', '#10b981', '#64748b']
      const datasets = hotProductLevels.map((level, index) => {
        const items = this.itemList.filter(item => item.hotproduct_level === level)
        const values = metricDefinitions.map(metric => {
          if (!items.length) return 0
          const total = items.reduce((sum, item) => sum + (Number(item.metrics && item.metrics[metric.key]) || 0), 0)
          return total / items.length
        })

        return {
          label: level,
          data: values,
          backgroundColor: `${colors[index]}22`,
          borderColor: colors[index],
          borderWidth: 2,
          pointBackgroundColor: colors[index]
        }
      })

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

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

      this.radarChart = new Chart(canvas, {
        type: 'radar',
        data: {
          labels: metricDefinitions.map(item => item.label),
          datasets: [{
            label: '指标得分',
            data: metricDefinitions.map(item => Number(this.selectedItem.metrics && this.selectedItem.metrics[item.key]) || 0),
            backgroundColor: 'rgba(37, 99, 235, 0.18)',
            borderColor: '#2563eb',
            borderWidth: 2,
            pointBackgroundColor: '#2563eb'
          }]
        },
        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
    },
    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] : ''
    },
    getMetricValue(item, key) {
      const value = Number(item && item.metrics && item.metrics[key])
      return Number.isFinite(value) ? value.toFixed(3) : '-'
    },
    getMetricPercentWidth(item, key) {
      const value = Number(item && item.metrics && item.metrics[key]) || 0
      return Math.max(0, Math.min(100, value * 100))
    },
    getRawData(item, key) {
      return item && item.raw_data && item.raw_data[key] != null ? item.raw_data[key] : '-'
    },
    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) {
      return {
        '超级爆款': 'badge-red',
        '潜力爆款': 'badge-yellow',
        '常规款': 'badge-green',
        '清货款': 'badge-gray'
      }[level] || 'badge-gray'
    },
    getLevelTextColor(level) {
      return {
        '超级爆款': 'text-red',
        '潜力爆款': 'text-yellow',
        '常规款': 'text-green',
        '清货款': 'text-gray'
      }[level] || 'text-gray'
    },
    getOperationAdvice(level) {
      return {
        '超级爆款': '建议优先补货、提高曝光，并持续跟踪退款和夜间流量波动。',
        '潜力爆款': '建议加大投放并优化转化链路，重点观察复购表现和价格接受度。',
        '常规款': '建议稳定运营，结合促销节奏逐步测试增长空间。',
        '清货款': '建议控制库存和投放，优先考虑清货或替换策略。'
      }[level] || '暂无建议'
    },
    formatScore(value) {
      const numberValue = Number(value)
      return Number.isFinite(numberValue) ? numberValue.toFixed(4) : '-'
    },
    formatCurrency(value) {
      if (value == null || value === '-') return '-'
      return formatCurrency(Number(value) || 0)
    },
    formatPercent(value) {
      const numberValue = Number(value)
      return Number.isFinite(numberValue) ? `${numberValue.toFixed(2)}%` : '-'
    },
    formatDateTime(date) {
      const pad = value => String(value).padStart(2, '0')
      return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
    },
    exportResults() {
      if (!this.hasResults) {
        this.$message.error('当前没有可导出的分析结果')
        return
      }

      const blob = new Blob([JSON.stringify(this.results, null, 2)], { 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,
.toolbar-card,
.stat-card,
.chart-card,
.table-card,
.empty-state,
.detail-hero,
.raw-item {
  background: #fff;
  border: 1px solid #e5e7eb;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
}

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

.page-header h2 {
  margin: 0 0 8px;
  font-size: 24px;
  color: #0f172a;
}

.page-header i {
  margin-right: 8px;
  color: #2563eb;
}

.page-desc {
  margin: 0;
  color: #64748b;
}

.analysis-switch {
  display: inline-flex;
  padding: 4px;
  border-radius: 12px;
  background: #eff6ff;
  border: 1px solid #bfdbfe;
}

.switch-btn {
  border: none;
  background: transparent;
  color: #475569;
  padding: 8px 18px;
  border-radius: 10px;
  cursor: pointer;
}

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

.toolbar-card {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: center;
  padding: 16px 20px;
  border-radius: 16px;
  margin-bottom: 16px;
}

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

.toolbar-status {
  color: #64748b;
  font-size: 13px;
}

.date-picker {
  width: 300px;
}

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

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

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

.stat-card {
  padding: 20px;
  border-radius: 16px;
}

.stat-card.accent {
  background: linear-gradient(135deg, #fff1f2, #ffffff);
}

.stat-label {
  color: #64748b;
  font-size: 13px;
  margin-bottom: 10px;
}

.stat-value {
  font-size: 30px;
  font-weight: 700;
  color: #0f172a;
  margin-bottom: 8px;
}

.stat-desc {
  color: #94a3b8;
  font-size: 12px;
}

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

.chart-card,
.table-card {
  border-radius: 16px;
  padding: 20px;
}

.chart-header h3,
.table-header h3 {
  margin: 0 0 6px;
  color: #0f172a;
}

.chart-header p,
.table-header p {
  margin: 0;
  color: #64748b;
  font-size: 13px;
}

.chart-body {
  height: 320px;
  margin-top: 16px;
}

.table-header {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.table-tools {
  display: flex;
  gap: 10px;
  align-items: center;
}

.filter-select {
  width: 150px;
}

.filter-input {
  width: 220px;
}

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

.data-table {
  width: 100%;
  border-collapse: collapse;
}

.data-table th,
.data-table td {
  padding: 14px 12px;
  border-bottom: 1px solid #e5e7eb;
  text-align: left;
  color: #334155;
  font-size: 13px;
}

.data-table th {
  color: #64748b;
  font-weight: 600;
  background: #f8fafc;
}

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

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

.score-cell {
  min-width: 140px;
}

.score-value {
  display: inline-block;
  margin-bottom: 6px;
  font-weight: 600;
}

.score-bar,
.metric-bar {
  height: 8px;
  border-radius: 999px;
  background: #e2e8f0;
  overflow: hidden;
}

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

.score-red { background: #ef4444; }
.score-yellow { background: #f59e0b; }
.score-green { background: #10b981; }
.score-gray { background: #94a3b8; }
.bg-blue { background: #3b82f6; }
.bg-green { background: #10b981; }
.bg-yellow { background: #f59e0b; }
.bg-purple { background: #8b5cf6; }
.bg-indigo { background: #6366f1; }

.level-badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}

.badge-red { color: #b91c1c; background: #fee2e2; }
.badge-yellow { color: #b45309; background: #fef3c7; }
.badge-green { color: #047857; background: #d1fae5; }
.badge-gray { color: #475569; background: #e2e8f0; }

.text-red { color: #dc2626; }
.text-yellow { color: #d97706; }
.text-green { color: #059669; }
.text-gray { color: #64748b; }

.empty-state {
  padding: 48px 24px;
  text-align: center;
  border-radius: 16px;
  color: #64748b;
}

.empty-state i {
  font-size: 40px;
  color: #94a3b8;
  margin-bottom: 12px;
}

.empty-cell {
  text-align: center !important;
  color: #94a3b8 !important;
}

.detail-content {
  padding-top: 8px;
}

.detail-top {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 16px;
}

.detail-hero {
  border-radius: 16px;
  padding: 20px;
}

.detail-id {
  margin: 0 0 18px;
  color: #475569;
}

.detail-score-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.detail-score-card {
  padding: 16px;
  border-radius: 14px;
  background: linear-gradient(135deg, #eff6ff, #ffffff);
  border: 1px solid #dbeafe;
}

.detail-score-card span {
  display: block;
  font-size: 12px;
  color: #64748b;
  margin-bottom: 8px;
}

.detail-score-card strong {
  font-size: 24px;
  color: #0f172a;
}

.detail-advice {
  margin: 0;
  color: #334155;
  line-height: 1.7;
}

.detail-radar {
  height: 320px;
  padding: 12px;
}

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.metric-item {
  padding: 16px;
  border-radius: 14px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
}

.metric-header {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  color: #334155;
  font-size: 13px;
}

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

.raw-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}

.raw-item {
  border-radius: 14px;
  padding: 16px;
}

.raw-item span {
  display: block;
  font-size: 12px;
  color: #64748b;
  margin-bottom: 8px;
}

.raw-item strong {
  font-size: 20px;
  color: #0f172a;
}

@media (max-width: 1200px) {
  .charts-grid,
  .detail-top,
  .raw-grid {
    grid-template-columns: 1fr;
  }
}

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

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

  .metrics-grid,
  .detail-score-row {
    grid-template-columns: 1fr;
  }
}
</style>
