<template>
  <d2-container>
    <template #header>
      <div class="search-bar">
        <el-form ref="form" :inline="true" :model="form" size="mini">
          <el-form-item :label="$t(key('batch_no'))" prop="batch">
            <el-input
              v-model="form.batch"
              :placeholder="$t(key('enter_batch_no'))"
              clearable
              readonly
              style="width:220px"
              @focus="openBatchDialog"
            >
              <el-button slot="append" icon="el-icon-search" @click="openBatchDialog" />
            </el-input>
          </el-form-item>
          <el-form-item :label="$t(key('tray_code_format'))">
            <el-select
              v-model="selectedFormatId"
              :placeholder="$t(key('select_format'))"
              filterable
              style="width:220px"
              @change="selectFormat"
            >
              <el-option
                v-for="item in formatList"
                :key="item.id"
                :label="formatLabel(item)"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
          <el-form-item :label="$t(key('tray_code'))" prop="tray">
            <el-input
              v-model="form.tray"
              :placeholder="$t(key('enter_tray_code'))"
              :disabled="!currentFormat"
              clearable
              style="width:220px"
              @keyup.enter.native="focusFirstChannel"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-check" :disabled="submitting" @click="openSubmitDialog">
              {{ $t(key('login')) }}
            </el-button>
            <el-button type="warning" icon="el-icon-unlock" :disabled="submitting" @click="unbindTray">
              {{ $t(key('tray_unbind')) }}
            </el-button>
            <el-button type="danger" icon="el-icon-switch-button" :disabled="submitting" @click="stopTray">
              {{ $t(key('tray_stop')) }}
            </el-button>
            <el-button icon="el-icon-edit" :disabled="loadingFormats" @click="openFormatDialog">
              {{ $t(key('tray_battery_format_edit')) }}
            </el-button>
            <el-button icon="el-icon-refresh" :disabled="submitting" @click="resetPage">
              {{ $t(key('reset')) }}
            </el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>

    <div class="registration-layout">
      <section class="channel-panel">
        <div class="panel-head">
          <span>{{ $t(key('data_table')) }}</span>
          <el-tag size="mini">{{ loadedCount }} / {{ capacity }}</el-tag>
        </div>
        <el-empty v-if="!currentFormat" :description="$t(key('select_format_first'))" :image-size="80" />
        <div v-else class="channel-grid">
          <el-form label-width="74px" size="mini">
            <el-form-item
              v-for="channel in channelList"
              :key="channel"
              :label="$t(key('channel')) + channel"
            >
              <el-input
                :ref="inputRef(channel)"
                v-model="batteryInputs[channel]"
                :placeholder="$t(key('enter_battery_code'))"
                clearable
                @keyup.enter.native="scanBattery(channel)"
                @clear="removeBattery(channel)"
              />
            </el-form-item>
          </el-form>
        </div>
      </section>

      <section class="battery-panel">
        <div class="panel-head">
          <span>{{ $t(key('tray_load_battery_count')) }}</span>
          <el-button
            type="text"
            class="danger-action"
            :disabled="!selectedRows.length"
            @click="batchInactivity"
          >
            {{ $t(key('batch_deactivate')) }}
          </el-button>
        </div>
        <page-table
          ref="batteryTable"
          :columns="columns"
          :data="tableData"
          :loading="loadingBattery"
          :toolbar-buttons="[]"
          :row-buttons="[]"
          :pagination="null"
          :selection-selectable="isActiveBattery"
          :table-attrs="{ size: 'mini', rowKey: 'index', highlightCurrentRow: true, rowClassName: rowClassName }"
          height="520px"
          @selection-change="selectedRows = $event"
        >
          <template #col-battery="{ row }">
            <span>{{ row.Battery || row.battery_id }}</span>
          </template>
          <template #col-active="{ row }">
            <el-tag :type="Number(row.active) === 1 ? 'danger' : 'success'" size="mini">
              {{ Number(row.active) === 1 ? $t(key('activated')) : $t(key('not_activated')) }}
            </el-tag>
          </template>
          <template #empty>
            <el-empty :description="$t('暂无数据')" :image-size="80" />
          </template>
        </page-table>
      </section>
    </div>

    <el-dialog :title="$t(key('batch_no'))" :visible.sync="batchDialogVisible" width="760px">
      <page-table
        :columns="batchColumns"
        :data="batchList"
        :loading="loadingBatches"
        :toolbar-buttons="[]"
        :row-buttons="[]"
        :pagination="null"
        :table-attrs="{ size: 'mini', rowKey: 'batch', highlightCurrentRow: true }"
        :table-listeners="batchTableListeners"
        height="420px"
      />
      <span slot="footer">
        <el-button size="mini" @click="batchDialogVisible = false">{{ $t(key('cancel')) }}</el-button>
        <el-button size="mini" type="primary" :disabled="!currentBatch" @click="confirmBatch">
          {{ $t(key('confirm')) }}
        </el-button>
      </span>
    </el-dialog>

    <el-dialog :title="$t(key('format_dialog_title'))" :visible.sync="formatDialogVisible" width="820px">
      <el-button type="primary" size="mini" icon="el-icon-plus" @click="openFormatForm">
        {{ $t(key('add')) }}
      </el-button>
      <page-table
        class="format-table"
        :columns="formatColumns"
        :data="formatList"
        :loading="loadingFormats"
        :toolbar-buttons="[]"
        :row-buttons="[]"
        :pagination="null"
        :table-attrs="{ size: 'mini', rowKey: 'id', highlightCurrentRow: true }"
        :table-listeners="formatTableListeners"
        height="360px"
      >
        <template #col-actions="{ row }">
          <el-button type="text" class="danger-action" @click="deleteFormat(row)">
            {{ $t(key('delete')) }}
          </el-button>
        </template>
      </page-table>
    </el-dialog>

    <el-dialog :title="$t(key('add_format_title'))" :visible.sync="formatFormVisible" width="620px">
      <el-form :model="formatForm" label-width="150px" size="mini">
        <el-form-item :label="$t(key('tray_barcode_format'))">
          <el-input v-model="formatForm.tray_format" clearable />
        </el-form-item>
        <el-form-item :label="$t(key('battery_barcode_format'))">
          <el-input v-model="formatForm.battery_format" clearable />
        </el-form-item>
        <el-form-item :label="$t(key('tray_battery_count'))">
          <el-input-number v-model="formatForm.battery_count" :min="1" :max="96" />
        </el-form-item>
      </el-form>
      <el-alert :title="$t(key('format_rule'))" type="warning" :closable="false" />
      <span slot="footer">
        <el-button size="mini" @click="formatFormVisible = false">{{ $t(key('cancel')) }}</el-button>
        <el-button size="mini" type="primary" @click="createFormat">{{ $t(key('confirm')) }}</el-button>
      </span>
    </el-dialog>

    <el-dialog :title="$t(key('submit_login'))" :visible.sync="submitDialogVisible" width="640px">
      <page-table
        :columns="submitColumns"
        :data="tableData"
        :loading="submitting"
        :toolbar-buttons="[]"
        :row-buttons="[]"
        :pagination="null"
        :table-attrs="{ size: 'mini', rowKey: 'index' }"
        height="360px"
      >
        <template #col-battery="{ row }">
          <span>{{ row.Battery || row.battery_id }}</span>
        </template>
      </page-table>
      <span slot="footer">
        <el-button size="mini" @click="submitDialogVisible = false">{{ $t(key('cancel')) }}</el-button>
        <el-button size="mini" type="primary" :disabled="submitting" @click="submitRegistration">
          {{ $t(key('confirm')) }}
        </el-button>
      </span>
    </el-dialog>
  </d2-container>
</template>

<script>
import { useTableColumns } from '@/composables/useTableColumns'
import { i18nMixin } from '@/composables/useI18n'
import PageTable from '@/components/page-table'
import { sendWorkerman } from '@/api/workerman'
import {
  getBatchAll,
  getBatchTrayFormatAll,
  createBatchTrayFormat,
  deleteBatchTrayFormat,
  checkBatteryid
} from '@/api/planning-production/tray-registration'

export default {
  name: 'planning-production-tray-registration',
  components: { PageTable },
  mixins: [i18nMixin('page.planning_production.production_monitoring.tray_registration')],
  data () {
    return {
      form: {
        batch: '',
        tray: ''
      },
      selectedFormatId: '',
      currentFormat: null,
      batteryInputs: {},
      tableData: [],
      batchList: [],
      formatList: [],
      selectedRows: [],
      currentBatch: null,
      batchDialogVisible: false,
      formatDialogVisible: false,
      formatFormVisible: false,
      submitDialogVisible: false,
      loadingBatches: false,
      loadingFormats: false,
      loadingBattery: false,
      submitting: false,
      formatForm: {
        tray_format: '',
        battery_format: '',
        battery_count: 1
      }
    }
  },
  computed: {
    capacity () {
      return Number((this.currentFormat && this.currentFormat.battery_count) || 0)
    },
    loadedCount () {
      return this.tableData.length
    },
    channelList () {
      return Array.from({ length: this.capacity }, (_, index) => index + 1)
    },
    trayRegExp () {
      return this.createFormatRegExp(this.currentFormat && this.currentFormat.tray_format)
    },
    batteryRegExp () {
      return this.createFormatRegExp(this.currentFormat && this.currentFormat.battery_format)
    },
    columns () {
      return useTableColumns([
        { prop: 'index', label: this.key('process_channel'), width: 90 },
        { prop: 'Battery', label: this.key('battery_id'), minWidth: 180, slot: 'battery', showOverflowTooltip: true },
        { prop: 'active', label: this.key('activation_status'), width: 110, slot: 'active' },
        { prop: 'batch', label: this.key('previous_batch'), minWidth: 150, showOverflowTooltip: true },
        { prop: 'tray', label: this.key('previous_tray'), minWidth: 150, showOverflowTooltip: true },
        { prop: 'process_code', label: this.key('completed_process'), minWidth: 160, showOverflowTooltip: true }
      ], {
        selectionWidth: 55,
        indexWidth: 0
      })
    },
    batchColumns () {
      return useTableColumns([
        { prop: 'batch', label: this.key('batch_no'), minWidth: 200, showOverflowTooltip: true },
        { prop: 'flow_name', label: this.key('process_flow_name'), minWidth: 200, showOverflowTooltip: true },
        { prop: 'create_time', label: this.key('batch_create_time'), minWidth: 180, showOverflowTooltip: true }
      ], {
        selectionWidth: 0,
        indexWidth: 55
      })
    },
    formatColumns () {
      return useTableColumns([
        { prop: 'tray_format', label: this.key('tray_barcode_format'), minWidth: 160, showOverflowTooltip: true },
        { prop: 'battery_format', label: this.key('battery_barcode_format'), minWidth: 180, showOverflowTooltip: true },
        { prop: 'battery_count', label: this.key('tray_battery_count'), width: 140 },
        { prop: 'actions', label: this.key('operation'), width: 90, slot: 'actions' }
      ], {
        selectionWidth: 0,
        indexWidth: 55
      })
    },
    submitColumns () {
      return useTableColumns([
        { prop: 'index', label: this.key('process_channel'), width: 120 },
        { prop: 'Battery', label: this.key('battery_id'), minWidth: 220, slot: 'battery', showOverflowTooltip: true }
      ], {
        selectionWidth: 0,
        indexWidth: 0
      })
    },
    batchTableListeners () {
      return {
        'current-change': this.onBatchCurrentChange,
        'row-click': this.onBatchCurrentChange,
        'row-dblclick': this.selectBatch
      }
    },
    formatTableListeners () {
      return {
        'row-dblclick': this.selectFormatRow
      }
    }
  },
  created () {
    this.fetchBatchList()
    this.fetchFormatList()
  },
  methods: {
    responseData (res) {
      const payload = res && res.data ? res.data : (res || {})
      return payload.data || payload
    },
    normalizeBatteryCheckResult (res) {
      if (res && res.code !== undefined) {
        return {
          code: Number(res.code),
          message: res.msg || res.errmsg,
          data: res.data || {}
        }
      }
      return {
        code: 0,
        message: '',
        data: res || {}
      }
    },
    formatLabel (item) {
      return `${item.tray_format} / ${item.battery_format} / ${item.battery_count}`
    },
    inputRef (channel) {
      return `batteryInput${channel}`
    },
    createFormatRegExp (format) {
      if (!format) return null
      const escaped = String(format).replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[A-Z0-9-]')
      return new RegExp(`^${escaped}$`)
    },
    openBatchDialog () {
      this.currentBatch = this.batchList.find(item => item.batch === this.form.batch) || null
      this.batchDialogVisible = true
      if (!this.batchList.length) this.fetchBatchList()
    },
    onBatchCurrentChange (row) {
      this.currentBatch = row || null
    },
    confirmBatch () {
      if (!this.currentBatch) return
      this.selectBatch(this.currentBatch)
    },
    selectBatch (row) {
      if (!row || !row.batch) return
      this.form.batch = row.batch
      this.currentBatch = row
      this.batchDialogVisible = false
    },
    async fetchBatchList () {
      this.loadingBatches = true
      try {
        const res = await getBatchAll({ action: 'get_batch' })
        const data = this.responseData(res)
        this.batchList = Array.isArray(data) ? data : []
      } finally {
        this.loadingBatches = false
      }
    },
    async fetchFormatList () {
      this.loadingFormats = true
      try {
        const res = await getBatchTrayFormatAll({ action: 'get_login_format' })
        const data = this.responseData(res)
        this.formatList = Array.isArray(data) ? data : []
        if (!this.currentFormat && this.formatList.length) {
          this.selectFormat(this.formatList[0].id)
        }
      } finally {
        this.loadingFormats = false
      }
    },
    selectFormat (id) {
      const target = this.formatList.find(item => String(item.id) === String(id))
      if (!target) return
      this.currentFormat = target
      this.selectedFormatId = target.id
      this.tableData = []
      this.selectedRows = []
      this.batteryInputs = {}
    },
    selectFormatRow (row) {
      this.selectFormat(row.id)
      this.formatDialogVisible = false
    },
    focusFirstChannel () {
      if (!this.validateTray()) return
      this.$nextTick(() => {
        const refs = this.$refs[this.inputRef(1)]
        const input = Array.isArray(refs) ? refs[0] : refs
        if (input) input.focus()
      })
    },
    validateTray () {
      if (!this.currentFormat) {
        this.$message.warning(this.$t(this.key('select_format_first')))
        return false
      }
      if (!this.form.tray) {
        this.$message.warning(this.$t(this.key('please_enter_tray_code')))
        return false
      }
      if (this.trayRegExp && !this.trayRegExp.test(this.form.tray)) {
        this.$message.warning(this.$t(this.key('format_error_exclamation')))
        return false
      }
      return true
    },
    async scanBattery (channel) {
      if (!this.validateTray()) return
      const batteryId = this.batteryInputs[channel]
      if (!batteryId) {
        this.removeBattery(channel)
        return
      }
      if (this.batteryRegExp && !this.batteryRegExp.test(batteryId)) {
        this.$message.warning(this.$t(this.key('format_error')))
        this.removeBattery(channel)
        return
      }
      const duplicate = this.tableData.find(item => item.index !== channel && item.Battery === batteryId)
      if (duplicate) {
        this.$message.warning(this.$t(this.key('insert_duplicate_battery')))
        this.removeBattery(channel)
        return
      }
      this.loadingBattery = true
      try {
        const res = await checkBatteryid({
          action: 'check_elements_code',
          battery_id: batteryId
        })
        const { code, message, data } = this.normalizeBatteryCheckResult(res)
        if (code !== 0) {
          this.$message.error(message || this.$t(this.key('format_error')))
          this.removeBattery(channel)
          return
        }
        const row = {
          ...data,
          Battery: batteryId,
          battery_id: data.battery_id || batteryId,
          index: channel
        }
        const exists = this.tableData.findIndex(item => item.index === channel)
        if (exists >= 0) {
          this.$set(this.tableData, exists, row)
        } else {
          this.tableData.push(row)
        }
        this.tableData.sort((a, b) => a.index - b.index)
        this.focusNextChannel(channel)
      } finally {
        this.loadingBattery = false
      }
    },
    focusNextChannel (channel) {
      const next = channel + 1
      if (next > this.capacity) return
      this.$nextTick(() => {
        const refs = this.$refs[this.inputRef(next)]
        const input = Array.isArray(refs) ? refs[0] : refs
        if (input) {
          input.focus()
          input.select()
        }
      })
    },
    removeBattery (channel) {
      this.$delete(this.batteryInputs, channel)
      this.tableData = this.tableData.filter(item => item.index !== channel)
    },
    openFormatDialog () {
      this.formatDialogVisible = true
      this.fetchFormatList()
    },
    openFormatForm () {
      this.formatForm = {
        tray_format: '',
        battery_format: '',
        battery_count: 1
      }
      this.formatFormVisible = true
    },
    async createFormat () {
      if (!this.formatForm.tray_format) {
        this.$message.warning(this.$t(this.key('add_tray_format')))
        return
      }
      if (!this.formatForm.battery_format) {
        this.$message.warning(this.$t(this.key('add_battery_format')))
        return
      }
      if (!this.formatForm.battery_count || Number(this.formatForm.battery_count) <= 0) {
        this.$message.warning(this.$t(this.key('add_battery_count')))
        return
      }
      await createBatchTrayFormat({
        action: 'set_login_format',
        ...this.formatForm
      })
      this.$message.success(this.$t(this.key('operation_success')))
      this.formatFormVisible = false
      this.fetchFormatList()
    },
    deleteFormat (row) {
      this.$confirm(this.$t(this.key('delete_confirm')), this.$t(this.key('prompt')), {
        confirmButtonText: this.$t(this.key('confirm')),
        cancelButtonText: this.$t(this.key('cancel')),
        type: 'warning'
      }).then(async () => {
        await deleteBatchTrayFormat({
          action: 'set_login_format',
          id: row.id
        })
        this.$message.success(this.$t(this.key('delete_success')))
        this.fetchFormatList()
      }).catch(() => {})
    },
    openSubmitDialog () {
      if (!this.validateSubmit()) return
      this.submitDialogVisible = true
    },
    validateSubmit () {
      if (!this.validateTray()) return false
      if (!this.form.batch) {
        this.$message.warning(this.$t(this.key('no_batch_no')))
        return false
      }
      if (!this.tableData.length) {
        this.$message.warning(this.$t(this.key('enter_battery_code')))
        return false
      }
      if (this.tableData.some(item => Number(item.active) === 1)) {
        this.$message.warning(this.$t(this.key('has_active_battery_login_forbidden')))
        return false
      }
      return true
    },
    batteryIdsForSubmit () {
      return this.channelList.map(channel => {
        const row = this.tableData.find(item => item.index === channel)
        return row ? row.Battery : '0'
      })
    },
    async submitRegistration () {
      if (!this.validateSubmit()) return
      this.submitting = true
      try {
        const res = await sendWorkerman({
          sendData: {
            action: 'set_tray_login',
            param: {
              workingsubclass: 'LOGIN',
              tray: this.form.tray,
              batch: this.form.batch,
              device_code: 'WEBMAN_LOGIN',
              direction_sign: '',
              lot: String(new Date().valueOf()),
              battery_ids: this.batteryIdsForSubmit(),
              Manual: true
            }
          }
        })
        const payload = res && res.data ? res.data : (res || {})
        if (payload.code !== undefined && Number(payload.code) !== 0) {
          this.$message.warning(payload.errmsg || payload.msg || this.$t(this.key('operation_failed')))
          return
        }
        this.$message.success(this.$t(this.key('upload_success')))
        this.submitDialogVisible = false
        this.resetPage()
      } finally {
        this.submitting = false
      }
    },
    unbindTray () {
      this.promptTray('tray_unbind_desc', 'tray_unbind', 'set_tray_unbinding', 'tray_unbind_success')
    },
    stopTray () {
      this.promptTray('tray_stop_desc', 'tray_stop', 'set_tray_inactivity', 'tray_stop_success')
    },
    promptTray (messageKey, titleKey, action, successKey) {
      this.$prompt(this.$t(this.key(messageKey)), this.$t(this.key(titleKey)), {
        confirmButtonText: this.$t(this.key('confirm')),
        cancelButtonText: this.$t(this.key('cancel')),
        inputValue: this.form.tray,
        inputValidator: value => {
          if (!value) return this.$t(this.key('enter_tray_no'))
          return true
        }
      }).then(async ({ value }) => {
        const param = { tray: value }
        await sendWorkerman({
          sendData: {
            action,
            param
          }
        })
        this.$message.success(this.$t(this.key(successKey)))
      }).catch(() => {})
    },
    batchInactivity () {
      if (!this.selectedRows.length) {
        this.$message.warning(this.$t(this.key('select_battery_to_deactivate')))
        return
      }
      this.$confirm(this.$t(this.key('battery_deactivate')), this.$t(this.key('prompt')), {
        confirmButtonText: this.$t(this.key('confirm')),
        cancelButtonText: this.$t(this.key('cancel')),
        type: 'warning'
      }).then(async () => {
        const rows = [...this.selectedRows]
        await sendWorkerman({
          sendData: {
            action: 'set_battery_inactivity',
            param: {
              data: rows.map(row => ({
                battery_id: row.Battery || row.battery_id,
                class: 'NG',
                classname: 'web_inactivity'
              }))
            }
          }
        })
        rows.forEach(row => {
          const target = this.tableData.find(item => item.index === row.index)
          if (target) this.$set(target, 'active', 0)
        })
        this.tableData = [...this.tableData]
        this.selectedRows = []
        if (this.$refs.batteryTable) this.$refs.batteryTable.clearSelection()
        this.$message.success(this.$t(this.key('batch_battery_deactivate_success')))
      }).catch(() => {})
    },
    rowClassName ({ row }) {
      return Number(row.active) === 1 ? 'is-active-battery' : ''
    },
    isActiveBattery (row) {
      return Number(row.active) === 1
    },
    resetPage () {
      this.form.tray = ''
      this.batteryInputs = {}
      this.tableData = []
      this.selectedRows = []
      this.submitDialogVisible = false
    }
  }
}
</script>

<style lang="scss" scoped>
.registration-layout {
  display: grid;
  grid-template-columns: minmax(360px, 1fr) minmax(520px, 1fr);
  gap: 12px;
}

.channel-panel,
.battery-panel {
  min-width: 0;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 32px;
  margin-bottom: 8px;
  color: #303133;
  font-weight: 600;
}

.channel-grid {
  max-height: 560px;
  padding-right: 8px;
  overflow: auto;

  ::v-deep .el-form {
    display: grid;
    grid-template-columns: repeat(2, minmax(220px, 1fr));
    column-gap: 10px;
  }
}

.format-table {
  margin-top: 10px;
}

.danger-action {
  color: #f56c6c;
}

::v-deep .el-table .is-active-battery td {
  background-color: rgba(245, 108, 108, 0.12);
}

@media (max-width: 1100px) {
  .registration-layout {
    grid-template-columns: 1fr;
  }
}
</style>
