<template>
  <Dialog
    v-model="dialogVisible"
    :title="t('iotMaintain.selectMaterials')"
    width="1200px"
    :close-on-click-modal="false"
    @close="handleClose">
    <div class="material-picker">
      <section class="context-panel">
        <div class="context-item">
          <span class="context-label">设备分类</span>
          <span class="context-value">{{ deviceCategoryName || '暂无' }}</span>
        </div>
        <div class="context-item">
          <span class="context-label">BOM节点</span>
          <span class="context-value">{{ bomNodeName || '暂无' }}</span>
        </div>
      </section>

      <section class="filter-panel">
        <el-form
          ref="queryFormRef"
          :model="queryParams"
          :inline="true"
          label-width="78px"
          size="default"
          class="filter-form">
          <el-form-item :label="t('workOrderMaterial.materialName')" prop="name">
            <el-input
              v-model="queryParams.name"
              :placeholder="t('workOrderMaterial.nameHolder')"
              clearable
              class="filter-input"
              @keyup.enter="handleQuery" />
          </el-form-item>
          <el-form-item :label="t('workOrderMaterial.materialCode')" prop="code">
            <el-input
              v-model="queryParams.code"
              :placeholder="t('workOrderMaterial.codeHolder')"
              clearable
              class="filter-input"
              @keyup.enter="handleQuery" />
          </el-form-item>
          <el-form-item class="filter-actions">
            <el-button type="primary" size="default" @click="handleQuery">
              <Icon icon="ep:search" class="mr-5px" />
              {{ t('workOrderMaterial.search') }}
            </el-button>
            <el-button size="default" @click="resetQuery">
              <Icon icon="ep:refresh" class="mr-5px" />
              {{ t('workOrderMaterial.reset') }}
            </el-button>
            <el-button type="success" size="default" @click="handleConfirm">
              <Icon icon="ep:check" class="mr-5px" />
              {{ t('workOrderMaterial.confirm') }}
            </el-button>
          </el-form-item>
        </el-form>
      </section>

      <section class="table-panel">
        <ZmTable
          ref="tableRef"
          :data="list"
          :loading="loading"
          :show-border="true"
          class="material-table"
          settings-cache-key="pms-bom-material-select"
          row-key="id"
          @row-click="handleRowClick"
          @selection-change="handleSelectionChange">
          <ZmTableColumn
            type="selection"
            width="56"
            :reserve-selection="true"
            hide-in-column-settings />
          <ZmTableColumn :label="t('workOrderMaterial.materialName')" prop="name" min-width="220" />
          <ZmTableColumn :label="t('workOrderMaterial.materialCode')" prop="code" min-width="160" />
          <ZmTableColumn :label="t('workOrderMaterial.unit')" prop="unit" width="110" />
          <ZmTableColumn :label="t('route.quantity')" prop="quantity" width="150">
            <template #default="{ row }">
              <el-input-number
                v-model="row.quantity"
                :controls="false"
                :min="0"
                :precision="2"
                size="default"
                class="quantity-input"
                @click.stop
                @focus="selectIfNeeded(row)"
                @change="() => syncSelectedQuantity(row)" />
            </template>
          </ZmTableColumn>
          <ZmTableColumn
            :label="t('deviceList.createTime')"
            prop="createTime"
            min-width="170"
            :formatter="dateFormatter" />
        </ZmTable>

        <div class="pagination-row">
          <Pagination
            :total="total"
            v-model:page="queryParams.pageNo"
            v-model:limit="queryParams.pageSize"
            @pagination="getList" />
        </div>
      </section>
    </div>
  </Dialog>
</template>

<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
import { dateFormatter } from '@/utils/formatTime'
import * as MaterialApi from '@/api/pms/material'

defineOptions({ name: 'MaterialList' })

type MaterialRow = Omit<MaterialApi.MaterialVO, 'quantity'> & {
  quantity?: number
}

const { t } = useI18n()
const { ZmTable, ZmTableColumn } = useTableComponents<MaterialRow>()
const emit = defineEmits<{
  (e: 'choose', value: MaterialApi.MaterialVO[]): void
  (e: 'close'): void
}>()

const dialogVisible = ref(false)
const loading = ref(false)
const queryFormRef = ref()
const tableRef = ref()
const list = ref<MaterialRow[]>([])
const total = ref(0)
const selectedRows = ref<MaterialRow[]>([])
const syncingSelection = ref(false)
const deviceCategoryName = ref('')
const bomNodeName = ref('')

const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  code: '',
  name: ''
})

const selectedIdSet = computed(() => new Set(selectedRows.value.map((item) => item.id)))

const getSelectedRow = (row: MaterialRow) => {
  return selectedRows.value.find((item) => item.id === row.id)
}

const normalizeQuantity = (quantity?: number) => {
  const value = Number(quantity)
  if (!Number.isFinite(value) || value <= 0) return undefined
  return Number(value.toFixed(2))
}

const applySelectedQuantities = () => {
  list.value.forEach((row) => {
    const selected = getSelectedRow(row)
    if (selected) {
      row.quantity = selected.quantity
    }
  })
}

const syncCurrentPageSelection = async () => {
  await nextTick()
  const elTableRef = tableRef.value?.elTableRef
  if (!elTableRef) return

  syncingSelection.value = true
  list.value.forEach((row) => {
    elTableRef.toggleRowSelection(row, selectedIdSet.value.has(row.id))
  })
  await nextTick()
  syncingSelection.value = false
}

const getList = async () => {
  loading.value = true
  try {
    const data = await MaterialApi.getMaterialPage(queryParams)
    list.value = data.list || []
    total.value = data.total || 0
    applySelectedQuantities()
    await syncCurrentPageSelection()
  } finally {
    loading.value = false
  }
}

const open = async (row: { deviceCategoryName?: string; name?: string }) => {
  deviceCategoryName.value = row.deviceCategoryName || ''
  bomNodeName.value = row.name || ''
  queryParams.pageNo = 1
  queryParams.name = ''
  queryParams.code = ''
  selectedRows.value = []
  tableRef.value?.elTableRef?.clearSelection()
  dialogVisible.value = true
  await getList()
}

defineExpose({ open })

const selectIfNeeded = (row: MaterialRow) => {
  if (!selectedIdSet.value.has(row.id)) {
    tableRef.value?.elTableRef?.toggleRowSelection(row, true)
  }
}

const syncSelectedQuantity = (row: MaterialRow) => {
  const selected = getSelectedRow(row)
  if (!selected) return
  const quantity = normalizeQuantity(row.quantity)
  selected.quantity = quantity
  row.quantity = quantity
}

const handleSelectionChange = (selection: MaterialRow[]) => {
  if (syncingSelection.value) return

  const currentPageIds = new Set(list.value.map((row) => row.id))
  const currentSelectionIds = new Set(selection.map((row) => row.id))
  const previousOtherPageRows = selectedRows.value.filter((row) => !currentPageIds.has(row.id))
  const currentPageRows = selection.map((row) => {
    const quantity = normalizeQuantity(row.quantity) || 1
    row.quantity = quantity
    return { ...row, quantity }
  })

  selectedRows.value = [...previousOtherPageRows, ...currentPageRows]
  list.value.forEach((row) => {
    if (!currentSelectionIds.has(row.id)) {
      row.quantity = undefined
    }
  })
}

const handleRowClick = (row: MaterialRow) => {
  tableRef.value?.elTableRef?.toggleRowSelection(row)
}

const handleQuery = () => {
  queryParams.pageNo = 1
  getList()
}

const resetQuery = () => {
  queryFormRef.value?.resetFields()
  handleQuery()
}

const handleConfirm = () => {
  if (!selectedRows.value.length) {
    ElMessage.warning('请至少选择一个物料')
    return
  }

  const invalidMaterial = selectedRows.value.find((item) => !normalizeQuantity(item.quantity))
  if (invalidMaterial) {
    ElMessage.warning('请填写大于0的物料数量')
    return
  }

  emit(
    'choose',
    selectedRows.value.map((row) => ({
      ...row,
      quantity: normalizeQuantity(row.quantity)
    })) as MaterialApi.MaterialVO[]
  )
  dialogVisible.value = false
}

const handleClose = () => {
  selectedRows.value = []
  list.value = []
  emit('close')
}
</script>

<style lang="scss" scoped>
.material-picker {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.context-panel,
.filter-panel,
.table-panel {
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
}

.context-panel {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  padding: 14px 16px;
  background: var(--el-fill-color-lighter);
}

.context-item {
  min-width: 0;
}

.context-label {
  margin-right: 10px;
  font-size: 13px;
  color: var(--el-text-color-secondary);
}

.context-value {
  font-size: 14px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.filter-panel {
  padding: 16px 16px 0;
  background: var(--el-bg-color);
}

.filter-form {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 0 12px;
}

.filter-input {
  width: 200px;
}

.filter-actions {
  margin-left: auto;
}

.table-panel {
  padding: 16px 16px 0;
  background: var(--el-bg-color);
}

.material-table {
  width: 100%;
}

.quantity-input {
  width: 96px;
}

.quantity-input :deep(.el-input__inner) {
  text-align: center;
}

.pagination-row {
  display: flex;
  justify-content: flex-end;
  padding: 12px 0 0;
}

@media (width <= 768px) {
  .context-panel {
    grid-template-columns: minmax(0, 1fr);
  }

  .filter-actions {
    width: 100%;
    margin-left: 0;
  }
}
</style>
