<template>
  <div class="product-analysis-view order-dashboard-page">
    <header class="page-header">
      <h1 class="page-title">商品关联透视</h1>
      <p class="page-subtitle">探索商品之间的共同购买关系，发现潜在高价值组合。</p>
    </header>

    <OrderDateRangeFilter
      :max-date="maxDate"
      default-period="day"
      storage-key="dtm-order-date-filter"
      @change="handleFilterChange"
    />

    <div class="table-container">
      <OrderLoadingPanel
        v-if="loading"
        title="正在加载商品关联数据"
        detail="正在读取共同购买关系与热门组合"
      />
      <div class="table-header">
        <h2 class="table-title">热门商品组合</h2>
        <div class="search-box">
          <el-input
            v-model.trim="skuKeyword"
            clearable
            placeholder="输入 SKU 搜索"
            @keyup.enter.native="applySkuSearch"
            @clear="applySkuSearch"
          >
            <el-button slot="append" icon="el-icon-search" @click="applySkuSearch" />
          </el-input>
        </div>
      </div>
      <table>
        <thead>
          <tr>
            <th>商品 A (SKU)</th>
            <th>商品 B (SKU)</th>
            <th>共同购买次数</th>
          </tr>
        </thead>
        <tbody>
          <tr v-if="paginatedData.length > 0" v-for="(item, index) in paginatedData" :key="index" class="data-row">
            <td class="sku-cell" :title="`商品A: ${item.productA}`">{{ item.productAId }}</td>
            <td class="sku-cell" :title="`商品B: ${item.productB}`">{{ item.productBId }}</td>
            <td class="count-cell">
              <div class="count-wrapper">{{ item.coPurchaseCount }}</div>
            </td>
          </tr>
          <tr v-else>
            <td colspan="3">没有找到符合条件的商品组合数据。</td>
          </tr>
        </tbody>
      </table>

      <div class="pagination">
        <button :disabled="currentPage === 1" @click="prevPage" class="page-button">上一页</button>
        <span class="page-info">第 {{ currentPage }} 页，共 {{ totalPages }} 页</span>
        <button :disabled="currentPage === totalPages" @click="nextPage" class="page-button">下一页</button>
      </div>
    </div>

    <div class="chart-container">
      <h2 class="chart-title">共购规则网络图</h2>
      <OrderLoadingPanel
        v-if="loading"
        title="正在生成共购网络图"
        detail="正在计算商品节点与共同购买关系"
      />
      <div ref="networkChart" style="width: 100%; height: 600px;"></div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import OrderLoadingPanel from '../components/OrderLoadingPanel.vue'
import OrderDateRangeFilter from '../components/OrderDateRangeFilter.vue'
import { getOrderCoPurchase, getOrderMaxDate } from '@/api/order'

export default {
  name: 'OrderRelated',
  components: {
    OrderLoadingPanel,
    OrderDateRangeFilter
  },
  data() {
    return {
      coPurchaseData: [],
      loading: true,
      currentPage: 1,
      itemsPerPage: 10,
      skuKeyword: '',
      maxDate: '',
      currentQuery: {},
      chartInstance: null
    }
  },
  computed: {
    paginatedData() {
      const start = (this.currentPage - 1) * this.itemsPerPage
      return this.coPurchaseData.slice(start, start + this.itemsPerPage)
    },
    totalPages() {
      return Math.max(1, Math.ceil(this.coPurchaseData.length / this.itemsPerPage))
    }
  },
  mounted() {
    this.initFilter()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize)
    this.chartInstance?.dispose()
  },
  methods: {
    prevPage() {
      if (this.currentPage > 1) this.currentPage -= 1
    },
    nextPage() {
      if (this.currentPage < this.totalPages) this.currentPage += 1
    },
    applySkuSearch() {
      this.currentPage = 1
      this.fetchData()
    },
    async initFilter() {
      try {
        this.maxDate = await getOrderMaxDate()
      } catch (error) {
        const today = new Date()
        this.maxDate = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`
      }
    },
    handleFilterChange(params) {
      this.currentQuery = params || {}
      this.currentPage = 1
      this.fetchData()
    },
    async fetchData() {
      this.loading = true
      try {
        const response = await getOrderCoPurchase({
          startDate: this.currentQuery.startDate,
          endDate: this.currentQuery.endDate,
          skuKeyword: this.skuKeyword || undefined
        })
        this.coPurchaseData = response || []
        this.renderNetworkChart(this.coPurchaseData)
      } catch (error) {
        console.error('获取共购数据失败:', error)
        this.coPurchaseData = []
        this.renderNetworkChart([])
      } finally {
        this.loading = false
      }
    },
    handleResize() {
      this.chartInstance?.resize()
    },
    renderNetworkChart(data) {
      const chartEl = this.$refs.networkChart
      if (!chartEl) return
      if (this.chartInstance) {
        this.chartInstance.dispose()
      }
      this.chartInstance = echarts.init(chartEl)

      const nodeCount = {}
      const linkWeights = {}
      data.forEach(item => {
        nodeCount[item.productAId] = (nodeCount[item.productAId] || 0) + 1
        nodeCount[item.productBId] = (nodeCount[item.productBId] || 0) + 1
        const linkKey = `${item.productAId}-${item.productBId}`
        linkWeights[linkKey] = (linkWeights[linkKey] || 0) + item.coPurchaseCount
      })

      const categories = [
        { name: '群组1', itemStyle: { color: '#FF6B6B' } },
        { name: '群组2', itemStyle: { color: '#4ECDC4' } },
        { name: '群组3', itemStyle: { color: '#45B7D1' } },
        { name: '群组4', itemStyle: { color: '#96CEB4' } },
        { name: '群组5', itemStyle: { color: '#FFEAA7' } },
        { name: '群组6', itemStyle: { color: '#DDA0DD' } }
      ]

      const nodes = []
      const links = []
      const nodeSet = new Set()
      const nodeCategories = {}
      let categoryIndex = 0

      data.forEach(item => {
        if (!nodeSet.has(item.productAId)) {
          nodeSet.add(item.productAId)
          const count = nodeCount[item.productAId]
          nodeCategories[item.productAId] = nodeCategories[item.productAId] ?? categoryIndex++ % categories.length
          nodes.push({
            id: item.productAId,
            name: item.productAId,
            symbolSize: Math.min(15 + count * 5, 50),
            category: nodeCategories[item.productAId],
            value: count
          })
        }
        if (!nodeSet.has(item.productBId)) {
          nodeSet.add(item.productBId)
          const count = nodeCount[item.productBId]
          nodeCategories[item.productBId] = nodeCategories[item.productBId] ?? categoryIndex++ % categories.length
          nodes.push({
            id: item.productBId,
            name: item.productBId,
            symbolSize: Math.min(15 + count * 5, 50),
            category: nodeCategories[item.productBId],
            value: count
          })
        }
        links.push({
          source: item.productAId,
          target: item.productBId,
          value: linkWeights[`${item.productAId}-${item.productBId}`],
          lineStyle: { width: 1 }
        })
      })

      this.chartInstance.setOption({
        tooltip: {
          formatter: params => {
            if (params.dataType === 'node') {
              return `${params.name}<br/>出现次数: ${params.data.value}`
            }
            if (params.dataType === 'edge') {
              return `${params.data.source} -> ${params.data.target}<br/>共购次数: ${params.data.value}`
            }
            return ''
          }
        },
        legend: [{
          data: categories.map(item => item.name),
          bottom: 0,
          left: 'center',
          itemGap: 20
        }],
        series: [{
          type: 'graph',
          layout: 'force',
          data: nodes,
          links,
          categories,
          roam: true,
          label: {
            show: true,
            position: 'right',
            formatter: '{b}',
            fontSize: 12
          },
          force: {
            repulsion: 300,
            edgeLength: [150, 250],
            gravity: 0.2,
            layoutAnimation: true
          },
          center: ['50%', '40%'],
          left: 0,
          right: 0,
          itemStyle: {
            borderColor: '#fff',
            borderWidth: 1,
            shadowBlur: 10,
            shadowColor: 'rgba(0, 0, 0, 0.3)'
          },
          lineStyle: {
            opacity: 0.9,
            curveness: 0
          },
          emphasis: {
            focus: 'adjacency',
            lineStyle: {
              width: 10
            }
          }
        }]
      })
    }
  }
}
</script>

<style scoped>
.product-analysis-view {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.page-header,
.table-container,
.chart-container {
  position: relative;
  background-color: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.page-title {
  font-size: 20px;
  font-weight: 600;
  margin: 0;
  color: #333;
}

.page-subtitle {
  font-size: 14px;
  color: #666;
  margin-top: 8px;
}

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

.table-title,
.chart-title {
  font-size: 18px;
  font-weight: 600;
  color: #333;
}

.search-box {
  width: 280px;
}

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

th,
td {
  padding: 12px 15px;
  text-align: left;
  border-bottom: 1px solid #f0f0f0;
}

thead th {
  background-color: #f8f9fa;
  font-size: 14px;
  font-weight: 600;
  color: #333;
}

.data-row:hover {
  background-color: #f8f9fa;
}

.sku-cell {
  font-family: 'Courier New', monospace;
  font-size: 14px;
}

.count-cell {
  text-align: left;
  font-size: 14px;
}

.count-wrapper {
  font-weight: bold;
  color: #3366cc;
  text-align: center;
  display: inline-block;
  min-width: 90px;
}

.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 20px;
  gap: 15px;
}

.page-button {
  padding: 8px 16px;
  background-color: #f0f4f8;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s;
}

.page-button:hover:not(:disabled) {
  background-color: #e1e8f0;
}

.page-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.page-info {
  font-size: 14px;
  color: #666;
  font-weight: 500;
}
</style>
