<script lang="ts" setup>
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import * as BomApi from '@/api/pms/bom'
import { CommonBomMaterialApi, type CommonBomMaterialVO } from '@/api/pms/commonbommaterial'
import { useTreeStore } from '@/store/modules/treeStore'
import BomForm from './BomForm.vue'
import DeviceCategoryTree from '@/components/DeviceCategoryTree/index.vue'
import MaterialList from '@/views/pms/bom/MaterialList.vue'
import MaterialListDrawer from '@/views/pms/bom/MaterialListDrawer.vue'

defineOptions({ name: 'Bom' })

type BomRow = Omit<BomApi.BomVO, 'id'> & {
  id: number
  children?: BomRow[]
  deviceCategoryName?: string
  materials?: number
}

type FormActionType = 'create' | 'update'

const { t } = useI18n()
const message = useMessage()
const treeStore = useTreeStore()
const { ZmTable, ZmTableColumn } = useTableComponents<BomRow>()

const initQuery: BomApi.BomListTreeReqVO = {
  pageNo: 1,
  pageSize: 10,
  deviceCategoryId: undefined,
  name: undefined,
  status: undefined
}

const queryParams = reactive<BomApi.BomListTreeReqVO>({ ...initQuery })
const queryFormRef = ref()
const loading = ref(false)
const isExpandAll = ref(true)
const refreshTable = ref(true)
const list = ref<BomRow[]>([])
const total = ref(0)
const selectedRow = ref<BomRow>()
const parentId = ref<number>()
const currentBomNodeId = ref<number>()
const drawerVisible = ref(false)
const showDrawer = ref()
const materialListRef = ref()
const formRef = ref()

const currentRowInfo = ref({
  deviceCategoryName: '',
  bomNodeName: ''
})

const commonBomMaterialData = ref<Partial<CommonBomMaterialVO>>({
  id: undefined,
  deviceCategoryId: undefined,
  bomNodeId: undefined,
  name: undefined,
  code: undefined,
  materialId: undefined,
  quantity: undefined
})

const selectedId = computed(() => treeStore.selectedId)
const activeRowId = computed(() => selectedRow.value?.id)

const normalizeListTreeResult = (data: BomRow[] | PageResult<BomRow[]>) => {
  if (Array.isArray(data)) {
    return {
      list: data,
      total: data.length
    }
  }

  return {
    list: data?.list || [],
    total: data?.total || 0
  }
}

const hasBomType = (row: BomRow, type: number) => {
  return row.type?.some((item) => Number(item) === type) || false
}

/** 查询 BOM 树列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await BomApi.getBomListTree(queryParams)
    const result = normalizeListTreeResult(data)
    list.value = result.list
    total.value = result.total
  } finally {
    loading.value = false
  }
}

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

const resetQuery = () => {
  Object.assign(queryParams, { ...initQuery })
  queryFormRef.value?.resetFields()
  clearRowSelection()
  handleQuery()
}

const handleSizeChange = (val: number) => {
  queryParams.pageSize = val
  handleQuery()
}

const handleCurrentChange = (val: number) => {
  queryParams.pageNo = val
  getList()
}

const handleDeviceCategoryTreeNodeClick = async (row: Tree) => {
  clearRowSelection()
  treeStore.setSelectedId(row.id)
  queryParams.deviceCategoryId = row.id
  queryParams.pageNo = 1
  await getList()
}

const handleClick = (row: BomRow) => {
  parentId.value = row.id
  selectedRow.value = row
}

const clearRowSelection = () => {
  selectedRow.value = undefined
  parentId.value = undefined
}

const getCurrentDeviceCategoryId = (row?: BomRow | null) => {
  return row?.deviceCategoryId || selectedRow.value?.deviceCategoryId || selectedId.value
}

const openForm = (type: FormActionType, row?: BomRow | null) => {
  if (!formRef.value?.open) return

  if (type === 'create') {
    const targetParentId = selectedRow.value?.id || parentId.value
    const targetDeviceCategoryId = getCurrentDeviceCategoryId(row)
    formRef.value.open(type, undefined, targetParentId, targetDeviceCategoryId)
    return
  }

  if (row) {
    treeStore.setSelectedId(row.deviceCategoryId)
    formRef.value.open(type, row.id, row.parentId, row.deviceCategoryId)
    return
  }

  message.warning('请选择需要修改的BOM节点')
}

const toggleExpandAll = () => {
  refreshTable.value = false
  isExpandAll.value = !isExpandAll.value
  nextTick(() => {
    refreshTable.value = true
  })
}

const openSelectMaterialForm = (row: BomRow) => {
  if (!materialListRef.value?.open) return
  currentBomNodeId.value = row.id
  commonBomMaterialData.value.deviceCategoryId = row.deviceCategoryId
  materialListRef.value.open(row)
}

const handleView = async (row: BomRow) => {
  if (!showDrawer.value?.openDrawer) return
  currentBomNodeId.value = row.id
  currentRowInfo.value = {
    deviceCategoryName: row.deviceCategoryName || '暂无',
    bomNodeName: row.name || '暂无'
  }
  drawerVisible.value = true
  await nextTick()
  showDrawer.value.openDrawer()
  await showDrawer.value.loadMaterials(row.id)
}

const chooseMaterial = async (selectedMaterials: CommonBomMaterialVO[]) => {
  if (!selectedMaterials.length) {
    message.warning('请至少选择一个物料')
    return
  }

  const invalidMaterial = selectedMaterials.find(
    (material) => !material.quantity || material.quantity <= 0
  )
  if (invalidMaterial) {
    message.warning('请填写大于0的物料数量')
    return
  }

  try {
    const materialsData = selectedMaterials.map((material) => ({
      deviceCategoryId: commonBomMaterialData.value.deviceCategoryId,
      bomNodeId: currentBomNodeId.value,
      materialId: material.id,
      name: material.name,
      code: material.code,
      quantity: material.quantity
    }))

    const resultCount = await CommonBomMaterialApi.addMaterials(materialsData)
    message.success(`成功添加物料数量：${resultCount}`)
    showDrawer.value?.loadMaterials(currentBomNodeId.value)
    await getList()
  } catch (error) {
    message.error('添加物料失败！')
  }
}

const handleDrawerClosed = () => {
  getList()
}

const handleDelete = async (id: number) => {
  try {
    const targetNode = findNodeById(list.value, id)

    if (targetNode?.children?.length) {
      message.error('当前BOM节点包含子节点，不可删除')
      return
    }

    await message.delConfirm()
    await BomApi.deleteBomNode(id)
    message.success(t('common.delSuccess'))
    await getList()
  } catch {}
}

const findNodeById = (nodes: BomRow[], id: number): BomRow | undefined => {
  for (const node of nodes) {
    if (node.id === id) return node

    if (node.children?.length) {
      const foundInChildren = findNodeById(node.children, id)
      if (foundInChildren) return foundInChildren
    }
  }

  return undefined
}

onMounted(() => {
  getList()
})
</script>

<template>
  <div
    class="grid grid-cols-[auto_1fr] grid-rows-[auto_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
    <DeviceCategoryTree
      v-model="queryParams.deviceCategoryId"
      :show-title="false"
      class="row-span-2"
      @node-click="handleDeviceCategoryTreeNodeClick" />

    <el-form
      ref="queryFormRef"
      :model="queryParams"
      size="default"
      label-width="110px"
      class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 py-3 gap-6 flex items-center justify-between flex-wrap min-w-0">
      <div class="flex items-center gap-6 flex-wrap">
        <el-form-item label="BOM节点名称" prop="name">
          <el-input
            v-model="queryParams.name"
            placeholder="请输入BOM节点名称"
            clearable
            class="!w-220px"
            @keyup.enter="handleQuery" />
        </el-form-item>
        <el-form-item label="BOM节点" prop="status">
          <el-select
            v-model="queryParams.status"
            placeholder="请选择BOM节点"
            clearable
            class="!w-180px">
            <el-option
              v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value" />
          </el-select>
        </el-form-item>
      </div>

      <el-form-item class="bom-query-actions">
        <el-button type="primary" @click="handleQuery">
          <Icon icon="ep:search" class="mr-5px" />搜索
        </el-button>
        <el-button @click="resetQuery"> <Icon icon="ep:refresh" class="mr-5px" />重置 </el-button>
        <el-button
          type="primary"
          plain
          @click="openForm('create')"
          v-hasPermi="['rq:iot-bom:create']">
          <Icon icon="ep:plus" class="mr-5px" />新增
        </el-button>
        <el-button type="danger" plain @click="toggleExpandAll">
          <Icon icon="ep:sort" class="mr-5px" />展开/折叠
        </el-button>
      </el-form-item>
    </el-form>

    <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg flex flex-col p-4 min-w-0">
      <div class="flex-1 relative min-h-0">
        <el-auto-resizer class="absolute">
          <template #default="{ width, height }">
            <ZmTable
              v-if="refreshTable"
              :data="list"
              :loading="loading"
              :width="width"
              :height="height"
              :max-height="height"
              :default-expand-all="isExpandAll"
              row-key="id"
              show-border
              :row-class-name="({ row }) => (row.id === activeRowId ? 'is-active-bom-row' : '')"
              @row-click="handleClick">
              <ZmTableColumn prop="name" label="BOM节点" min-width="180" align="left" fixed="left">
                <template #default="{ row }">
                  <el-tooltip
                    effect="dark"
                    :content="`设备分类：${row.deviceCategoryName || '暂无'}`"
                    placement="top-start"
                    :disabled="!row.deviceCategoryName">
                    <span class="bom-node-name">{{ row.name }}</span>
                  </el-tooltip>
                </template>
              </ZmTableColumn>
              <ZmTableColumn prop="deviceCategoryName" label="设备分类" min-width="140" />
              <ZmTableColumn label="维修" width="90">
                <template #default="{ row }">
                  <el-switch :model-value="hasBomType(row, 1)" disabled />
                </template>
              </ZmTableColumn>
              <ZmTableColumn label="保养" width="90">
                <template #default="{ row }">
                  <el-switch :model-value="hasBomType(row, 2)" disabled />
                </template>
              </ZmTableColumn>
              <ZmTableColumn prop="sort" label="排序" width="80" />
              <ZmTableColumn prop="materials" label="物料数量" width="100" />
              <ZmTableColumn
                label="操作"
                width="300"
                fixed="right"
                :show-overflow-tooltip="false"
                action>
                <template #default="{ row }">
                  <el-button
                    link
                    type="primary"
                    @click.stop="openForm('update', row)"
                    v-hasPermi="['rq:iot-bom:update']">
                    <Icon icon="ep:edit" class="mr-4px" />
                    修改
                  </el-button>
                  <el-button
                    link
                    type="primary"
                    @click.stop="openSelectMaterialForm(row)"
                    v-hasPermi="['rq:iot-bom:update']">
                    <Icon icon="ep:plus" class="mr-4px" />
                    添加物料
                  </el-button>
                  <el-button
                    link
                    type="primary"
                    @click.stop="handleView(row)"
                    v-hasPermi="['rq:iot-bom:update']">
                    <Icon icon="ep:view" class="mr-4px" />
                    物料详情
                  </el-button>
                  <el-button
                    link
                    type="danger"
                    @click.stop="handleDelete(row.id)"
                    v-hasPermi="['rq:iot-bom:delete']">
                    <Icon icon="ep:delete" class="mr-4px" />
                    删除
                  </el-button>
                </template>
              </ZmTableColumn>
            </ZmTable>
          </template>
        </el-auto-resizer>
      </div>

      <div class="h-8 mt-2 flex items-center justify-end">
        <el-pagination
          v-show="total > 0"
          size="default"
          :current-page="queryParams.pageNo"
          :page-size="queryParams.pageSize"
          :background="true"
          :page-sizes="[10, 20, 30, 50, 100]"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange" />
      </div>
    </div>
  </div>

  <BomForm ref="formRef" :category_id="selectedId" @success="getList" />
  <MaterialList ref="materialListRef" @choose="chooseMaterial" />
  <MaterialListDrawer
    ref="showDrawer"
    :model-value="drawerVisible"
    :node-id="currentBomNodeId"
    :row-info="currentRowInfo"
    @update:model-value="(val) => (drawerVisible = val)"
    @refresh="handleDrawerClosed" />
</template>

<style scoped>
:deep(.el-form-item) {
  margin-bottom: 0;
}

.bom-node-name {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bom-query-actions {
  margin-left: auto;
}

:deep(.is-active-bom-row .el-table__cell) {
  background-color: var(--el-color-primary-light-9) !important;
}
</style>
