<template>
  <d2-container>
    <template #header>
      <div class="search-bar">
        <el-form :inline="true" :model="search" size="mini">
          <el-form-item :label="$t(key('device_category'))">
            <el-select v-model="search.device_category_id" :placeholder="$t(key('please_select_device_category'))" clearable filterable style="width:220px">
              <el-option v-for="item in deviceCategoryOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
          <el-form-item :label="$t(key('device_consumables_category_name'))">
            <el-select v-model="search.device_consumables_category_id" :placeholder="$t(key('please_select_consumables_category'))" clearable filterable style="width:240px">
              <el-option v-for="item in consumablesCategoryOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
          <el-form-item :label="$t(key('consumables_item_code'))">
            <el-input v-model.trim="search.code" :placeholder="$t(key('enter_consumables_item_code'))" clearable style="width:220px" @keyup.enter.native="onSearch" />
          </el-form-item>
          <el-form-item :label="$t(key('consumables_item_name'))">
            <el-input v-model.trim="search.name" :placeholder="$t(key('enter_consumables_item_name'))" clearable style="width:220px" @keyup.enter.native="onSearch" />
          </el-form-item>
          <el-form-item :label="$t(key('create_time'))">
            <el-date-picker v-model="search.create_time" type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss" :start-placeholder="$t(key('start_time'))" :end-placeholder="$t(key('end_time'))" style="width:330px" />
          </el-form-item>
          <el-form-item :label="$t(key('update_time'))">
            <el-date-picker v-model="search.update_time" type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss" :start-placeholder="$t(key('start_time'))" :end-placeholder="$t(key('end_time'))" style="width:330px" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search" @click="onSearch">{{ $t(key('search')) }}</el-button>
            <el-button icon="el-icon-refresh" @click="onReset">{{ $t(key('reset')) }}</el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>

    <page-table ref="pageTable" :columns="columns" :data="tableData" :loading="loading" :toolbar-buttons="toolbarButtons" :row-buttons="rowButtons" :pagination="pagination" auto-height @page-change="onPageChange" @selection-change="selectedRows = $event" />

    <page-dialog-form ref="dialogForm" :visible.sync="dialogVisible" :title="dialogTitle" width="620px" :form-cols="formCols" :form-data="formData" :rules="rules" label-width="150px" :submitting="submitting" :confirm-text="key('confirm')" :cancel-text="key('cancel')" @submit="onDialogSubmit" @close="resetForm" />

    <el-dialog :title="$t(key('import_title'))" :visible.sync="importVisible" width="900px" :close-on-click-modal="false">
      <el-alert :title="$t(key('import_tip'))" type="warning" :closable="false" />
      <el-upload class="import-upload" action="" :auto-upload="false" :show-file-list="true" :file-list="importFileList" accept=".xls,.xlsx" :on-change="onImportFileChange">
        <el-button slot="trigger" size="mini" type="success">{{ $t(key('select_file')) }}</el-button>
        <el-button style="margin-left:10px" size="mini" type="primary" :loading="importLoading" @click.stop="downloadTemplate">{{ $t(key('download_template')) }}</el-button>
      </el-upload>
      <el-table v-loading="importTableLoading" :data="importRows" border height="330" size="mini">
        <el-table-column prop="code" :label="$t(key('consumables_item_code'))" min-width="130" />
        <el-table-column prop="name" :label="$t(key('consumables_item_name'))" min-width="130" />
        <el-table-column prop="device_consumables_category_name" :label="$t(key('device_consumables_category_name'))" min-width="150" />
        <el-table-column prop="device_category_name" :label="$t(key('device_category'))" min-width="130" />
        <el-table-column prop="standard_service_life" :label="$t(key('standard_service_life'))" min-width="130" />
        <el-table-column prop="warning_service_life" :label="$t(key('warning_service_life'))" min-width="130" />
        <el-table-column prop="unit_name" :label="$t(key('service_life_unit'))" min-width="120" />
        <el-table-column prop="remark" :label="$t(key('remark'))" min-width="130" />
      </el-table>
      <span slot="footer">
        <el-button @click="importVisible = false">{{ $t(key('cancel')) }}</el-button>
        <el-button type="primary" @click="submitImport">{{ $t(key('confirm')) }}</el-button>
      </span>
    </el-dialog>
  </d2-container>
</template>

<script>
import { useTableColumns } from '@/composables/useTableColumns'
import { useTableButtons } from '@/composables/useTableButtons'
import { i18nMixin } from '@/composables/useI18n'
import { confirmMixin } from '@/composables/useConfirmHandle'
import PageTable from '@/components/page-table'
import PageDialogForm from '@/components/page-dialog-form'
import { downloadRename, readExcel } from '@/utils/file'
import { getEquipmentCategoryALL } from '@/api/equipment-management/equipment-category'
import { getUnitAll } from '@/api/production-master-data/material-unit'
import { getAll as getConsumablesCategoryAll } from '@/api/equipment-management/consumables-category'
import { getList, createItem, editItem, deleteItem, createExportTask, getImportTemplate, importData } from '@/api/equipment-management/consumables-items'

function readPageData (res) {
  const data = res && res.data !== undefined ? res.data : res
  if (Array.isArray(data)) return { list: data, total: data.length }
  if (data && Array.isArray(data.data)) return { list: data.data, total: Number(data.count || data.total || data.data.length) }
  if (data && data.data && Array.isArray(data.data.data)) return { list: data.data.data, total: Number(data.data.count || data.data.total || data.data.data.length) }
  return { list: [], total: 0 }
}
function toOptions (list, label = 'name', value = 'id') {
  return (Array.isArray(list) ? list : []).map(item => ({ label: item[label], value: item[value], raw: item }))
}

export default {
  name: 'equipment-management-consumables-items',
  components: { PageTable, PageDialogForm },
  mixins: [i18nMixin('page.equipment_management.consumables_management.consumables_items'), confirmMixin],
  data () {
    return {
      loading: false,
      submitting: false,
      tableData: [],
      selectedRows: [],
      search: { device_category_id: '', device_consumables_category_id: '', code: '', name: '', create_time: [], update_time: [] },
      pagination: { current: 1, size: 10, total: 0 },
      dialogVisible: false,
      dialogTitle: '',
      handleType: 'create',
      editId: '',
      formData: { device_category_id: '', device_consumables_category_id: '', code: '', name: '', standard_service_life: 0, warning_service_life: 0, unit_id: '', remark: '' },
      deviceCategoryOptions: [],
      consumablesCategoryOptions: [],
      unitOptions: [],
      importVisible: false,
      importFileList: [],
      importRows: [],
      importLoading: false,
      importTableLoading: false,
      columns: [],
      toolbarButtons: [],
      rowButtons: [],
      rules: {
        device_category_id: [{ required: true, message: this.key('please_select_device_category'), trigger: 'change' }],
        device_consumables_category_id: [{ required: true, message: this.key('please_select_consumables_category'), trigger: 'change' }],
        code: [{ required: true, message: this.key('enter_consumables_item_code'), trigger: 'blur' }],
        name: [{ required: true, message: this.key('enter_consumables_item_name'), trigger: 'blur' }],
        standard_service_life: [{ required: true, message: this.key('enter_standard_service_life'), trigger: 'blur' }, { validator: this.validateLifeRule, trigger: 'change' }],
        warning_service_life: [{ required: true, message: this.key('enter_warning_service_life'), trigger: 'blur' }, { validator: this.validateLifeRule, trigger: 'change' }],
        unit_id: [{ required: true, message: this.key('please_select_service_life_unit'), trigger: 'change' }]
      }
    }
  },
  computed: {
    formCols () {
      return [
        [
          { type: 'select', prop: 'device_category_id', label: this.key('device_category'), placeholder: this.key('please_select_device_category'), options: this.deviceCategoryOptions, style: { width: '100%' }, onChange: this.onFormDeviceCategoryChange },
          { type: 'select', prop: 'device_consumables_category_id', label: this.key('consumables_category'), placeholder: this.key('please_select_consumables_category'), options: this.consumablesCategoryOptions, style: { width: '100%' } }
        ],
        [
          { type: 'input', prop: 'code', label: this.key('consumables_item_code'), placeholder: this.key('enter_consumables_item_code'), style: { width: '100%' } },
          { type: 'input', prop: 'name', label: this.key('consumables_item_name'), placeholder: this.key('enter_consumables_item_name'), style: { width: '100%' } }
        ],
        [
          { type: 'input-number', prop: 'standard_service_life', label: this.key('standard_life'), placeholder: this.key('enter_standard_service_life'), min: 0, style: { width: '100%' } },
          { type: 'input-number', prop: 'warning_service_life', label: this.key('warning_life'), placeholder: this.key('enter_warning_service_life'), min: 0, style: { width: '100%' } }
        ],
        [{ type: 'select', prop: 'unit_id', label: this.key('service_life_unit'), placeholder: this.key('please_select_service_life_unit'), options: this.unitOptions, style: { width: '100%' } }],
        [{ type: 'input', prop: 'remark', label: this.key('remark'), placeholder: this.key('enter_remark'), inputType: 'textarea', autosize: { minRows: 2, maxRows: 6 }, style: { width: '100%' } }]
      ]
    }
  },
  created () {
    this.columns = useTableColumns([
      { prop: 'sort', label: this.key('sort'), width: 80 },
      { prop: 'code', label: this.key('consumables_item_code'), minWidth: 140 },
      { prop: 'name', label: this.key('consumables_item_name'), minWidth: 140 },
      { prop: 'device_consumables_category_name', label: this.key('device_consumables_category_name'), minWidth: 160 },
      { prop: 'device_category_name', label: this.key('device_category'), minWidth: 140 },
      { prop: 'standard_service_life', label: this.key('standard_service_life'), minWidth: 130 },
      { prop: 'warning_service_life', label: this.key('warning_service_life'), minWidth: 130 },
      { prop: 'unit_name', label: this.key('service_life_unit'), minWidth: 120 },
      { prop: 'remark', label: this.key('remark'), minWidth: 140, showOverflowTooltip: true },
      { prop: 'create_time', label: this.key('create_time'), minWidth: 160 },
      { prop: 'update_time', label: this.key('update_time'), minWidth: 160 },
      { prop: '_actions', label: this.key('operation'), width: 170, fixed: 'right' }
    ])
    const btns = useTableButtons({
      toolbar: [
        { key: 'add', label: this.key('add'), icon: 'el-icon-plus', type: 'primary', auth: '/device_management/device_consumables/device_consumables_items/create', onClick: this.openAdd },
        { key: 'batch_delete', label: this.key('batch_delete'), icon: 'el-icon-delete', color: 'danger', auth: '/device_management/device_consumables/device_consumables_items/batch-delete', needSelection: true, disabledTip: this.key('please_select_data'), onClick: this.handleBatchDelete },
        { key: 'import', label: this.key('import'), icon: 'el-icon-upload2', type: 'success', auth: '/device_management/device_consumables/device_consumables_items/import', onClick: this.openImport },
        { key: 'export', label: this.key('export'), icon: 'el-icon-download', type: 'primary', auth: '/device_management/device_consumables/device_consumables_items/export', onClick: this.handleExport }
      ],
      row: [
        { key: 'edit', label: this.key('edit'), icon: 'el-icon-edit', auth: '/device_management/device_consumables/device_consumables_items/edit', onClick: this.openEdit },
        { key: 'delete', label: this.key('delete'), icon: 'el-icon-delete', color: 'danger', auth: '/device_management/device_consumables/device_consumables_items/delete', onClick: this.handleDelete }
      ]
    }, this.$permission)
    this.toolbarButtons = btns.toolbarButtons
    this.rowButtons = btns.rowButtons
    this.initOptions()
    this.fetchData()
  },
  methods: {
    async initOptions () {
      const [devices, categories, units] = await Promise.all([getEquipmentCategoryALL({}), getConsumablesCategoryAll({}), getUnitAll({})])
      this.deviceCategoryOptions = toOptions((devices && devices.data) || devices)
      this.consumablesCategoryOptions = toOptions((categories && categories.data) || categories)
      this.unitOptions = toOptions((units && units.data) || units)
    },
    onFormDeviceCategoryChange () {
      this.formData.device_consumables_category_id = ''
    },
    buildSearchParams () {
      const params = { ...this.search }
      if (!Array.isArray(params.create_time) || !params.create_time.length) delete params.create_time
      if (!Array.isArray(params.update_time) || !params.update_time.length) delete params.update_time
      return params
    },
    async fetchData () {
      this.loading = true
      try {
        const res = await getList({ ...this.buildSearchParams(), page_no: this.pagination.current, page_size: this.pagination.size })
        const page = readPageData(res)
        this.tableData = page.list
        this.pagination.total = page.total
      } finally { this.loading = false }
    },
    onSearch () { this.pagination.current = 1; this.fetchData() },
    onReset () { this.search = { device_category_id: '', device_consumables_category_id: '', code: '', name: '', create_time: [], update_time: [] }; this.pagination.current = 1; this.fetchData() },
    onPageChange (page) { this.pagination.current = page.current; this.pagination.size = page.size; this.fetchData() },
    resetForm () { this.formData = { device_category_id: '', device_consumables_category_id: '', code: '', name: '', standard_service_life: 0, warning_service_life: 0, unit_id: '', remark: '' }; this.editId = '' },
    openAdd () { this.handleType = 'create'; this.dialogTitle = this.key('add_title'); this.resetForm(); this.dialogVisible = true },
    openEdit (row) {
      this.handleType = 'edit'; this.dialogTitle = this.key('edit_title'); this.editId = row.id
      this.formData = { device_category_id: row.device_category_id || '', device_consumables_category_id: row.device_consumables_category_id || '', code: row.code || '', name: row.name || '', standard_service_life: Number(row.standard_service_life || 0), warning_service_life: Number(row.warning_service_life || 0), unit_id: row.unit_id || '', remark: row.remark || '' }
      this.dialogVisible = true
    },
    validateLife () {
      if (Number(this.formData.standard_service_life) < Number(this.formData.warning_service_life)) {
        this.$message.error(this.$t(this.key('warning_life_not_greater_than_standard')))
        return false
      }
      return true
    },
    validateLifeRule (rule, value, callback) {
      if (Number(this.formData.standard_service_life) < Number(this.formData.warning_service_life)) {
        callback(new Error(this.$t(this.key('warning_life_not_greater_than_standard'))))
        return
      }
      callback()
    },
    async onDialogSubmit () {
      if (!this.validateLife()) return
      this.submitting = true
      try {
        if (this.handleType === 'create') await createItem(this.formData)
        else await editItem({ ...this.formData, id: this.editId })
        this.$message.success(this.$t(this.key('operation_success')))
        this.dialogVisible = false
        this.fetchData()
      } finally { this.submitting = false }
    },
    async handleDelete (row) {
      const cancelled = await this.$confirmAction({ message: this.key('confirm_delete'), title: this.key('tip'), confirmButtonText: this.key('confirm'), cancelButtonText: this.key('cancel') }, () => deleteItem({ id: [row.id] }))
      if (cancelled) return
      this.$message.success(this.$t(this.key('operation_success')))
      this.fetchData()
    },
    async handleBatchDelete () {
      if (!this.selectedRows.length) { this.$message.error(this.$t(this.key('please_select_data'))); return }
      const cancelled = await this.$confirmAction({ message: this.key('confirm_batch_delete'), title: this.key('tip'), confirmButtonText: this.key('confirm'), cancelButtonText: this.key('cancel') }, () => deleteItem({ id: this.selectedRows.map(item => item.id) }))
      if (cancelled) return
      this.$message.success(this.$t(this.key('operation_success')))
      this.fetchData()
    },
    async handleExport () {
      const cancelled = await this.$confirmAction({ message: this.key('confirm_export'), title: this.key('tip'), confirmButtonText: this.key('confirm'), cancelButtonText: this.key('cancel') }, () => createExportTask({ ...this.buildSearchParams(), action: 'download' }))
      if (cancelled) return
      this.$message.success(this.$t(this.key('create_download_task_success')))
    },
    openImport () { this.importFileList = []; this.importRows = []; this.importVisible = true },
    async downloadTemplate () { this.importLoading = true; try { const res = await getImportTemplate({}); downloadRename(res, 'xlsx', this.$t(this.key('import_template_name'))) } finally { this.importLoading = false } },
    async onImportFileChange (file) {
      if (!file || !/\.(xls|xlsx)$/i.test(file.name)) { this.$message.error(this.$t(this.key('file_format_error'))); return }
      this.importFileList = [file]
      this.importTableLoading = true
      try {
        const rows = await readExcel(file.raw)
        const headers = ['consumables_item_code', 'consumables_item_name', 'device_consumables_category_name', 'device_category', 'standard_service_life', 'warning_service_life', 'service_life_unit', 'remark'].map(k => this.$t(this.key(k)))
        if (rows.length && headers.some(title => !Object.prototype.hasOwnProperty.call(rows[0], title))) {
          this.$message.error(this.$t(this.key('file_column_missing'), { title: headers.find(title => !Object.prototype.hasOwnProperty.call(rows[0], title)) }))
          this.importRows = []
          return
        }
        this.importRows = rows.map(row => ({ code: row[headers[0]], name: row[headers[1]], device_consumables_category_name: row[headers[2]], device_category_name: row[headers[3]], standard_service_life: row[headers[4]], warning_service_life: row[headers[5]], unit_name: row[headers[6]], remark: row[headers[7]] }))
      } finally { this.importTableLoading = false }
    },
    async submitImport () {
      if (!this.importRows.length) { this.$message.error(this.$t(this.key('please_import_data'))); return }
      await importData({ import_data: JSON.stringify(this.importRows) })
      this.$message.success(this.$t(this.key('operation_success')))
      this.importVisible = false
      this.fetchData()
    }
  }
}
</script>

<style scoped>
.search-bar { padding: 10px 0; }
.import-upload { margin: 12px 0; }
/deep/ .el-form-item--mini.el-form-item { margin-bottom: 4px; }
</style>
