<template>
  <div class="produce-kanban">
    <div class="kanban-bg-grid" aria-hidden="true"></div>
    <div class="kanban-scanline" aria-hidden="true"></div>

    <header class="kanban-header">
      <div class="kanban-header__brand">
        <div class="brand-logo">
          <span class="brand-logo__cn">伊特</span>
          <span class="brand-logo__en">Evo-Tech</span>
        </div>
      </div>
      <div class="kanban-header__center">
        <h1 class="kanban-title">河北伊特机械设备制造有限公司 生产管理看板</h1>
        <p class="kanban-subtitle">工作中心：{{ chejian || '—' }}</p>
      </div>
      <div class="kanban-header__clock">
        <span class="clock-date">{{ clockDate }}</span>
        <span class="clock-time">{{ clockTime }}</span>
      </div>
    </header>

    <div class="kanban-table-wrap">
      <div class="kanban-table-head">
        <table>
          <colgroup>
            <col style="width: 4%" />
            <col style="width: 11%" />
            <col style="width: 14%" />
            <col style="width: 12%" />
            <col style="width: 5%" />
            <col style="width: 5%" />
            <col style="width: 5%" />
            <col style="width: 6%" />
            <col style="width: 10%" />
            <col style="width: 8%" />
            <col style="width: 8%" />
            <col style="width: 6%" />
          </colgroup>
          <thead>
            <tr>
              <th>序号</th>
              <th>生产令号</th>
              <th>产品编码</th>
              <th>产品名称</th>
              <th>数量</th>
              <th>转入</th>
              <th>转出</th>
              <th>工序号</th>
              <th>作业</th>
              <th>计划开始时间</th>
              <th>计划结束时间</th>
              <th>延期</th>
            </tr>
          </thead>
        </table>
      </div>

      <div
        class="kanban-page-viewport"
        ref="viewport"
        @mouseenter="pagePaused = true"
        @mouseleave="pagePaused = false"
      >
        <div v-if="loading" class="kanban-loading">
          <i class="el-icon-loading"></i>
          <span>数据加载中…</span>
        </div>
        <div v-else-if="!displayRows.length" class="kanban-empty">暂无生产数据</div>
        <transition v-else name="kanban-page" mode="out-in">
          <table :key="currentPage" class="kanban-data-table">
            <colgroup>
              <col style="width: 4%" />
              <col style="width: 11%" />
              <col style="width: 14%" />
              <col style="width: 12%" />
              <col style="width: 5%" />
              <col style="width: 5%" />
              <col style="width: 5%" />
              <col style="width: 6%" />
              <col style="width: 10%" />
              <col style="width: 8%" />
              <col style="width: 8%" />
              <col style="width: 6%" />
            </colgroup>
            <tbody>
              <tr
                v-for="row in pagedRows"
                :key="row._key"
                :class="{ 'row-delayed': row._delayed }"
              >
                <td>{{ row._index }}</td>
                <td>{{ row.moOrderNo || '—' }}</td>
                <td :title="row.materialNumber">{{ row.materialNumber || '—' }}</td>
                <td :title="row.materialName">{{ row.materialName || '—' }}</td>
                <td>{{ formatQty(row.operQty) }}</td>
                <td>{{ formatQty(row.transInQty) }}</td>
                <td>{{ formatQty(row.transOutQty) }}</td>
                <td>{{ row.operNumber != null && row.operNumber !== '' ? row.operNumber : '—' }}</td>
                <td :title="row.processName">{{ row.processName || '—' }}</td>
                <td>{{ formatPlanDate(row.operPlanStartTime) }}</td>
                <td>{{ formatPlanDate(row.operPlanFinishTime) }}</td>
                <td>{{ row._delayText }}</td>
              </tr>
              <tr v-for="n in emptyRowCount" :key="`empty-${n}`" class="row-placeholder">
                <td v-for="c in 12" :key="c">&nbsp;</td>
              </tr>
            </tbody>
          </table>
        </transition>
      </div>

      <footer class="kanban-footer">
        <span>共 {{ displayRows.length }} 条</span>
        <span class="kanban-footer__sep">|</span>
        <span>第 {{ currentPage }} / {{ totalPages }} 页</span>
        <span class="kanban-footer__sep">|</span>
        <span>每页 {{ pageSize }} 条</span>
        <span class="kanban-footer__sep">|</span>
        <span>{{ refreshHint }}</span>
        <div v-if="totalPages > 1 && totalPages <= 20" class="kanban-pager-dots">
          <span
            v-for="p in totalPages"
            :key="p"
            class="pager-dot"
            :class="{ 'is-active': p === currentPage }"
          ></span>
        </div>
      </footer>
    </div>
  </div>
</template>

<script>
import { getProduceDataKanban } from '@/api/system/workCenterData'
import dayjs from 'dayjs'

const DEFAULT_CHEJIAN = '机一工段'
const REFRESH_MS = 10 * 60 * 1000
const PAGE_FLIP_SEC = 30
const DEFAULT_PAGE_SIZE = 18
const ROW_HEIGHT = 42

export default {
  name: 'ProduceKanban',
  data() {
    return {
      chejian: DEFAULT_CHEJIAN,
      loading: false,
      rawList: [],
      clockDate: '',
      clockTime: '',
      pagePaused: false,
      pageSize: DEFAULT_PAGE_SIZE,
      currentPage: 1,
      pageFlipCountdown: PAGE_FLIP_SEC,
      refreshHint: '',
      clockTimer: null,
      refreshTimer: null,
      pageFlipTimer: null,
      countdownTimer: null,
    }
  },
  computed: {
    displayRows() {
      return this.rawList.map((item, index) => this.normalizeRow(item, index))
    },
    totalPages() {
      if (!this.displayRows.length) return 1
      return Math.ceil(this.displayRows.length / this.pageSize)
    },
    pagedRows() {
      const start = (this.currentPage - 1) * this.pageSize
      return this.displayRows.slice(start, start + this.pageSize)
    },
    emptyRowCount() {
      return Math.max(0, this.pageSize - this.pagedRows.length)
    },
  },
  watch: {
    '$route.query.chejian': {
      immediate: true,
      handler(val) {
        this.chejian = val || DEFAULT_CHEJIAN
        this.fetchData()
      },
    },
    totalPages(val) {
      if (this.currentPage > val) {
        this.currentPage = 1
      }
    },
  },
  mounted() {
    document.title = '生产管理看板'
    this.tickClock()
    this.clockTimer = setInterval(this.tickClock, 1000)
    this.refreshTimer = setInterval(this.fetchData, REFRESH_MS)
    window.addEventListener('resize', this.handleResize)
    this.$nextTick(() => {
      this.calcPageSize()
      this.startPageFlip()
    })
  },
  beforeDestroy() {
    clearInterval(this.clockTimer)
    clearInterval(this.refreshTimer)
    this.stopPageFlip()
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    tickClock() {
      const now = dayjs()
      this.clockDate = now.format('YYYY-MM-DD')
      this.clockTime = now.format('HH:mm:ss')
    },
    handleResize() {
      this.calcPageSize()
    },
    calcPageSize() {
      const viewport = this.$refs.viewport
      if (!viewport || !viewport.clientHeight) {
        this.pageSize = DEFAULT_PAGE_SIZE
        return
      }
      const size = Math.floor(viewport.clientHeight / ROW_HEIGHT)
      this.pageSize = Math.max(10, Math.min(30, size || DEFAULT_PAGE_SIZE))
    },
    startPageFlip() {
      this.stopPageFlip()
      this.pageFlipCountdown = PAGE_FLIP_SEC
      this.countdownTimer = setInterval(() => {
        if (this.pagePaused || this.loading || this.totalPages <= 1) {
          return
        }
        if (this.pageFlipCountdown > 1) {
          this.pageFlipCountdown -= 1
          return
        }
        this.nextPage()
        this.pageFlipCountdown = PAGE_FLIP_SEC
      }, 1000)
    },
    stopPageFlip() {
      if (this.pageFlipTimer) {
        clearInterval(this.pageFlipTimer)
        this.pageFlipTimer = null
      }
      if (this.countdownTimer) {
        clearInterval(this.countdownTimer)
        this.countdownTimer = null
      }
    },
    nextPage() {
      if (this.totalPages <= 1) return
      this.currentPage = this.currentPage >= this.totalPages ? 1 : this.currentPage + 1
    },
    resetPagination() {
      this.currentPage = 1
      this.pageFlipCountdown = PAGE_FLIP_SEC
      this.$nextTick(() => {
        this.calcPageSize()
        this.startPageFlip()
      })
    },
    async fetchData() {
      if (!this.chejian) return
      this.loading = true
      try {
        const res = await getProduceDataKanban(this.chejian)
        this.rawList = this.parseList(res)
        this.refreshHint = `更新于 ${dayjs().format('HH:mm:ss')}`
        this.resetPagination()
      } catch (e) {
        this.rawList = []
        this.refreshHint = '数据加载失败'
        this.stopPageFlip()
      } finally {
        this.loading = false
      }
    },
    parseList(res) {
      if (Array.isArray(res)) return res
      if (Array.isArray(res && res.rows)) return res.rows
      if (Array.isArray(res && res.data)) return res.data
      return []
    },
    normalizeRow(item, index) {
      const delayDays = this.pickNumber(item, ['delayDays', 'delayDay', 'delay'])
      const delayed = delayDays != null && delayDays > 0
      return {
        ...item,
        moOrderNo: this.pickField(item, ['moOrderNo', 'productionOrderNo', 'sclh']),
        materialNumber: this.pickField(item, ['materialNumber', 'productCode']),
        materialName: this.pickField(item, ['materialName', 'productName']),
        operQty: this.pickField(item, ['operQty', 'qty', 'quantity']),
        transInQty: this.pickField(item, ['transInQty', 'transferIn']),
        transOutQty: this.pickField(item, ['transOutQty', 'transferOut']),
        operNumber: this.pickField(item, ['operNumber', 'processNo', 'operNo']),
        processName: this.pickField(item, ['processName', 'operation', 'workName']),
        operPlanStartTime: this.pickField(item, ['operPlanStartTime', 'planStartDate', 'FPlanStartDate']),
        operPlanFinishTime: this.pickField(item, ['operPlanFinishTime', 'planFinishDate', 'FPlanFinishDate']),
        _index: index + 1,
        _key: item.id != null ? item.id : `${index}-${item.moOrderNo || ''}`,
        _delayed: delayed,
        _delayText: delayed ? String(delayDays) : '--',
      }
    },
    pickField(obj, keys) {
      for (let i = 0; i < keys.length; i++) {
        const v = obj[keys[i]]
        if (v !== undefined && v !== null && v !== '') return v
      }
      return ''
    },
    pickNumber(obj, keys) {
      const v = this.pickField(obj, keys)
      if (v === '') return null
      const n = Number(v)
      return Number.isFinite(n) ? n : null
    },
    formatQty(val) {
      if (val === '' || val == null) return '—'
      const n = Number(val)
      return Number.isFinite(n) ? n : val
    },
    formatPlanDate(val) {
      if (!val) return '—'
      const d = dayjs(val)
      if (d.isValid()) return d.format('MM-DD')
      const str = String(val)
      if (str.length >= 10) return str.slice(5, 10)
      return str
    },
  },
}
</script>

<style scoped>
.produce-kanban {
  --kb-bg: #07101f;
  --kb-bg-panel: rgba(8, 22, 42, 0.92);
  --kb-border: rgba(64, 158, 255, 0.35);
  --kb-border-strong: rgba(64, 158, 255, 0.55);
  --kb-text: #eef4ff;
  --kb-text-dim: rgba(200, 220, 255, 0.72);
  --kb-delay: #ff4d4f;
  --kb-header-h: 88px;

  position: fixed;
  inset: 0;
  overflow: hidden;
  background: radial-gradient(ellipse 120% 80% at 50% -10%, #0f2847 0%, var(--kb-bg) 55%);
  color: var(--kb-text);
  font-family: "Microsoft YaHei", "PingFang SC", "Helvetica Neue", sans-serif;
}

.kanban-bg-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(64, 158, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(64, 158, 255, 0.04) 1px, transparent 1px);
  background-size: 32px 32px;
  pointer-events: none;
}

.kanban-scanline {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    transparent,
    transparent 2px,
    rgba(0, 0, 0, 0.03) 2px,
    rgba(0, 0, 0, 0.03) 4px
  );
  pointer-events: none;
  opacity: 0.35;
}

.kanban-header {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  align-items: center;
  height: var(--kb-header-h);
  padding: 0 28px;
  border-bottom: 2px solid var(--kb-border-strong);
  background: linear-gradient(180deg, rgba(12, 32, 58, 0.95) 0%, rgba(8, 20, 38, 0.88) 100%);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.35);
}

.brand-logo {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.brand-logo__cn {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: #fff;
}

.brand-logo__en {
  margin-top: 2px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: #5dade2;
  text-transform: uppercase;
}

.kanban-header__center {
  text-align: center;
}

.kanban-title {
  margin: 0;
  font-size: clamp(22px, 2.2vw, 34px);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #fff;
  text-shadow: 0 0 20px rgba(64, 158, 255, 0.25);
}

.kanban-subtitle {
  margin: 6px 0 0;
  font-size: clamp(14px, 1.2vw, 20px);
  font-weight: 600;
  color: #7ec8ff;
  letter-spacing: 0.08em;
}

.kanban-header__clock {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.clock-date {
  display: block;
  font-size: 16px;
  color: var(--kb-text-dim);
}

.clock-time {
  display: block;
  margin-top: 4px;
  font-size: 26px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.06em;
}

.kanban-table-wrap {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  height: calc(100vh - var(--kb-header-h));
  padding: 10px 16px 12px;
}

.kanban-table-head {
  flex-shrink: 0;
  border: 1px solid var(--kb-border-strong);
  border-bottom: none;
  background: rgba(15, 45, 80, 0.85);
}

.kanban-table-head table,
.kanban-data-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.kanban-table-head th {
  padding: 12px 6px;
  font-size: clamp(13px, 1vw, 16px);
  font-weight: 700;
  color: #fff;
  text-align: center;
  border-right: 1px solid rgba(64, 158, 255, 0.2);
  white-space: nowrap;
}

.kanban-table-head th:last-child {
  border-right: none;
}

.kanban-page-viewport {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  border: 1px solid var(--kb-border);
  background: var(--kb-bg-panel);
  position: relative;
}

.kanban-data-table {
  height: 100%;
}

.kanban-data-table td {
  padding: 10px 6px;
  height: 42px;
  box-sizing: border-box;
  font-size: clamp(13px, 0.95vw, 17px);
  font-weight: 600;
  text-align: center;
  color: var(--kb-text);
  border-bottom: 1px solid rgba(64, 158, 255, 0.12);
  border-right: 1px solid rgba(64, 158, 255, 0.08);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kanban-data-table td:last-child {
  border-right: none;
}

.kanban-data-table tbody tr:nth-child(even):not(.row-placeholder) td {
  background: rgba(255, 255, 255, 0.02);
}

.kanban-data-table tbody tr.row-delayed td {
  color: var(--kb-delay);
  text-shadow: 0 0 8px rgba(255, 77, 79, 0.35);
}

.kanban-data-table tbody tr.row-placeholder td {
  border-bottom-color: rgba(64, 158, 255, 0.06);
  background: transparent;
}

.kanban-page-enter-active,
.kanban-page-leave-active {
  transition: opacity 0.45s ease, transform 0.45s ease;
}

.kanban-page-enter {
  opacity: 0;
  transform: translateY(12px);
}

.kanban-page-leave-to {
  opacity: 0;
  transform: translateY(-12px);
}

.kanban-loading,
.kanban-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 100%;
  font-size: 18px;
  color: var(--kb-text-dim);
}

.kanban-loading i {
  font-size: 24px;
}

.kanban-footer {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 8px;
  font-size: 14px;
  color: var(--kb-text-dim);
}

.kanban-footer__sep {
  opacity: 0.4;
}

.kanban-pager-dots {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 8px;
}

.pager-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  transition: background 0.3s, transform 0.3s;
}

.pager-dot.is-active {
  background: #409eff;
  transform: scale(1.25);
  box-shadow: 0 0 8px rgba(64, 158, 255, 0.6);
}
</style>
