<template>
  <div class="mod-config">
    <el-card class="overview-card" shadow="never">
      <div slot="header" class="card-title-row">
        <div>
          <div class="page-title">生产追溯与运营看板</div>
          <div class="page-desc">面向批次、任务单、挂具、物料的全链路追溯与关键指标监控</div>
        </div>
        <el-button plain class="search-btn" :loading="reportLoading" @click="loadReport">刷新报表</el-button>
      </div>
      <div class="metric-grid">
        <div class="metric-item">
          <div class="metric-label">任务总数</div>
          <div class="metric-value">{{ metricData.totalJobs }}</div>
        </div>
        <div class="metric-item">
          <div class="metric-label">完工任务</div>
          <div class="metric-value">{{ metricData.completedJobs }}</div>
        </div>
        <div class="metric-item">
          <div class="metric-label">在制任务</div>
          <div class="metric-value">{{ metricData.processingJobs }}</div>
        </div>
        <div class="metric-item">
          <div class="metric-label">任务完工率</div>
          <div class="metric-value">{{ formatRate(report.jobCompletionRate) }}</div>
        </div>
        <div class="metric-item">
          <div class="metric-label">过站通过数</div>
          <div class="metric-value">{{ metricData.stationPassCount }}</div>
        </div>
        <div class="metric-item">
          <div class="metric-label">过站拦截数</div>
          <div class="metric-value">{{ metricData.stationInterceptCount }}</div>
        </div>
        <div class="metric-item">
          <div class="metric-label">过站拦截率</div>
          <div class="metric-value">{{ formatRate(report.interceptRate) }}</div>
        </div>
        <div class="metric-item">
          <div class="metric-label">手工录入数</div>
          <div class="metric-value">{{ metricData.manualRecordCount }}</div>
        </div>
      </div>
      <div class="report-time">报表更新时间：{{ reportRefreshTime || '-' }}</div>
    </el-card>

    <el-card style="margin-top: 12px;">
      <div slot="header" class="card-title-row">
        <span>追溯查询工作台</span>
        <div>
          <el-button plain class="reset-btn" @click="resetTraceQuery">重置条件</el-button>
          <el-button plain class="search-btn" :loading="traceLoading" @click="loadTrace">查询</el-button>
        </div>
      </div>
      <el-form :inline="true" label-position="top" class="query-form">
        <el-form-item label="批次编码">
          <el-input v-model.trim="traceQueryForm.batchCode" clearable placeholder="例如 BATCH-20260428-01" style="width: 220px" @keyup.enter.native="loadTrace" />
        </el-form-item>
        <el-form-item label="任务单号">
          <el-input v-model.trim="traceQueryForm.jobCode" clearable placeholder="例如 JOB-20260428-01" style="width: 220px" @keyup.enter.native="loadTrace" />
        </el-form-item>
        <el-form-item label="挂具编码">
          <el-input v-model.trim="traceQueryForm.rackCode" clearable placeholder="例如 RACK-01" style="width: 180px" @keyup.enter.native="loadTrace" />
        </el-form-item>
        <el-form-item label="物料编码">
          <el-input v-model.trim="traceQueryForm.partNo" clearable placeholder="例如 PART-001" style="width: 180px" @keyup.enter.native="loadTrace" />
        </el-form-item>
      </el-form>

      <el-tabs v-model="traceTab" type="border-card">
        <el-tab-pane label="追溯摘要" name="summary">
          <el-descriptions :column="4" border>
            <el-descriptions-item label="批次">{{ traceSummary.batchCode || '-' }}</el-descriptions-item>
            <el-descriptions-item label="任务单">{{ traceSummary.jobCode || '-' }}</el-descriptions-item>
            <el-descriptions-item label="挂具">{{ traceSummary.rackCode || '-' }}</el-descriptions-item>
            <el-descriptions-item label="物料">{{ traceSummary.partNo || '-' }}</el-descriptions-item>
            <el-descriptions-item label="当前状态">{{ traceSummary.status || '-' }}</el-descriptions-item>
            <el-descriptions-item label="通过工序数">{{ traceSummary.passCount }}</el-descriptions-item>
            <el-descriptions-item label="拦截次数">{{ traceSummary.interceptCount }}</el-descriptions-item>
            <el-descriptions-item label="手工补录次数">{{ traceSummary.manualCount }}</el-descriptions-item>
          </el-descriptions>
        </el-tab-pane>

        <el-tab-pane label="过站记录" name="station">
          <el-table class="data-table" :data="stationRows" border height="260" style="width: 100%">
            <el-table-column type="index" width="50" />
            <el-table-column prop="time" label="时间" min-width="170" />
            <el-table-column prop="stepCode" label="工序编码" width="120" />
            <el-table-column prop="stationId" label="站点/池子" width="140" />
            <el-table-column prop="rackCode" label="挂具" width="120" />
            <el-table-column prop="result" label="结果" width="100" />
            <el-table-column prop="message" label="备注" min-width="180" show-overflow-tooltip />
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="手工录入记录" name="manual">
          <el-table class="data-table" :data="manualRows" border height="260" style="width: 100%">
            <el-table-column type="index" width="50" />
            <el-table-column prop="recordType" label="类型" width="110" />
            <el-table-column prop="docNo" label="单号" min-width="150" />
            <el-table-column prop="qty" label="数量" width="100" />
            <el-table-column prop="operatorName" label="录入人" width="120" />
            <el-table-column prop="reviewerName" label="复核人" width="120" />
            <el-table-column prop="recordTime" label="录入时间" min-width="170" />
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="原始JSON" name="raw">
          <pre class="trace-box">{{ prettyTraceJson }}</pre>
        </el-tab-pane>
      </el-tabs>
    </el-card>
  </div>
</template>

<script>
import { traceQuery, reportOverview } from '@/api/rack/closedLoop'

export default {
  data () {
    return {
      traceQueryForm: { batchCode: '', jobCode: '', rackCode: '', partNo: '' },
      traceLoading: false,
      reportLoading: false,
      traceTab: 'summary',
      reportRefreshTime: '',
      traceResult: {},
      report: {}
    }
  },
  computed: {
    metricData () {
      const totalJobs = Number(this.report.totalJobs) || 0
      const completedJobs = Number(this.report.completedJobs) || 0
      return {
        totalJobs,
        completedJobs,
        processingJobs: Math.max(totalJobs - completedJobs, 0),
        stationPassCount: Number(this.report.stationPassCount) || 0,
        stationInterceptCount: Number(this.report.stationInterceptCount) || 0,
        manualRecordCount: Number(this.report.manualRecordCount) || 0
      }
    },
    traceSummary () {
      return {
        batchCode: this.pickFirstValue(this.traceResult, ['batchCode', 'batchNo', 'inboundBatchCode']),
        jobCode: this.pickFirstValue(this.traceResult, ['jobCode', 'taskCode']),
        rackCode: this.pickFirstValue(this.traceResult, ['rackCode', 'currentRackCode']),
        partNo: this.pickFirstValue(this.traceResult, ['partNo', 'materialCode']),
        status: this.pickFirstValue(this.traceResult, ['status', 'jobStatus', 'traceStatus']),
        passCount: this.safeNumber(this.pickFirstValue(this.traceResult, ['passCount', 'stationPassCount'])),
        interceptCount: this.safeNumber(this.pickFirstValue(this.traceResult, ['interceptCount', 'stationInterceptCount'])),
        manualCount: this.safeNumber(this.pickFirstValue(this.traceResult, ['manualCount', 'manualRecordCount']))
      }
    },
    stationRows () {
      const source = this.pickFirstArray(this.traceResult, [
        'stationRecords',
        'stationPassLogs',
        'passLogs',
        'traceRecords',
        'events'
      ])
      return source.map(item => ({
        time: this.formatDateTime(this.pickFirstValue(item, ['eventTime', 'passTime', 'recordTime', 'createTime', 'time'])),
        stepCode: this.pickFirstValue(item, ['stepCode', 'processCode', 'stepNo']),
        stationId: this.pickFirstValue(item, ['stationId', 'poolCode', 'stationCode']),
        rackCode: this.pickFirstValue(item, ['rackCode']),
        result: this.pickFirstValue(item, ['result', 'eventType', 'status']) || '-',
        message: this.pickFirstValue(item, ['msg', 'message', 'remark']) || '-'
      }))
    },
    manualRows () {
      const source = this.pickFirstArray(this.traceResult, [
        'manualRecords',
        'manualRecordList',
        'manualRows',
        'manualList'
      ])
      return source.map(item => ({
        recordType: item.recordType || '-',
        docNo: item.docNo || '-',
        qty: this.safeNumber(item.qty),
        operatorName: item.operatorName || '-',
        reviewerName: item.reviewerName || '-',
        recordTime: this.formatDateTime(item.recordTime)
      }))
    },
    prettyTraceJson () {
      return JSON.stringify(this.traceResult || {}, null, 2)
    }
  },
  mounted () {
    this.loadReport()
  },
  methods: {
    resetTraceQuery () {
      this.traceQueryForm = { batchCode: '', jobCode: '', rackCode: '', partNo: '' }
      this.traceResult = {}
      this.traceTab = 'summary'
    },
    async loadTrace () {
      const hasCondition = Object.keys(this.traceQueryForm).some(key => String(this.traceQueryForm[key] || '').trim())
      if (!hasCondition) {
        this.$message.warning('请至少输入一个追溯条件')
        return
      }
      this.traceLoading = true
      try {
        const { data } = await traceQuery(this.traceQueryForm)
        this.traceResult = data.result || {}
        if (!Object.keys(this.traceResult).length) {
          this.$message.warning('未查询到追溯结果')
        }
      } finally {
        this.traceLoading = false
      }
    },
    async loadReport () {
      this.reportLoading = true
      try {
        const { data } = await reportOverview()
        this.report = data.result || {}
        this.reportRefreshTime = this.formatDateTime(Date.now())
      } finally {
        this.reportLoading = false
      }
    },
    formatRate (value) {
      if (value === null || value === undefined) return '0%'
      return `${(Number(value) * 100).toFixed(2)}%`
    },
    safeNumber (val) {
      return Number(val) || 0
    },
    pickFirstValue (obj, fields) {
      if (!obj || typeof obj !== 'object') {
        return ''
      }
      for (let i = 0; i < fields.length; i++) {
        const key = fields[i]
        if (obj[key] !== undefined && obj[key] !== null && obj[key] !== '') {
          return obj[key]
        }
      }
      return ''
    },
    pickFirstArray (obj, fields) {
      for (let i = 0; i < fields.length; i++) {
        const value = this.pickFirstValue(obj, [fields[i]])
        if (Array.isArray(value)) {
          return value
        }
      }
      return []
    },
    formatDateTime (v) {
      if (!v) return '-'
      let date = null
      if (typeof v === 'number') {
        date = new Date(v)
      } else if (typeof v === 'string') {
        const trimmed = v.trim()
        if (/^\d+$/.test(trimmed)) {
          date = new Date(Number(trimmed))
        } else {
          date = new Date(trimmed)
        }
      } else if (v instanceof Date) {
        date = v
      } else {
        date = new Date(v)
      }
      if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
        return String(v).replace('T', ' ')
      }
      const y = date.getFullYear()
      const m = String(date.getMonth() + 1).padStart(2, '0')
      const d = String(date.getDate()).padStart(2, '0')
      const hh = String(date.getHours()).padStart(2, '0')
      const mm = String(date.getMinutes()).padStart(2, '0')
      const ss = String(date.getSeconds()).padStart(2, '0')
      return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
    }
  }
}
</script>

<style scoped>
.overview-card {
  margin-bottom: 12px;
}

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

.page-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.page-desc {
  margin-top: 4px;
  font-size: 12px;
  color: #909399;
}

.metric-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(130px, 1fr));
  gap: 10px;
}

.metric-item {
  border: 1px solid #ebeef5;
  border-radius: 6px;
  background: #fff;
  padding: 10px;
}

.metric-label {
  font-size: 12px;
  color: #909399;
}

.metric-value {
  margin-top: 6px;
  font-size: 20px;
  font-weight: 600;
  color: #303133;
}

.report-time {
  margin-top: 10px;
  color: #909399;
  font-size: 12px;
}

.data-table {
  background-color: #fff;
  border-radius: 4px;
}

.data-table >>> .el-table__header-wrapper th,
.data-table >>> .el-table__fixed-header-wrapper th {
  background-color: #f5f7fa !important;
  color: #333;
  font-weight: 600;
  border-color: #ebeef5;
  padding: 8px 0;
}

.data-table >>> .el-table__header-wrapper .cell,
.data-table >>> .el-table__fixed-header-wrapper .cell,
.data-table >>> .el-table__body-wrapper .cell,
.data-table >>> .el-table__fixed-body-wrapper .cell {
  padding: 0 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px !important;
}

.query-form {
  background-color: #fff;
  padding: 5px 0 0;
  border-radius: 4px;
  margin-bottom: 12px;
}

.query-form >>> .el-form-item__label {
  color: #333;
  font-size: 13px;
  padding-bottom: 5px;
}

.query-form >>> .el-input__inner {
  height: 32px;
  line-height: 32px;
  border-radius: 4px;
  font-size: 13px;
}

.query-form >>> .el-button {
  height: 32px;
  padding: 0 15px;
  font-size: 13px;
  border-radius: 4px;
}

.search-btn {
  background-color: #ecf5ff;
  border-color: #b3d8ff;
  color: #409eff;
}

.search-btn:hover {
  background-color: #409eff;
  border-color: #409eff;
  color: #fff;
}

.reset-btn {
  background-color: #f5f7fa;
  border-color: #d3d4d6;
  color: #606266;
}

.reset-btn:hover {
  background-color: #909399;
  border-color: #909399;
  color: #fff;
}

.add-btn {
  background-color: #f0f9eb;
  border-color: #c2e7b0;
  color: #67c23a;
}

.add-btn:hover {
  background-color: #67c23a;
  border-color: #67c23a;
  color: #fff;
}

.trace-box {
  margin: 0;
  max-height: 300px;
  overflow: auto;
  background: #f7f7f7;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 10px;
}
</style>
