<template>
  <div class="inventory-overview">
    <el-card class="filter-card">
      <div class="filter-bar">
        <span class="filter-label">统计日期</span>
        <el-date-picker
          v-model="dateRange"
          type="daterange"
          size="small"
          value-format="yyyy-MM-dd"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          clearable
        />
        <el-button type="primary" size="small" @click="refreshData" :disabled="uploadTaskPolling">
          <i class="el-icon-search"></i> 查询
        </el-button>
        <el-button size="small" @click="resetDateRange" :disabled="uploadTaskPolling">
          <i class="el-icon-refresh-left"></i> 重置
        </el-button>
      </div>
    </el-card>

    <el-row :gutter="20" class="metrics-row">
      <el-col :span="6">
        <el-card class="metric-card">
          <div class="metric-content">
            <div class="metric-icon" style="background-color: #409eff;">
              <i class="el-icon-box"></i>
            </div>
            <div class="metric-info">
              <div class="metric-label">总体库存量（成品）</div>
              <div class="metric-value">{{ overviewData.totalInventory }}</div>
              <div class="metric-unit">件</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="metric-card">
          <div class="metric-content">
            <div class="metric-icon" style="background-color: #67c23a;">
              <i class="el-icon-money"></i>
            </div>
            <div class="metric-info">
              <div class="metric-label">库存价值（成品）</div>
              <div class="metric-value">{{ overviewData.totalValue }}</div>
              <div class="metric-unit">万元</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="metric-card">
          <div class="metric-content">
            <div class="metric-icon" style="background-color: #e6a23c;">
              <i class="el-icon-refresh"></i>
            </div>
            <div class="metric-info">
              <div class="metric-label">库存周转率（成品）</div>
              <div class="metric-value">{{ overviewData.turnoverRate }}</div>
              <div class="metric-unit">次</div>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="metric-card">
          <div class="metric-content">
            <div class="metric-icon" style="background-color: #f56c6c;">
              <i class="el-icon-truck"></i>
            </div>
            <div class="metric-info">
              <div class="metric-label">库销比（成品）</div>
              <div class="metric-value">{{ overviewData.stockSalesRatio }}</div>
              <div class="metric-unit">库存/销量</div>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="20" class="waterline-row">
      <el-col :span="6">
        <el-card class="waterline-card danger" @click.native="openRiskDialog">
          <div class="waterline-label">低于补货点</div>
          <div class="waterline-value">{{ overviewData.waterlineBelowReorder }}</div>
          <div class="waterline-sub">需要补货判断</div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="waterline-card warning" @click.native="openRiskDialog">
          <div class="waterline-label">超过最高水位</div>
          <div class="waterline-value">{{ overviewData.waterlineOverMax }}</div>
          <div class="waterline-sub">超储/资金占用</div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="waterline-card info" @click.native="openRiskDialog">
          <div class="waterline-label">呆滞预警</div>
          <div class="waterline-value">{{ overviewData.waterlineSlowMoving }}</div>
          <div class="waterline-sub">低动销库存</div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="waterline-card success">
          <div class="waterline-label">健康水位</div>
          <div class="waterline-value">{{ overviewData.waterlineHealthy }}</div>
          <div class="waterline-sub">处于水位区间</div>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="20" class="upload-row">
      <el-col :span="24">
        <el-card class="upload-card">
          <template slot="header">
            <div class="card-header">
              <span>库存数据上传</span>
              <div class="card-actions">
                <el-button type="primary" size="small" @click="openUploadDialog">
                  <i class="el-icon-upload2"></i> 上传数据
                </el-button>
                <el-button size="small" @click="refreshData" :disabled="uploadTaskPolling">
                  <i class="el-icon-refresh"></i> 刷新
                </el-button>
              </div>
            </div>
          </template>
          <div class="upload-hint">
            支持上传入库、销售、组装、产品资料、半成品映射文件（xlsx/xls）。上传后会先创建后台任务，处理完成后自动刷新本页分析。
          </div>
          <div v-if="uploadTaskStatusText" class="upload-task-status">
            <el-tag :type="uploadTaskStatusType" size="mini">{{ uploadTaskStatusLabel }}</el-tag>
            <span>{{ uploadTaskStatusText }}</span>
          </div>
          <div v-if="lastUploadSummary" class="upload-summary">
            <el-tag type="success" size="mini">最近上传</el-tag>
            <span>{{ lastUploadSummary }}</span>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="20" class="charts-row">
      <el-col :span="24">
        <el-card>
          <template slot="header">
            <span>成品入库/销售/库存对比</span>
          </template>
          <div ref="inventoryComparisonChart" class="chart" />
          <el-empty v-if="!monthlyLoading && monthlyComparison.length === 0" description="暂无数据" />
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="20" class="charts-row">
      <el-col :span="12">
        <el-card>
          <template slot="header">
            <span>库存数量按产品类型分布</span>
          </template>
          <div ref="inventoryValuePieChart" class="chart" v-loading="categoryValueLoading" />
          <el-empty v-if="!categoryValueLoading && categoryValueDistribution.length === 0" description="暂无数据" />
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card>
          <template slot="header">
            <span>周转率 Top10</span>
          </template>
          <div ref="turnoverTopChart" class="chart" v-loading="turnoverTopLoading" />
          <el-empty v-if="!turnoverTopLoading && turnoverTopList.length === 0" description="暂无数据" />
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="20" class="charts-row">
      <el-col :span="24">
        <el-card class="risk-entry-card">
          <template slot="header">
            <div class="card-header">
              <span>风险产品详情</span>
              <div class="card-actions">
                <el-tag v-if="warningTotal > 0" type="danger">{{ warningTotal }} 个风险 SKU</el-tag>
                <el-button type="primary" size="small" @click="openRiskDialog">
                  <i class="el-icon-view"></i> 查看详情
                </el-button>
              </div>
            </div>
          </template>
          <div class="risk-entry-content">
            <span v-if="warningTotal > 0">
              当前存在 {{ warningTotal }} 个水位异常 SKU，包含低于补货点、超过最高水位和呆滞预警。
            </span>
            <span v-else>当前没有检测到水位异常 SKU。</span>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-dialog
      title="上传库存分析数据"
      :visible.sync="uploadDialogVisible"
      width="720px"
      @close="resetUploadForm"
    >
      <el-alert
        type="info"
        show-icon
        :closable="false"
        title="可上传Excel进行分析；若不上传文件则默认从数据库读取。入库/销售为常用必传项，其余可选。"
        class="upload-alert"
      />
      <el-form label-width="110px" class="upload-form">
        <el-form-item label="入库数据">
          <div class="upload-field">
            <el-input v-model="uploadNames.purchase" placeholder="未选择文件" readonly />
            <el-button size="small" @click="triggerFile('purchase')">选择文件</el-button>
            <el-button v-if="uploadFiles.purchase" type="text" size="mini" @click="clearUploadFile('purchase')">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="销售数据">
          <div class="upload-field">
            <el-input v-model="uploadNames.sales" placeholder="未选择文件" readonly />
            <el-button size="small" @click="triggerFile('sales')">选择文件</el-button>
            <el-button v-if="uploadFiles.sales" type="text" size="mini" @click="clearUploadFile('sales')">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="组装数据">
          <div class="upload-field">
            <el-input v-model="uploadNames.assembly" placeholder="未选择文件" readonly />
            <el-button size="small" @click="triggerFile('assembly')">选择文件</el-button>
            <el-button v-if="uploadFiles.assembly" type="text" size="mini" @click="clearUploadFile('assembly')">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="产品资料">
          <div class="upload-field">
            <el-input v-model="uploadNames.product" placeholder="未选择文件" readonly />
            <el-button size="small" @click="triggerFile('product')">选择文件</el-button>
            <el-button v-if="uploadFiles.product" type="text" size="mini" @click="clearUploadFile('product')">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="半成品映射">
          <div class="upload-field">
            <el-input v-model="uploadNames.mapping" placeholder="未选择文件" readonly />
            <el-button size="small" @click="triggerFile('mapping')">选择文件</el-button>
            <el-button v-if="uploadFiles.mapping" type="text" size="mini" @click="clearUploadFile('mapping')">清除</el-button>
          </div>
        </el-form-item>
      </el-form>
      <input ref="purchaseInput" class="hidden-file-input" type="file" accept=".xlsx,.xls" @change="handleFileChange('purchase', $event)">
      <input ref="salesInput" class="hidden-file-input" type="file" accept=".xlsx,.xls" @change="handleFileChange('sales', $event)">
      <input ref="assemblyInput" class="hidden-file-input" type="file" accept=".xlsx,.xls" @change="handleFileChange('assembly', $event)">
      <input ref="productInput" class="hidden-file-input" type="file" accept=".xlsx,.xls" @change="handleFileChange('product', $event)">
      <input ref="mappingInput" class="hidden-file-input" type="file" accept=".xlsx,.xls" @change="handleFileChange('mapping', $event)">
      <span slot="footer" class="dialog-footer">
        <el-button @click="uploadDialogVisible = false" :disabled="uploadLoading">取消</el-button>
        <el-button type="primary" :loading="uploadLoading" @click="submitUpload">上传/读取并处理</el-button>
      </span>
    </el-dialog>

    <el-dialog
      title="风险产品水位详情"
      :visible.sync="riskDialogVisible"
      width="1180px"
      top="6vh"
    >
      <el-table
        :data="warningList"
        stripe
        max-height="560"
        style="width: 100%"
        v-loading="warningLoading"
      >
        <el-table-column prop="sku" label="产品编码" width="170" fixed />
        <el-table-column prop="productName" label="产品名称" min-width="180">
          <template slot-scope="scope">{{ scope.row.productName || '-' }}</template>
        </el-table-column>
        <el-table-column label="风险类型" width="130">
          <template slot-scope="scope">
            <el-tag :type="getWaterlineStatusType(scope.row.waterlineStatus)">
              {{ getWaterlineStatusText(scope.row.waterlineStatus) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="effectiveInventory" label="有效库存" width="100" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.effectiveInventory) }}</template>
        </el-table-column>
        <el-table-column prop="remainingInventory" label="现有库存" width="100" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.remainingInventory) }}</template>
        </el-table-column>
        <el-table-column prop="inTransit" label="在途库存" width="100" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.inTransit) }}</template>
        </el-table-column>
        <el-table-column prop="qualifiedInTransit" label="折算在途" width="100" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.qualifiedInTransit) }}</template>
        </el-table-column>
        <el-table-column prop="supplierDefectRate" label="预测销量" width="100" align="right">
          <template slot-scope="scope">{{ formatPercentPlain(scope.row.qualifiedInTransit) }}</template>
        </el-table-column>
        <el-table-column prop="reorderPoint" label="ROP" width="90" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.reorderPoint) }}</template>
        </el-table-column>
        <el-table-column prop="waterlineMax" label="W_MAX" width="100" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.waterlineMax) }}</template>
        </el-table-column>
        <el-table-column prop="safetyStock" label="SS" width="80" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.safetyStock) }}</template>
        </el-table-column>
        <el-table-column prop="leadTime" label="提前期" width="90" align="right">
          <template slot-scope="scope">{{ scope.row.leadTime }} 天</template>
        </el-table-column>
        <el-table-column prop="dailySales" label="日销" width="80" align="right" />
        <el-table-column prop="salableDays" label="可售天数" width="100" align="right">
          <template slot-scope="scope">{{ formatSalableDays(scope.row.salableDays) }}</template>
        </el-table-column>
        <el-table-column prop="assemblyCapacity" label="可组" width="90" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.assemblyCapacity) }}</template>
        </el-table-column>
        <el-table-column prop="suggestedQty" label="建议量" width="90" align="right">
          <template slot-scope="scope">{{ formatNumber(scope.row.suggestedQty) }}</template>
        </el-table-column>
        <el-table-column prop="riskReason" label="风险原因" min-width="220" />
        <el-table-column prop="suggestedAction" label="建议动作" min-width="220" />
      </el-table>
      <el-empty v-if="!warningLoading && warningList.length === 0" description="暂无风险产品" />
      <el-pagination
        :current-page="warningCurrentPage"
        :page-size="warningPageSize"
        :total="warningTotal"
        :page-sizes="[10, 20, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        class="table-pagination"
        @current-change="handleWarningPageChange"
        @size-change="handleWarningSizeChange"
      />
    </el-dialog>
  </div>
</template>

<script>
import request from '@/utils/request'
import * as echarts from 'echarts'
require('echarts/theme/macarons')

const TASK_POLL_INTERVAL = 2000
const TASK_POLL_LIMIT = 120

export default {
  name: 'StorageOverview',
  data() {
    return {
      overviewData: {
        totalInventory: 0,
        totalValue: 0,
        turnoverRate: 0,
        stockSalesRatio: 0,
        inTransitRatio: 0,
        inTransitQty: 0,
        qualifiedInTransitQty: 0,
        assemblyQty: 0,
        waterlineBelowReorder: 0,
        waterlineOverMax: 0,
        waterlineSlowMoving: 0,
        waterlineHealthy: 0,
        waterlineRiskTotal: 0
      },
      dateRange: [],
      monthlyComparison: [],
      monthlyLoading: false,
      categoryValueDistribution: [],
      categoryValueLoading: false,
      turnoverTopList: [],
      turnoverTopLoading: false,
      warningList: [],
      warningLoading: false,
      warningCurrentPage: 1,
      warningPageSize: 10,
      warningTotal: 0,
      skuTableData: [],
      spuTableData: [],
      loading: false,
      spuLoading: false,
      skuFilters: {
        attribute: '',
        category: '',
        spu: ''
      },
      skuSort: {
        prop: '',
        order: ''
      },
      spuSort: {
        prop: '',
        order: ''
      },
      skuCurrentPage: 1,
      skuPageSize: 10,
      spuCurrentPage: 1,
      spuPageSize: 10,
      chartInstance: null,
      valuePieChart: null,
      turnoverTopChart: null,
      uploadDialogVisible: false,
      uploadLoading: false,
      uploadFiles: {
        purchase: null,
        sales: null,
        assembly: null,
        product: null,
        mapping: null
      },
      uploadNames: {
        purchase: '',
        sales: '',
        assembly: '',
        product: '',
        mapping: ''
      },
      lastUploadSummary: '',
      uploadTaskId: '',
      uploadTaskStatus: '',
      uploadTaskStatusText: '',
      uploadTaskPolling: false,
      riskDialogVisible: false
    }
  },
  computed: {
    uploadTaskStatusType() {
      if (this.uploadTaskStatus === 'success') return 'success'
      if (this.uploadTaskStatus === 'failed') return 'danger'
      if (this.uploadTaskStatus === 'running') return 'warning'
      return 'info'
    },
    uploadTaskStatusLabel() {
      if (this.uploadTaskStatus === 'success') return '处理完成'
      if (this.uploadTaskStatus === 'failed') return '处理失败'
      if (this.uploadTaskStatus === 'running') return '处理中'
      if (this.uploadTaskStatus === 'pending') return '排队中'
      return '任务状态'
    },
    skuAttributeOptions() {
      const values = this.skuTableData
        .map(item => (item.attribute || '').trim())
        .filter(item => item)
      return Array.from(new Set(values)).sort()
    },
    skuCategoryOptions() {
      const values = this.skuTableData
        .map(item => (item.category || '').trim())
        .filter(item => item)
      return Array.from(new Set(values)).sort()
    },
    skuSpuOptions() {
      const values = this.skuTableData
        .map(item => (item.spuName || '').trim())
        .filter(item => item)
      return Array.from(new Set(values)).sort()
    },
    filteredSkuData() {
      return this.skuTableData.filter(row => {
        if (this.skuFilters.attribute && row.attribute !== this.skuFilters.attribute) return false
        if (this.skuFilters.category && row.category !== this.skuFilters.category) return false
        if (this.skuFilters.spu && row.spuName !== this.skuFilters.spu) return false
        return true
      })
    },
    sortedSkuData() {
      const { prop, order } = this.skuSort
      if (!prop || !order) {
        return this.filteredSkuData
      }
      return this.sortTableData(this.filteredSkuData, prop, order)
    },
    pagedSkuData() {
      const start = (this.skuCurrentPage - 1) * this.skuPageSize
      return this.sortedSkuData.slice(start, start + this.skuPageSize)
    },
    skuTotal() {
      return this.filteredSkuData.length
    },
    pagedSpuData() {
      const start = (this.spuCurrentPage - 1) * this.spuPageSize
      return this.sortedSpuData.slice(start, start + this.spuPageSize)
    },
    spuTotal() {
      return this.sortedSpuData.length
    },
    sortedSpuData() {
      const { prop, order } = this.spuSort
      if (!prop || !order) {
        return this.spuTableData
      }
      return this.sortTableData(this.spuTableData, prop, order)
    }
  },
  mounted() {
    this.refreshData()
    this.$nextTick(() => {
      this.initChart()
    })
    window.addEventListener('resize', this.resizeChart)
  },
  watch: {
    'skuFilters.attribute'() {
      this.skuCurrentPage = 1
    },
    'skuFilters.category'() {
      this.skuCurrentPage = 1
    },
    'skuFilters.spu'() {
      this.skuCurrentPage = 1
    }
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resizeChart)
    if (this.chartInstance) {
      this.chartInstance.dispose()
      this.chartInstance = null
    }
    if (this.valuePieChart) {
      this.valuePieChart.dispose()
      this.valuePieChart = null
    }
    if (this.turnoverTopChart) {
      this.turnoverTopChart.dispose()
      this.turnoverTopChart = null
    }
  },
  methods: {
    inventoryRequest(config) {
      return request({ timeout: 120000, ...config })
    },
    getDateParams() {
      if (!Array.isArray(this.dateRange) || this.dateRange.length !== 2) {
        return {}
      }
      return {
        startDate: this.dateRange[0],
        endDate: this.dateRange[1]
      }
    },
    resetDateRange() {
      this.dateRange = []
      this.refreshData()
    },
    normalizeResponse(res) {
      if (!res) return null
      if (res.code === 200) return res.data
      if (res.data) return res.data
      return null
    },
    initChart() {
      if (!this.chartInstance && this.$refs.inventoryComparisonChart) {
        this.chartInstance = echarts.init(this.$refs.inventoryComparisonChart, 'macarons')
      }
      if (!this.valuePieChart && this.$refs.inventoryValuePieChart) {
        this.valuePieChart = echarts.init(this.$refs.inventoryValuePieChart, 'macarons')
      }
      if (!this.turnoverTopChart && this.$refs.turnoverTopChart) {
        this.turnoverTopChart = echarts.init(this.$refs.turnoverTopChart, 'macarons')
      }
      this.updateMonthlyChart()
      this.updateCategoryValueChart()
      this.updateTurnoverTopChart()
    },
    resizeChart() {
      if (this.chartInstance) this.chartInstance.resize()
      if (this.valuePieChart) this.valuePieChart.resize()
      if (this.turnoverTopChart) this.turnoverTopChart.resize()
    },
    updateMonthlyChart() {
      if (!this.chartInstance) return
      const months = []
      const purchase = []
      const sales = []
      const inventory = []

      if (Array.isArray(this.monthlyComparison) && this.monthlyComparison.length) {
        this.monthlyComparison.forEach(item => {
          months.push(item.month)
          purchase.push(item.purchase || 0)
          sales.push(item.sales || 0)
          inventory.push(item.inventory || 0)
        })
      }

      const option = {
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' }
        },
        legend: { data: ['成品入库', '成品销售', '成品库存'] },
        grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
        xAxis: { type: 'category', data: months },
        yAxis: { type: 'value', name: '数量 (件)' },
        series: [
          { name: '成品入库', type: 'bar', data: purchase, itemStyle: { color: '#5470c6' } },
          { name: '成品销售', type: 'bar', data: sales, itemStyle: { color: '#91cc75' } },
          { name: '成品库存', type: 'line', data: inventory, itemStyle: { color: '#fac858' }, lineStyle: { width: 3 }, smooth: true }
        ]
      }
      this.chartInstance.setOption(option, true)
    },
    updateCategoryValueChart() {
      if (!this.valuePieChart) return
      const data = Array.isArray(this.categoryValueDistribution) ? this.categoryValueDistribution : []
      const option = {
        tooltip: {
          trigger: 'item',
          formatter: params => {
            const value = Number(params.value || 0).toLocaleString()
            return `${params.name}<br/>库存数量: ${value} 件<br/>占比: ${params.percent}%`
          }
        },
        legend: {
          type: 'scroll',
          orient: 'vertical',
          right: 0,
          top: 20,
          bottom: 20
        },
        series: [
          {
            name: '库存数量',
            type: 'pie',
            radius: ['42%', '68%'],
            center: ['38%', '50%'],
            avoidLabelOverlap: true,
            label: { formatter: '{b}: {d}%' },
            data
          }
        ]
      }
      this.valuePieChart.setOption(option, true)
    },
    updateTurnoverTopChart() {
      if (!this.turnoverTopChart) return
      const rows = Array.isArray(this.turnoverTopList) ? this.turnoverTopList : []
      const labels = rows.map(item => item.productName || item.spuName || item.sku)
      const values = rows.map(item => item.turnoverRate || 0)
      const option = {
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' },
          formatter: params => {
            const item = params && params.length ? params[0] : null
            if (!item) return ''
            const row = rows[item.dataIndex] || {}
            return `${row.productName || row.spuName || row.sku}<br/>SKU: ${row.sku || '-'}<br/>周转率: ${item.value} 次`
          }
        },
        grid: { left: '3%', right: '5%', bottom: '3%', containLabel: true },
        xAxis: { type: 'value', name: '次' },
        yAxis: {
          type: 'category',
          inverse: true,
          data: labels,
          axisLabel: {
            width: 120,
            overflow: 'truncate'
          }
        },
        series: [
          {
            name: '周转率',
            type: 'bar',
            data: values,
            barMaxWidth: 18,
            itemStyle: { color: '#409eff' },
            label: { show: true, position: 'right' }
          }
        ]
      }
      this.turnoverTopChart.setOption(option, true)
    },
    async fetchOverviewData() {
      try {
        const res = await this.inventoryRequest({ url: '/api/inventory/overview', method: 'get', params: this.getDateParams() })
        const data = this.normalizeResponse(res)
        if (data) this.overviewData = { ...this.overviewData, ...data }
      } catch (error) {
        console.error('获取总览数据失败:', error)
      }
    },
    async fetchMonthlyComparison() {
      this.monthlyLoading = true
      try {
        const res = await this.inventoryRequest({ url: '/api/inventory/monthly-comparison', method: 'get', params: this.getDateParams() })
        const data = this.normalizeResponse(res)
        if (data && Array.isArray(data.months)) {
          this.monthlyComparison = data.months.map((month, idx) => ({
            month,
            purchase: data.purchase ? data.purchase[idx] : 0,
            sales: data.sales ? data.sales[idx] : 0,
            inventory: data.inventory ? data.inventory[idx] : 0
          }))
        } else if (Array.isArray(data)) {
          this.monthlyComparison = data
        } else {
          this.monthlyComparison = []
        }
      } catch (error) {
        console.error('获取月度对比数据失败:', error)
      } finally {
        this.monthlyLoading = false
        this.$nextTick(() => this.updateMonthlyChart())
      }
    },
    async fetchCategoryValueDistribution() {
      this.categoryValueLoading = true
      try {
        const res = await this.inventoryRequest({ url: '/api/inventory/category-value-distribution', method: 'get', params: this.getDateParams() })
        const data = this.normalizeResponse(res)
        this.categoryValueDistribution = Array.isArray(data) ? data : []
      } catch (error) {
        console.error('获取库存金额分类分布失败:', error)
      } finally {
        this.categoryValueLoading = false
        this.$nextTick(() => this.updateCategoryValueChart())
      }
    },
    async fetchTurnoverTop() {
      this.turnoverTopLoading = true
      try {
        const res = await this.inventoryRequest({ url: '/api/inventory/turnover-top10', method: 'get', params: this.getDateParams() })
        const data = this.normalizeResponse(res)
        this.turnoverTopList = Array.isArray(data) ? data : []
      } catch (error) {
        console.error('获取周转率Top10失败:', error)
      } finally {
        this.turnoverTopLoading = false
        this.$nextTick(() => this.updateTurnoverTopChart())
      }
    },
    async fetchWarningList() {
      this.warningLoading = true
      try {
        const res = await this.inventoryRequest({
          url: '/api/inventory/low-salable-days',
          method: 'get',
          params: {
            ...this.getDateParams(),
            page: this.warningCurrentPage,
            pageSize: this.warningPageSize
          }
        })
        const data = this.normalizeResponse(res)
        if (data && Array.isArray(data.list)) {
          this.warningList = data.list
          this.warningTotal = Number(data.total || 0)
        } else {
          this.warningList = Array.isArray(data) ? data : []
          this.warningTotal = this.warningList.length
        }
      } catch (error) {
        console.error('获取预警明细失败:', error)
      } finally {
        this.warningLoading = false
      }
    },
    openRiskDialog() {
      this.riskDialogVisible = true
      this.fetchWarningList()
    },
    async fetchSkuSummary() {
      this.loading = true
      try {
        const res = await this.inventoryRequest({ url: '/api/inventory/sku-summary', method: 'get' })
        const data = this.normalizeResponse(res)
        if (Array.isArray(data)) {
          this.skuTableData = data
          this.skuCurrentPage = 1
        }
      } catch (error) {
        console.error('获取SKU汇总数据失败:', error)
      } finally {
        this.loading = false
      }
    },
    async fetchSpuSummary() {
      this.spuLoading = true
      try {
        const res = await this.inventoryRequest({ url: '/api/inventory/spu-summary', method: 'get' })
        const data = this.normalizeResponse(res)
        if (Array.isArray(data)) {
          this.spuTableData = data
          this.spuCurrentPage = 1
        }
      } catch (error) {
        console.error('获取SPU汇总数据失败:', error)
      } finally {
        this.spuLoading = false
      }
    },
    async refreshData() {
      this.warningCurrentPage = 1
      await this.fetchOverviewData()
      await this.fetchMonthlyComparison()
      await this.fetchCategoryValueDistribution()
      await this.fetchTurnoverTop()
      await this.fetchWarningList()
    },
    openUploadDialog() {
      this.uploadDialogVisible = true
    },
    triggerFile(type) {
      const refKey = `${type}Input`
      const input = this.$refs[refKey]
      if (input && input.click) {
        input.click()
      }
    },
    handleFileChange(type, event) {
      const file = event && event.target ? event.target.files[0] : null
      if (!file) {
        return
      }
      const name = (file.name || '').toLowerCase()
      if (!name.endsWith('.xlsx') && !name.endsWith('.xls')) {
        this.$message.error('仅支持上传 xlsx/xls 文件')
        if (event && event.target) event.target.value = ''
        return
      }
      this.uploadFiles[type] = file
      this.uploadNames[type] = file.name
      if (event && event.target) event.target.value = ''
    },
    clearUploadFile(type) {
      this.uploadFiles[type] = null
      this.uploadNames[type] = ''
    },
    resetUploadForm() {
      this.uploadFiles = {
        purchase: null,
        sales: null,
        assembly: null,
        product: null,
        mapping: null
      }
      this.uploadNames = {
        purchase: '',
        sales: '',
        assembly: '',
        product: '',
        mapping: ''
      }
      this.uploadLoading = false
    },
    hasUploadFiles() {
      return ['purchase', 'sales', 'assembly', 'product', 'mapping'].some(key => this.uploadFiles[key])
    },
    async submitUpload() {
      const useDb = !this.hasUploadFiles()
      if (useDb) {
        this.$message.info('未选择文件，将从数据库读取库存数据')
      }
      const formData = new FormData()
      if (this.uploadFiles.purchase) formData.append('purchaseFile', this.uploadFiles.purchase)
      if (this.uploadFiles.sales) formData.append('salesFile', this.uploadFiles.sales)
      if (this.uploadFiles.assembly) formData.append('assemblyFile', this.uploadFiles.assembly)
      if (this.uploadFiles.product) formData.append('productFile', this.uploadFiles.product)
      if (this.uploadFiles.mapping) formData.append('semiMappingFile', this.uploadFiles.mapping)

      this.uploadLoading = true
      this.uploadTaskStatus = 'pending'
      this.uploadTaskStatusText = '文件上传中，请稍候'
      try {
        const res = await this.inventoryRequest({
          url: '/api/inventory/upload',
          method: 'post',
          data: formData,
          headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false },
          timeout: 300000
        })
        if (!(res && res.code === 200 && res.data && res.data.taskId)) {
          this.$message.error((res && res.msg) || '上传失败')
          this.uploadTaskStatus = 'failed'
          this.uploadTaskStatusText = (res && res.msg) || '上传失败'
          return
        }
        this.uploadTaskId = res.data.taskId
        this.uploadTaskStatus = res.data.status || 'pending'
        this.uploadTaskStatusText = res.data.message || '任务已创建，等待后台处理'
        const fileCount = res.data.count || 0
        this.lastUploadSummary = fileCount > 0
          ? `已接收 ${fileCount} 个文件，任务ID：${this.uploadTaskId}`
          : `未上传文件，已切换为数据库读取，任务ID：${this.uploadTaskId}`
        this.uploadDialogVisible = false
        this.resetUploadForm()
        this.$message.success(useDb ? '已提交，后台将从数据库读取并处理库存数据' : '上传成功，后台正在处理库存数据')
        await this.pollUploadTask(this.uploadTaskId)
      } catch (error) {
        console.error('上传库存数据失败:', error)
        this.uploadTaskStatus = 'failed'
        this.uploadTaskStatusText = '上传失败，请检查文件格式或后端日志'
        this.$message.error('上传失败，请检查文件格式或后端日志')
      } finally {
        this.uploadLoading = false
      }
    },
    async pollUploadTask(taskId) {
      this.uploadTaskPolling = true
      try {
        for (let attempt = 0; attempt < TASK_POLL_LIMIT; attempt++) {
          const res = await this.inventoryRequest({
            url: `/api/inventory/upload-task/${taskId}`,
            method: 'get',
            timeout: 30000
          })
          const data = this.normalizeResponse(res)
          if (!data) {
            throw new Error((res && res.msg) || '任务状态获取失败')
          }
          this.uploadTaskStatus = data.status || 'pending'
          this.uploadTaskStatusText = data.message || '后台处理中'
          if (data.status === 'success') {
            this.lastUploadSummary = `已处理 ${data.count || 0} 个文件`
            this.$message.success('库存数据处理完成，已刷新分析结果')
            await this.refreshData()
            return
          }
          if (data.status === 'failed') {
            throw new Error(data.message || '库存数据处理失败')
          }
          await this.sleep(TASK_POLL_INTERVAL)
        }
        throw new Error('库存数据处理超时，请稍后手动刷新')
      } catch (error) {
        this.uploadTaskStatus = 'failed'
        this.uploadTaskStatusText = error.message || '库存数据处理失败'
        this.$message.error(this.uploadTaskStatusText)
      } finally {
        this.uploadTaskPolling = false
      }
    },
    sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms))
    },
    sortTableData(source, prop, order) {
      const direction = order === 'ascending' ? 1 : -1
      const data = [...source]
      data.sort((a, b) => {
        const aRaw = a[prop]
        const bRaw = b[prop]
        const aNum = typeof aRaw === 'number' ? aRaw : Number(aRaw)
        const bNum = typeof bRaw === 'number' ? bRaw : Number(bRaw)
        const aIsNum = !Number.isNaN(aNum) && aRaw !== '' && aRaw !== null && aRaw !== undefined
        const bIsNum = !Number.isNaN(bNum) && bRaw !== '' && bRaw !== null && bRaw !== undefined
        if (aIsNum && bIsNum) {
          return (aNum - bNum) * direction
        }
        return String(aRaw || '').localeCompare(String(bRaw || ''), 'zh-Hans-CN', { numeric: true }) * direction
      })
      return data
    },
    handleSkuSortChange({ prop, order }) {
      this.skuSort = { prop, order }
      this.skuCurrentPage = 1
    },
    handleSkuPageChange(page) {
      this.skuCurrentPage = page
    },
    handleSkuSizeChange(size) {
      this.skuPageSize = size
      this.skuCurrentPage = 1
    },
    handleSpuPageChange(page) {
      this.spuCurrentPage = page
    },
    handleSpuSizeChange(size) {
      this.spuPageSize = size
      this.spuCurrentPage = 1
    },
    handleSpuSortChange({ prop, order }) {
      this.spuSort = { prop, order }
      this.spuCurrentPage = 1
    },
    handleWarningPageChange(page) {
      this.warningCurrentPage = page
      this.fetchWarningList()
    },
    handleWarningSizeChange(size) {
      this.warningPageSize = size
      this.warningCurrentPage = 1
      this.fetchWarningList()
    },
    resetSkuFilters() {
      this.skuFilters.attribute = ''
      this.skuFilters.category = ''
      this.skuFilters.spu = ''
      this.skuSort = { prop: '', order: '' }
      this.skuCurrentPage = 1
    },
    getTurnoverRateType(rate) {
      if (rate === 0) return 'info'
      if (rate >= 1) return 'success'
      if (rate >= 0.5) return 'warning'
      return 'danger'
    },
    getWaterlineStatusType(status) {
      const map = {
        below_reorder: 'danger',
        over_max: 'warning',
        slow_moving: 'info',
        healthy: 'success'
      }
      return map[status] || 'info'
    },
    getWaterlineStatusText(status) {
      const map = {
        below_reorder: '低于补货点',
        over_max: '超过最高水位',
        slow_moving: '呆滞预警',
        healthy: '健康'
      }
      return map[status] || '未知'
    },
    formatSalableDays(value) {
      const num = Number(value || 0)
      if (num >= 9999) return '无销量'
      return num.toLocaleString()
    },
    formatNumber(value) {
      const num = Number(value || 0)
      return num.toLocaleString()
    },
    formatPercentPlain(value) {
      const num = Number(value || 0)
      return `${num.toFixed(2)}%`
    }
  }
}
</script>

<style scoped>
.inventory-overview {
  width: 100%;
}

.filter-card {
  margin-bottom: 20px;
}

.filter-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.filter-label {
  color: #606266;
  font-size: 14px;
}

.metrics-row {
  margin-bottom: 20px;
}

.waterline-row {
  margin-bottom: 20px;
}

.waterline-card {
  cursor: pointer;
  border-left: 4px solid #dcdfe6;
}

.waterline-card.danger {
  border-left-color: #f56c6c;
}

.waterline-card.warning {
  border-left-color: #e6a23c;
}

.waterline-card.info {
  border-left-color: #409eff;
}

.waterline-card.success {
  cursor: default;
  border-left-color: #67c23a;
}

.waterline-label {
  color: #606266;
  font-size: 14px;
}

.waterline-value {
  margin-top: 8px;
  color: #303133;
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
}

.waterline-sub {
  margin-top: 8px;
  color: #909399;
  font-size: 12px;
}

.metric-card {
  cursor: pointer;
  transition: transform 0.3s;
}

.metric-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.metric-content {
  display: flex;
  align-items: center;
  gap: 15px;
}

.metric-icon {
  width: 60px;
  height: 60px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 28px;
}

.metric-info {
  flex: 1;
}

.metric-label {
  font-size: 14px;
  color: #909399;
  margin-bottom: 8px;
}

.metric-value {
  font-size: 28px;
  font-weight: bold;
  color: #303133;
  line-height: 1;
}

.metric-unit,
.metric-sub {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.charts-row {
  margin-bottom: 20px;
}

.upload-row {
  margin-bottom: 20px;
}

.risk-entry-card .card-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.risk-entry-content {
  color: #606266;
  font-size: 14px;
  line-height: 1.7;
}

.upload-card .card-actions {
  display: flex;
  gap: 8px;
}

.upload-hint {
  font-size: 13px;
  color: #909399;
  line-height: 1.6;
}

.upload-task-status,
.upload-summary {
  margin-top: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: #606266;
}

.upload-form {
  margin-top: 16px;
}

.upload-field {
  display: flex;
  align-items: center;
  gap: 10px;
}

.hidden-file-input {
  display: none;
}

.upload-alert {
  margin-bottom: 12px;
}

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

.sku-filters {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.table-pagination {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
}

.chart {
  height: 300px;
}
</style>
