<template>
  <d2-container>
    <template #header>
      <div class="search-bar">
        <el-form :inline="true" size="mini">
          <el-form-item :label="$t(key('device_category'))">
            <el-select
              v-model="search.device_category_id"
              :placeholder="$t(key('select_device_category'))"
              clearable
              filterable
              style="width:220px"
              @change="onSearch"
            >
              <el-option
                v-for="item in deviceCategoryOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button icon="el-icon-refresh" :disabled="loading" @click="onReset">
              {{ $t(key('reset')) }}
            </el-button>
          </el-form-item>
        </el-form>
      </div>
      <div class="status-board">
        <el-card
          :class="['status-card', 'status-card--all', { 'is-active': activeStatus === '' }]"
          shadow="hover"
          @click.native="selectStatus('all')"
        >
          <span class="status-card__label">{{ $t(key('device_total')) }}</span>
          <strong class="status-card__value">{{ totalDeviceCount }}</strong>
        </el-card>
        <el-card
          v-for="item in statusCards"
          :key="item.status"
          :class="['status-card', 'status-card--' + item.className, { 'is-active': activeStatus === item.status }]"
          shadow="hover"
          @click.native="selectStatus(item.status)"
        >
          <span class="status-card__label">{{ $t(key(item.label)) }}</span>
          <strong class="status-card__value">{{ item.count }}</strong>
        </el-card>
      </div>
    </template>

    <page-table
      :columns="columns"
      :data="sortedTableData"
      :loading="loading"
      :toolbar-buttons="[]"
      :row-buttons="[]"
      :pagination="null"
      :table-attrs="{ size: 'mini', rowKey: 'id', highlightCurrentRow: true }"
      :table-listeners="tableListeners"
      auto-height
    >
      <template #col-status="{ row }">
        <el-tag :color="statusColor(row.status)" class="status-tag">
          {{ statusName(row.status) }}
        </el-tag>
      </template>
      <template #col-msg="{ row }">
        <span>{{ row.status === 'TROUBLE' ? row.msg : '' }}</span>
      </template>
      <template #empty>
        <el-empty :description="$t('暂无数据')" :image-size="80" />
      </template>
    </page-table>
  </d2-container>
</template>

<script>
import { useTableColumns } from '@/composables/useTableColumns'
import { i18nMixin } from '@/composables/useI18n'
import PageTable from '@/components/page-table'
import { getDeviceAll } from '@/api/planning-production/equipment-monitoring'
import { getDeviceCategoryAll } from '@/api/production-master-data/device-category'

const STATUS_META = {
  FINISH: { label: 'finished', color: '#409EFF', className: 'finish' },
  RUN: { label: 'run', color: '#67C23A', className: 'run' },
  OFFLINE: { label: 'offline', color: '#A1A1A1', className: 'offline' },
  TROUBLE: { label: 'exception', color: '#F56C6C', className: 'trouble' },
  IDLE: { label: 'idle', color: '#E6A23C', className: 'idle' },
  PAUSE: { label: 'manual', color: '#EF42EF', className: 'pause' }
}

export default {
  name: 'planning-production-equipment-monitoring',
  components: { PageTable },
  mixins: [i18nMixin('page.planning_production.production_monitoring.equipment_monitoring')],
  data () {
    return {
      loading: false,
      activeStatus: '',
      tableData: [],
      statusNum: [],
      totalCount: 0,
      deviceCategoryOptions: [],
      search: {
        device_category_id: ''
      },
      sortState: {
        prop: '',
        order: ''
      },
      refreshTimer: null
    }
  },
  computed: {
    columns () {
      return useTableColumns([
        { prop: 'code', label: this.key('device_code'), minWidth: 140, sortable: 'custom', showOverflowTooltip: true },
        { prop: 'name', label: this.key('device_name'), minWidth: 160, sortable: 'custom', showOverflowTooltip: true },
        { prop: 'area_name', label: this.key('area'), minWidth: 120, sortable: 'custom', showOverflowTooltip: true },
        { prop: 'line_name', label: this.key('production_line'), minWidth: 140, sortable: 'custom', showOverflowTooltip: true },
        { prop: 'workstation_name', label: this.key('workstation'), minWidth: 140, sortable: 'custom', showOverflowTooltip: true },
        { prop: 'heartbeat', label: this.key('last_response'), minWidth: 170, sortable: 'custom', showOverflowTooltip: true },
        { prop: 'status', label: this.key('work_status'), minWidth: 110, sortable: 'custom', slot: 'status' },
        { prop: 'msg', label: this.key('msg'), minWidth: 180, sortable: 'custom', slot: 'msg', showOverflowTooltip: true }
      ], {
        selectionWidth: 0,
        indexWidth: 55
      })
    },
    tableListeners () {
      return {
        'sort-change': this.onSortChange
      }
    },
    statusCountMap () {
      return this.statusNum.reduce((result, item) => {
        const status = this.normalizeStatus(item.status || item.key || item.name || item.type)
        if (status) {
          result[status] = Number(item.num || item.count || item.value || item.total || 0)
        }
        return result
      }, {})
    },
    totalDeviceCount () {
      const statusTotal = Object.keys(this.statusCountMap).reduce((total, status) => {
        return total + this.statusCountMap[status]
      }, 0)
      return statusTotal || this.totalCount || this.tableData.length
    },
    statusCards () {
      return Object.keys(STATUS_META).map(status => ({
        status,
        count: this.statusCountMap[status] || 0,
        ...STATUS_META[status]
      }))
    },
    sortedTableData () {
      if (!this.sortState.prop || !this.sortState.order) return this.tableData
      const direction = this.sortState.order === 'ascending' ? 1 : -1
      return [...this.tableData].sort((a, b) => {
        return this.compareValue(a[this.sortState.prop], b[this.sortState.prop]) * direction
      })
    }
  },
  mounted () {
    this.loadDeviceCategoryOptions()
    this.fetchData()
    this.refreshTimer = setInterval(() => {
      this.fetchData(false)
    }, 5000)
  },
  beforeDestroy () {
    if (this.refreshTimer) {
      clearInterval(this.refreshTimer)
      this.refreshTimer = null
    }
  },
  methods: {
    selectStatus (status) {
      this.activeStatus = status === 'all' ? '' : status
      this.fetchData()
    },
    normalizePayload (res) {
      if (!res) return {}
      if (Array.isArray(res)) return { data: res, status_num: [] }
      if (res.data && !Array.isArray(res.data) && (res.data.data || res.data.status_num || res.data.statusNum || res.data.status_count || res.data.statusCount)) {
        return res.data
      }
      const payload = res || {}
      if (Array.isArray(payload)) {
        return { data: payload, status_num: [] }
      }
      return payload || {}
    },
    normalizeList (res) {
      const payload = this.normalizePayload(res)
      if (Array.isArray(payload)) return payload
      if (Array.isArray(payload.data)) return payload.data
      if (Array.isArray(payload.list)) return payload.list
      if (Array.isArray(payload.rows)) return payload.rows
      if (Array.isArray(payload.records)) return payload.records
      return []
    },
    normalizeStatus (status) {
      return String(status || '').toUpperCase()
    },
    normalizeStatusNum (payload, list) {
      const statusNum = payload.status_num || payload.statusNum || payload.status_count || payload.statusCount || payload.status_counts || payload.statusCounts
      if (Array.isArray(statusNum)) return statusNum
      if (statusNum && typeof statusNum === 'object') {
        return Object.keys(statusNum).map(status => ({
          status,
          num: statusNum[status]
        }))
      }
      const counts = list.reduce((result, row) => {
        const status = this.normalizeStatus(row.status)
        if (status) {
          result[status] = (result[status] || 0) + 1
        }
        return result
      }, {})
      return Object.keys(counts).map(status => ({
        status,
        num: counts[status]
      }))
    },
    normalizeTotal (payload, list) {
      return Number(payload.count || payload.total || payload.total_count || payload.totalCount || list.length || 0)
    },
    async loadDeviceCategoryOptions () {
      try {
        const res = await getDeviceCategoryAll()
        this.deviceCategoryOptions = this.normalizeList(res).map(item => ({
          value: item.id || item.device_category_id,
          label: item.name || item.device_category_name || item.code
        })).filter(item => item.value !== undefined && item.label)
      } catch { /* 类别加载失败不影响监控列表 */ }
    },
    onReset () {
      this.search.device_category_id = ''
      this.fetchData()
    },
    onSearch () {
      this.fetchData()
    },
    onSortChange ({ prop, order }) {
      this.sortState = {
        prop: prop || '',
        order: order || ''
      }
    },
    compareValue (left, right) {
      if (left === right) return 0
      if (left === undefined || left === null || left === '') return -1
      if (right === undefined || right === null || right === '') return 1
      const leftNumber = Number(left)
      const rightNumber = Number(right)
      if (!Number.isNaN(leftNumber) && !Number.isNaN(rightNumber)) {
        return leftNumber - rightNumber
      }
      const leftDate = Date.parse(left)
      const rightDate = Date.parse(right)
      if (!Number.isNaN(leftDate) && !Number.isNaN(rightDate)) {
        return leftDate - rightDate
      }
      return String(left).localeCompare(String(right), 'zh-Hans-CN')
    },
    async fetchData (showLoading = true) {
      if (showLoading) this.loading = true
      try {
        const res = await getDeviceAll({
          status: this.activeStatus,
          device_category_id: this.search.device_category_id
        })
        const payload = this.normalizePayload(res)
        const list = this.normalizeList(payload)
        this.statusNum = this.normalizeStatusNum(payload, list)
        this.totalCount = this.normalizeTotal(payload, list)
        this.tableData = list
      } finally {
        if (showLoading) this.loading = false
      }
    },
    statusName (status) {
      const meta = STATUS_META[status]
      return meta ? this.$t(this.key(meta.label)) : status
    },
    statusColor (status) {
      const meta = STATUS_META[status]
      return meta ? meta.color : '#909399'
    }
  }
}
</script>

<style lang="scss" scoped>
.search-bar {
  padding: 0 0 10px;
}

.status-board {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
}

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

  ::v-deep .el-card__body {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
  }

  &.is-active {
    border-color: #303133;
    box-shadow: 0 2px 10px rgba(48, 49, 51, 0.12);
  }
}

.status-card--all {
  border-left-color: #303133;
}

.status-card--finish {
  border-left-color: #409EFF;
}

.status-card--run {
  border-left-color: #67C23A;
}

.status-card--offline {
  border-left-color: #A1A1A1;
}

.status-card--trouble {
  border-left-color: #F56C6C;
}

.status-card--idle {
  border-left-color: #E6A23C;
}

.status-card--pause {
  border-left-color: #EF42EF;
}

.status-card__label {
  color: #606266;
  font-size: 13px;
}

.status-card__value {
  color: #303133;
  font-size: 22px;
  line-height: 1;
}

.status-tag {
  color: #fff;
  border: 0;
}
</style>
