<template>
  <div class="shop-value-analysis-page">
    <header class="page-header">
      <div>
        <h1 class="main-title">店铺价值分析</h1>
        <p class="subtitle">实时监控关键指标与趋势</p>
      </div>
      <div class="header-actions">
        <span class="control-label">时间筛选</span>
        <el-date-picker
          v-model="selectedDate"
          class="date-picker"
          type="date"
          value-format="yyyy-MM-dd"
          :clearable="false"
          :editable="false"
          :picker-options="pickerOptions"
          placeholder="选择上传数据日期"
          @change="handleDateChange"
        />
        <div class="tab-group">
          <button :class="['time-tab', { active: activeTab === 'day' }]" @click="applyDateFilter('day')">当天</button>
          <button :class="['time-tab', { active: activeTab === '7d' }]" @click="applyDateFilter('7d')">最近7天</button>
          <button :class="['time-tab', { active: activeTab === 'tm' }]" @click="applyDateFilter('tm')">本月</button>
          <button :class="['time-tab', { active: activeTab === 'lm' }]" @click="applyDateFilter('lm')">上月</button>
          <button :class="['time-tab', { active: activeTab === 'all' }]" @click="applyDateFilter('all')">全量数据</button>
        </div>
      </div>
    </header>

    <div class="upload-row">
      <button class="btn-upload" :disabled="uploadingShop" @click="triggerShopUpload">
        {{ uploadingShop ? '上传中...' : '上传CSV导入' }}
      </button>
      <input
        ref="shopUploadInput"
        type="file"
        accept=".csv"
        multiple
        style="display: none;"
        @change="handleShopUploadChange"
      >
    </div>

    <div class="chart-card">
      <div class="top-product-contribution-container">
        <div class="kpi-card-grid">
          <div class="kpi-card">
            <span class="kpi-title">总销售额</span>
            <span class="kpi-value">¥{{ formatNumber(topProductData.totalSales) }}</span>
          </div>
          <div class="kpi-card">
            <span class="kpi-title">Top 5 商品总销售额</span>
            <span class="kpi-value">¥{{ formatNumber(topProductData.top5TotalSales) }}</span>
          </div>
          <div class="kpi-card">
            <span class="kpi-title">Top 5 贡献占比</span>
            <span class="kpi-value">{{ (topProductData.contributionRatio * 100).toFixed(2) }}%</span>
          </div>
        </div>

        <div class="chart-card inner-chart-card">
          <h3 class="chart-title">Top 5 商品销售分布</h3>
          <div ref="donutChartRef" style="width: 100%; height: 400px;"></div>
        </div>
      </div>
    </div>

    <div class="charts-container">
      <div class="chart-card">
        <div class="card-header">
          <h3 class="chart-title">各部门业绩分析（销量 / 销售额）</h3>
        </div>
        <div class="chart-wrapper">
          <div ref="unitContributionChart" class="chart-instance"></div>
        </div>
      </div>

      <div class="chart-card">
        <div class="card-header">
          <h3 class="chart-title">各渠道业绩分析（销量 / 销售额）</h3>
        </div>
        <div class="chart-wrapper">
          <div ref="channelTotalChart" class="chart-instance"></div>
        </div>
      </div>

      <div class="chart-card">
        <div class="card-header">
          <h3 class="chart-title">各平台价值分析（销量 / 销售额）</h3>
        </div>
        <div class="chart-wrapper">
          <div ref="platformChart" class="chart-instance"></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import {
  getShopChannelContribution,
  getShopChannelRoiValue,
  getShopChannelTotalContribution,
  getShopMaxDate,
  getShopTopProductContribution,
  getShopUnitContribution,
  uploadShopValueFiles
} from '@/api/order'

export default {
  name: 'ShopValue',
  data() {
    return {
      topProductData: {
        totalSales: 0,
        top5TotalSales: 0,
        contributionRatio: 0,
        top5Products: []
      },
      uploadingShop: false,
      selectedDate: '',
      maxDate: '',
      activeTab: '7d',
      currentDateRange: { start: '', end: '' },
      pickerOptions: {
        disabledDate: time => {
          if (!this.maxDate) return false
          return time.getTime() > new Date(`${this.maxDate}T23:59:59`).getTime()
        }
      }
    }
  },
  mounted() {
    this.initDashboard()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    getQueryParams() {
      return {
        startDate: this.currentDateRange.start,
        endDate: this.currentDateRange.end
      }
    },
    triggerShopUpload() {
      if (!this.uploadingShop && this.$refs.shopUploadInput) {
        this.$refs.shopUploadInput.click()
      }
    },
    async handleShopUploadChange(event) {
      const files = Array.from(event?.target?.files || [])
      if (!files.length) return
      const invalid = files.find(file => !String(file.name || '').toLowerCase().endsWith('.csv'))
      if (invalid) {
        this.$modal.msgError('仅支持上传 CSV 文件')
        event.target.value = ''
        return
      }
      await this.uploadShopFiles(files)
      event.target.value = ''
    },
    async uploadShopFiles(files) {
      this.uploadingShop = true
      try {
        const formData = new FormData()
        files.forEach(file => formData.append('files', file))
        const data = await uploadShopValueFiles(formData)
        if (data?.success) {
          this.$modal.msgSuccess(data.message || '上传并导入成功')
          await this.initDashboard()
          return
        }
        if (data?.debug) {
          console.error('[shop-upload-debug]', data.debug)
        }
        this.$modal.msgError(data?.message || '上传导入失败')
      } catch (error) {
        if (error?.response?.data?.debug) {
          console.error('[shop-upload-debug]', error.response.data.debug)
        }
        const msg = error?.response?.data?.message || error?.message || '上传导入失败'
        this.$modal.msgError(msg)
      } finally {
        this.uploadingShop = false
      }
    },
    handleDateChange() {
      if (!this.selectedDate) {
        this.selectedDate = this.maxDate
      }
      this.applyDateFilter(this.activeTab)
    },
    pad2(value) {
      return String(value).padStart(2, '0')
    },
    toDate(value) {
      if (value instanceof Date) return new Date(value.getTime())
      if (!value) return new Date()
      return new Date(`${value}T00:00:00`)
    },
    formatYmd(value) {
      const date = this.toDate(value)
      return `${date.getFullYear()}-${this.pad2(date.getMonth() + 1)}-${this.pad2(date.getDate())}`
    },
    addDays(value, days) {
      const date = this.toDate(value)
      date.setDate(date.getDate() + days)
      return date
    },
    addMonths(value, months) {
      const date = this.toDate(value)
      date.setMonth(date.getMonth() + months)
      return date
    },
    startOfMonth(value) {
      const date = this.toDate(value)
      return new Date(date.getFullYear(), date.getMonth(), 1)
    },
    endOfMonth(value) {
      const date = this.toDate(value)
      return new Date(date.getFullYear(), date.getMonth() + 1, 0)
    },
    buildRange(type = this.activeTab) {
      const baseDate = this.toDate(this.selectedDate || this.maxDate || new Date())
      if (type === 'day') {
        const day = this.formatYmd(baseDate)
        return { start: day, end: day }
      }
      if (type === '7d') {
        return {
          start: this.formatYmd(this.addDays(baseDate, -6)),
          end: this.formatYmd(baseDate)
        }
      }
      if (type === 'tm') {
        return {
          start: this.formatYmd(this.startOfMonth(baseDate)),
          end: this.formatYmd(this.endOfMonth(baseDate))
        }
      }
      if (type === 'lm') {
        const lastMonth = this.addMonths(baseDate, -1)
        return {
          start: this.formatYmd(this.startOfMonth(lastMonth)),
          end: this.formatYmd(this.endOfMonth(lastMonth))
        }
      }
      return {
        start: '2022-01-01',
        end: this.maxDate || this.formatYmd(baseDate)
      }
    },
    async initDashboard() {
      try {
        const maxDate = await getShopMaxDate()
        this.maxDate = maxDate
        this.selectedDate = maxDate
      } catch (error) {
        console.error('获取店铺最大日期失败:', error)
        const today = this.formatYmd(new Date())
        this.maxDate = today
        this.selectedDate = today
      }
      await this.applyDateFilter(this.activeTab)
    },
    async applyDateFilter(type) {
      this.activeTab = type
      this.currentDateRange = this.buildRange(type)
      await this.fetchData()
    },
    formatNumber(num) {
      if (!num) return '0'
      return new Intl.NumberFormat().format(Number(num).toFixed(0))
    },
    handleResize() {
      const refs = this.$refs
      if (refs.unitContributionChart) echarts.getInstanceByDom(refs.unitContributionChart)?.resize()
      if (refs.channelTotalChart) echarts.getInstanceByDom(refs.channelTotalChart)?.resize()
      if (refs.platformChart) echarts.getInstanceByDom(refs.platformChart)?.resize()
      if (refs.donutChartRef) echarts.getInstanceByDom(refs.donutChartRef)?.resize()
    },
    initDonutChart(chartData) {
      const chartEl = this.$refs.donutChartRef
      if (!chartEl) return
      const myChart = echarts.getInstanceByDom(chartEl) || echarts.init(chartEl)
      myChart.setOption({
        tooltip: {
          trigger: 'item',
          formatter: '{a}<br/>{b}: ¥{c} ({d}%)'
        },
        legend: {
          orient: 'horizontal',
          bottom: '0%',
          left: 'center'
        },
        series: [{
          name: '销售额',
          type: 'pie',
          radius: ['60%', '80%'],
          avoidLabelOverlap: false,
          label: {
            show: true,
            position: 'outside',
            formatter: '{b}: {d}%'
          },
          labelLine: {
            show: true,
            length: 15,
            length2: 10
          },
          emphasis: {
            label: {
              show: true,
              fontSize: 14,
              fontWeight: 'bold'
            }
          },
          data: chartData
        }]
      }, true)
    },
    async fetchTopProductData() {
      try {
        const response = await getShopTopProductContribution(this.getQueryParams())
        if (!response?.success) return
        const data = response.data || {}
        this.topProductData.totalSales = data.totalSales || 0
        this.topProductData.top5TotalSales = data.top5TotalSales || 0
        this.topProductData.contributionRatio = data.contributionRatio || 0
        this.topProductData.top5Products = data.top5Products || []

        const chartData = this.topProductData.top5Products.map(item => ({
          name: item.productCode,
          value: item.salesAmount
        }))
        this.initDonutChart(chartData)
      } catch (error) {
        console.error('获取 Top 5 商品贡献失败:', error)
      }
    },
    initDualIndicatorBarChart(chartEl, data, categoryKey, seriesConfig) {
      if (!chartEl) return
      const spacePerBar = 120
      chartEl.style.width = `${Math.max(800, spacePerBar * data.length)}px`

      const myChart = echarts.getInstanceByDom(chartEl) || echarts.init(chartEl)
      const categories = data.map(item => item[categoryKey])
      const series = seriesConfig.map(({ key, name, color }) => ({
        name,
        type: 'bar',
        data: data.map(item => item[key]),
        barMaxWidth: '40px',
        itemStyle: { color, borderRadius: [4, 4, 0, 0] },
        yAxisIndex: seriesConfig.findIndex(config => config.key === key)
      }))

      myChart.setOption({
        tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
        legend: { data: seriesConfig.map(item => item.name), top: 0 },
        grid: { left: '80px', right: '80px', top: '40px', bottom: '60px' },
        xAxis: {
          type: 'category',
          data: categories,
          axisLabel: { interval: 0, rotate: 45, color: '#666', margin: 20 },
          axisTick: { alignWithLabel: true }
        },
        yAxis: seriesConfig.map(({ name, formatter }, index) => ({
          type: 'value',
          name,
          nameTextStyle: { color: '#666' },
          axisLabel: {
            color: '#666',
            formatter: formatter || (value => {
              if (value >= 1000000) return `${value / 1000000}M`
              if (value >= 1000) return `${value / 1000}K`
              return value
            })
          },
          position: index === 0 ? 'left' : 'right',
          offset: index === 1 ? 40 : 0
        })),
        series
      }, true)
    },
    initPlatformValueChart(chartEl, data) {
      if (!chartEl) return
      const spacePerBar = 140
      chartEl.style.width = `${Math.max(800, spacePerBar * data.length)}px`

      const myChart = echarts.getInstanceByDom(chartEl) || echarts.init(chartEl)
      const categories = data.map(item => item.name)

      myChart.setOption({
        tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
        legend: { data: ['销量', '销售额'], top: 0 },
        grid: { left: '80px', right: '80px', top: '40px', bottom: '60px' },
        xAxis: {
          type: 'category',
          data: categories,
          axisLabel: { interval: 0, rotate: 45, color: '#666', margin: 20 },
          axisTick: { alignWithLabel: true }
        },
        yAxis: [
          {
            type: 'value',
            name: '销量',
            nameTextStyle: { color: '#666' },
            axisLabel: {
              color: '#5470c6',
              formatter: value => {
                if (value >= 1000000) return `${value / 1000000}M`
                if (value >= 1000) return `${value / 1000}K`
                return value
              }
            }
          },
          {
            type: 'value',
            name: '销售额(元)',
            nameTextStyle: { color: '#e9c46a' },
            axisLabel: {
              color: '#e9c46a',
              formatter: value => `¥${Number(value).toFixed(2)}`
            },
            position: 'right',
            offset: 40
          }
        ],
        series: [
          {
            name: '销量',
            type: 'bar',
            data: data.map(item => item.totalVolume),
            barMaxWidth: '40px',
            itemStyle: { color: '#5470c6', borderRadius: [4, 4, 0, 0] },
            yAxisIndex: 0
          },
          {
            name: '销售额',
            type: 'bar',
            data: data.map(item => item.avgOrderValue),
            barMaxWidth: '40px',
            itemStyle: { color: '#e9c46a', borderRadius: [4, 4, 0, 0] },
            yAxisIndex: 1
          }
        ]
      }, true)
    },
    async fetchData() {
      try {
        const params = this.getQueryParams()
        const [unitRes, channelTotalRes, channelContributionRes, channelRoiValueRes] = await Promise.all([
          getShopUnitContribution(params),
          getShopChannelTotalContribution(params),
          getShopChannelContribution(params),
          getShopChannelRoiValue(params)
        ])

        if (unitRes?.success && unitRes.data) {
          this.initDualIndicatorBarChart(this.$refs.unitContributionChart, unitRes.data, 'name', [
            { key: 'totalVolume', name: '销量', color: '#5470c6' },
            {
              key: 'totalAmount',
              name: '销售额(元)',
              color: '#91cc75',
              formatter: value => `¥${value >= 10000 ? `${value / 10000}w` : value}`
            }
          ])
        }

        if (channelTotalRes?.success && channelTotalRes.data) {
          this.initDualIndicatorBarChart(this.$refs.channelTotalChart, channelTotalRes.data, 'name', [
            { key: 'totalVolume', name: '销量', color: '#5470c6' },
            {
              key: 'totalAmount',
              name: '销售额(元)',
              color: '#e9c46a',
              formatter: value => `¥${value >= 10000 ? `${value / 10000}w` : value}`
            }
          ])
        }

        if (channelContributionRes?.success && channelRoiValueRes?.success && channelContributionRes.data && channelRoiValueRes.data) {
          const platformSales = Object.entries(channelContributionRes.data).map(([name, value]) => ({
            name,
            totalVolume: Number(value)
          }))
          const platformAvgOrder = Object.entries(channelRoiValueRes.data).map(([name, value]) => ({
            name,
            avgOrderValue: Number(value)
          }))
          const mergedData = platformSales
            .map(item => ({
              ...item,
              avgOrderValue: platformAvgOrder.find(avg => avg.name === item.name)?.avgOrderValue || 0
            }))
            .sort((a, b) => b.totalVolume - a.totalVolume)

          this.initPlatformValueChart(this.$refs.platformChart, mergedData)
        }

        await this.fetchTopProductData()
      } catch (error) {
        console.error('获取店铺价值数据失败:', error)
      }
    }
  }
}
</script>

<style scoped>
.shop-value-analysis-page {
  padding: 24px;
  background-color: #f4f7f9;
  font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
}

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

.main-title {
  font-size: 24px;
  font-weight: 600;
  color: #1d2129;
}

.subtitle {
  font-size: 14px;
  color: #86909c;
  margin-top: 4px;
}

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

.control-label {
  font-size: 14px;
  color: #666;
}

.date-picker {
  width: 150px;
}

.tab-group {
  display: flex;
  gap: 8px;
}

.time-tab {
  padding: 6px 14px;
  border: 1px solid #ddd;
  background: #fff;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.time-tab.active {
  background-color: #188df0;
  color: #fff;
  border-color: #188df0;
}

.upload-row {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 20px;
}

.btn-upload {
  background-color: #2a7f62;
  color: #fff;
  border: none;
  padding: 12px 28px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 16px;
  font-weight: 600;
}

.btn-upload:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}

.charts-container {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.chart-card {
  background: #fff;
  padding: 24px;
  border-radius: 4px;
  border: 1px solid #e5e6eb;
  display: grid;
  grid-template-rows: auto 1fr;
  overflow: hidden;
}

.inner-chart-card {
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}

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

.chart-title {
  font-size: 16px;
  font-weight: 600;
  color: #1d2129;
}

.chart-wrapper {
  overflow-x: auto;
  overflow-y: hidden;
  min-width: 0;
}

.chart-instance {
  height: 400px;
}

.chart-wrapper::-webkit-scrollbar {
  height: 8px;
}

.chart-wrapper::-webkit-scrollbar-track {
  background: #f1f1f1;
}

.chart-wrapper::-webkit-scrollbar-thumb {
  background: #c9cdd4;
  border-radius: 4px;
}

.top-product-contribution-container {
  display: flex;
  flex-direction: column;
  gap: 20px;
  width: 100%;
}

.kpi-card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.kpi-card {
  background-color: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}

.kpi-title {
  font-size: 14px;
  color: #666;
  margin-bottom: 10px;
}

.kpi-value {
  font-size: 28px;
  font-weight: bold;
  color: #333;
}
</style>
