<template>
  <d2-container>
    <template #header>
      <div class="search-bar">
        <el-form :inline="true" :model="search" size="mini">
          <el-form-item :label="$t(key('device_name'))">
            <el-select v-model="search.device_code" :placeholder="$t(key('select_device'))" clearable filterable style="width:220px">
              <el-option v-for="item in deviceOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
          <el-form-item :label="$t(key('consumable_code'))">
            <el-input v-model.trim="search.device_consumables_item_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('consumable_name'))">
            <el-input v-model.trim="search.device_consumables_item_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">
      <template #col-status="{ row }">
        <el-tag v-if="Number(row.status) === 0" size="mini">{{ $t(key('normal')) }}</el-tag>
        <el-tag v-else-if="Number(row.status) === 1" type="warning" size="mini">{{ $t(key('near_standard_life')) }}</el-tag>
        <el-tag v-else-if="Number(row.status) === 2" type="danger" size="mini">{{ $t(key('exceed_standard_life')) }}</el-tag>
        <el-tag v-else type="info" size="mini">-</el-tag>
      </template>
    </page-table>

    <page-dialog-form ref="dialogForm" :visible.sync="dialogVisible" :title="dialogTitle" width="620px" :form-cols="formCols" :form-data="formData" :rules="activeRules" 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="820px" :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="320" size="mini">
        <el-table-column prop="device_consumables_item_name" :label="$t(key('device_consumables_item'))" min-width="160" />
        <el-table-column prop="device_name" :label="$t(key('related_device'))" min-width="160" />
        <el-table-column prop="device_consumables_lifetime" :label="$t(key('used_life'))" min-width="130" />
        <el-table-column prop="remark" :label="$t(key('remark'))" min-width="140" />
      </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 { getAll as getDeviceAll } from '@/api/equipment-management/equipment-registry'
import { getAll as getConsumablesItemsAll } from '@/api/equipment-management/consumables-items'
import { getList, createItem, editItem, deleteItem, createExportTask, getImportTemplate, importData } from '@/api/equipment-management/consumables-lifecycle'
import { createItem as createReplaceLog } from '@/api/equipment-management/replacement-logs'

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 = 'code') {
  return (Array.isArray(list) ? list : []).map(item => ({ label: item[label], value: item[value], raw: item }))
}

export default {
  name: 'equipment-management-consumables-lifecycle',
  components: { PageTable, PageDialogForm },
  mixins: [i18nMixin('page.equipment_management.consumables_management.consumables_lifecycle'), confirmMixin],
  data () {
    return {
      loading: false,
      submitting: false,
      tableData: [],
      selectedRows: [],
      search: { device_code: '', device_consumables_item_code: '', device_consumables_item_name: '', create_time: [], update_time: [] },
      pagination: { current: 1, size: 10, total: 0 },
      dialogVisible: false,
      dialogTitle: '',
      handleType: 'create',
      editId: '',
      formData: { device_consumables_item_code: '', device_code: '', standard_service_life: 0, warning_service_life: 0, device_consumables_lifetime: 0, replace_user: '', replace_time: '', replace_reason: '', replacement_time: 0, remark: '' },
      consumablesItemOptions: [],
      deviceOptions: [],
      importVisible: false,
      importFileList: [],
      importRows: [],
      importLoading: false,
      importTableLoading: false,
      columns: [],
      toolbarButtons: [],
      rowButtons: []
    }
  },
  computed: {
    replaceReasonOptions () {
      return [
        { label: this.$t(this.key('replace_reason_abnormal')), value: this.$t(this.key('replace_reason_abnormal')) },
        { label: this.$t(this.key('replace_reason_normal')), value: this.$t(this.key('replace_reason_normal')) },
        { label: this.$t(this.key('replace_reason_exceed')), value: this.$t(this.key('replace_reason_exceed')) }
      ]
    },
    formCols () {
      const disabledBase = this.handleType !== 'create'
      const cols = [
        [{ type: 'select', prop: 'device_consumables_item_code', label: this.key('device_consumables_item'), placeholder: this.key('select_consumable'), options: this.consumablesItemOptions, disabled: disabledBase, style: { width: '100%' }, onChange: this.onConsumablesItemChange }],
        [{ type: 'select', prop: 'device_code', label: this.key('related_device'), placeholder: this.key('select_device'), options: this.deviceOptions, disabled: disabledBase, style: { width: '100%' } }],
        [{ type: 'input-number', prop: 'standard_service_life', label: this.key('standard_life'), min: 0, disabled: true, style: { width: '100%' } }],
        [{ type: 'input-number', prop: 'warning_service_life', label: this.key('warning_life'), min: 0, disabled: true, style: { width: '100%' } }]
      ]
      if (this.handleType === 'replace') {
        cols.push(
          [{ type: 'input', prop: 'replace_user', label: this.key('replace_user'), placeholder: this.key('input_replace_user'), style: { width: '100%' } }],
          [{ type: 'date-picker', prop: 'replace_time', label: this.key('replace_time'), placeholder: this.key('input_replace_time'), style: { width: '100%' } }],
          [{ type: 'select', prop: 'replace_reason', label: this.key('replace_reason'), placeholder: this.key('select_replace_reason'), options: this.replaceReasonOptions, style: { width: '100%' } }],
          [{ type: 'input-number', prop: 'replacement_time', label: this.key('replace_duration'), min: 0, style: { width: '100%' } }]
        )
      } else {
        cols.push([{ type: 'input-number', prop: 'device_consumables_lifetime', label: this.key('used_life'), min: 0, style: { width: '100%' } }])
      }
      cols.push([{ type: 'input', prop: 'remark', label: this.key('remark'), placeholder: this.key('enter_remark'), inputType: 'textarea', autosize: { minRows: 2, maxRows: 6 }, style: { width: '100%' } }])
      return cols
    },
    activeRules () {
      const rules = {
        device_code: [{ required: true, message: this.key('device_required'), trigger: 'change' }],
        device_consumables_item_code: [{ required: true, message: this.key('consumable_required'), trigger: 'change' }]
      }
      if (this.handleType === 'replace') {
        rules.replace_user = [{ required: true, message: this.key('input_replace_user'), trigger: 'blur' }]
        rules.replace_time = [{ required: true, message: this.key('input_replace_time'), trigger: 'change' }]
        rules.replace_reason = [{ required: true, message: this.key('replace_reason_required'), trigger: 'change' }]
        rules.replacement_time = [{ required: true, message: this.key('input_replace_duration'), trigger: 'blur' }]
      } else {
        rules.device_consumables_lifetime = [{ required: true, message: this.key('input_used_life'), trigger: 'blur' }]
      }
      return rules
    }
  },
  created () {
    this.columns = useTableColumns([
      { prop: 'sort', label: this.key('sort'), width: 80 },
      { prop: 'status', label: this.key('status'), slot: 'status', width: 120 },
      { prop: 'device_consumables_item_code', label: this.key('consumable_code'), minWidth: 150 },
      { prop: 'device_consumables_item_name', label: this.key('consumable_name'), minWidth: 150 },
      { prop: 'device_consumables_category_name', label: this.key('consumable_category'), minWidth: 150 },
      { prop: 'device_name', label: this.key('related_device'), minWidth: 150 },
      { 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: 'device_consumables_lifetime', label: this.key('used_life'), 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: 230, 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_lifetime_management/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_lifetime_management/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_lifetime_management/import', onClick: this.openImport },
        { key: 'export', label: this.key('export'), icon: 'el-icon-download', type: 'primary', auth: '/device_management/device_consumables/device_consumables_lifetime_management/export', onClick: this.handleExport }
      ],
      row: [
        { key: 'declare_lifetime', label: this.key('declare_lifetime'), icon: 'el-icon-edit', auth: '/device_management/device_consumables/device_consumables_lifetime_management/edit', onClick: this.openEdit },
        { key: 'replace', label: this.key('replace'), icon: 'el-icon-refresh', auth: '/device_management/device_consumables/device_consumables_lifetime_management/change', onClick: this.openReplace },
        { key: 'delete', label: this.key('delete'), icon: 'el-icon-delete', color: 'danger', auth: '/device_management/device_consumables/device_consumables_lifetime_management/delete', onClick: this.handleDelete }
      ]
    }, this.$permission)
    this.toolbarButtons = btns.toolbarButtons
    this.rowButtons = btns.rowButtons
    this.initOptions()
    this.fetchData()
  },
  methods: {
    async initOptions () {
      const [items, devices] = await Promise.all([getConsumablesItemsAll({}), getDeviceAll({})])
      this.consumablesItemOptions = toOptions((items && items.data) || items)
      this.deviceOptions = toOptions((devices && devices.data) || devices)
    },
    async onConsumablesItemChange (code) {
      const option = this.consumablesItemOptions.find(item => item.value === code)
      const row = option && option.raw ? option.raw : {}
      this.formData.standard_service_life = Number(row.standard_service_life || 0)
      this.formData.warning_service_life = Number(row.warning_service_life || 0)
      this.formData.device_code = ''
      if (row.device_category_id) {
        const res = await getDeviceAll({ device_category_id: row.device_category_id })
        this.deviceOptions = toOptions((res && res.data) || res)
      }
    },
    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_code: '', device_consumables_item_code: '', device_consumables_item_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_consumables_item_code: '', device_code: '', standard_service_life: 0, warning_service_life: 0, device_consumables_lifetime: 0, replace_user: '', replace_time: '', replace_reason: '', replacement_time: 0, remark: '' }; this.editId = '' },
    fillForm (row) {
      this.editId = row.id
      this.formData = { device_consumables_item_code: row.device_consumables_item_code || '', device_code: row.device_code || '', standard_service_life: Number(row.standard_service_life || 0), warning_service_life: Number(row.warning_service_life || 0), device_consumables_lifetime: Number(row.device_consumables_lifetime || 0), replace_user: row.replace_user || '', replace_time: row.replace_time || '', replace_reason: row.replace_reason || '', replacement_time: Number(row.replacement_time || 0), remark: row.remark || '' }
    },
    openAdd () { this.handleType = 'create'; this.dialogTitle = this.key('add_title'); this.resetForm(); this.dialogVisible = true },
    openEdit (row) { this.handleType = 'edit'; this.dialogTitle = this.key('declare_lifetime'); this.fillForm(row); this.dialogVisible = true },
    openReplace (row) { this.handleType = 'replace'; this.dialogTitle = this.key('replace'); this.fillForm(row); this.formData.replace_time = this.formData.replace_time || ''; this.dialogVisible = true },
    async onDialogSubmit () {
      this.submitting = true
      try {
        if (this.handleType === 'create') await createItem(this.formData)
        else if (this.handleType === 'edit') await editItem({ ...this.formData, id: this.editId })
        else await createReplaceLog({ ...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 = ['device_consumables_item', 'related_device', 'used_life', '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 => ({ device_consumables_item_name: row[headers[0]], device_name: row[headers[1]], device_consumables_lifetime: row[headers[2]], remark: row[headers[3]] }))
      } 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>
