<template>
  <div class="device-bom-library">
    <section class="library-workbench">
      <el-form
        ref="queryFormRef"
        :model="queryParams"
        inline
        size="default"
        class="library-workbench__header">
        <div class="library-header-main">
          <div class="workbench-title">
            <span class="workbench-title__icon">
              <Icon icon="ep:box" />
            </span>
            <div>
              <h3>设备BOM清单</h3>
            </div>
          </div>

          <el-form-item label="BOM节点名称" prop="name">
            <el-input
              v-model="queryParams.name"
              class="library-search-input"
              clearable
              placeholder="请输入BOM节点名称"
              @keyup.enter="handleQuery">
              <template #prefix>
                <Icon icon="ep:search" />
              </template>
            </el-input>
          </el-form-item>
          <el-form-item label="BOM节点" prop="nodeId">
            <el-tree-select
              v-model="selectedNodeId"
              class="library-search-input"
              :data="nodeOptions"
              :props="{ label: 'name', children: 'children' }"
              check-strictly
              clearable
              filterable
              node-key="id"
              placeholder="请选择BOM节点" />
          </el-form-item>
        </div>

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

      <div class="library-table-wrap">
        <el-auto-resizer>
          <template #default="{ width, height }">
            <ZmTable
              v-if="refreshTable"
              :data="displayList"
              class="library-table"
              :loading="loading"
              :width="width"
              :height="height"
              :max-height="height"
              :default-expand-all="isExpandAll"
              :column-max-width="420"
              row-key="id"
              empty-text="暂无数据"
              show-border>
              <ZmTableColumn prop="name" label="BOM节点" min-width="180" align="left" fixed="left">
                <template #default="{ row }">
                  <el-tooltip
                    effect="dark"
                    :content="`设备分类：${row.deviceCategoryName || props.deviceCategoryName || '暂无'}`"
                    placement="top-start"
                    :disabled="!row.deviceCategoryName && !props.deviceCategoryName">
                    <span class="bom-node-name">{{ row.name || '-' }}</span>
                  </el-tooltip>
                </template>
              </ZmTableColumn>
              <ZmTableColumn prop="deviceCategoryName" label="设备分类" min-width="140">
                <template #default="{ row }">
                  {{ row.deviceCategoryName || props.deviceCategoryName || '-' }}
                </template>
              </ZmTableColumn>
              <ZmTableColumn prop="sort" label="排序" width="80" />
              <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="materials" label="物料数量" width="100">
                <template #default="{ row }">
                  {{ row.materials ?? 0 }}
                </template>
              </ZmTableColumn>
              <ZmTableColumn label="操作" width="320" fixed="right" action>
                <template #default="{ row }">
                  <div class="table-actions">
                    <el-button
                      v-hasPermi="['rq:iot-bom:update']"
                      link
                      type="primary"
                      class="table-action-btn"
                      @click="openForm('update', row)">
                      <Icon icon="ep:edit" />
                      修改
                    </el-button>
                    <el-button
                      v-hasPermi="['rq:iot-bom:update']"
                      link
                      type="primary"
                      class="table-action-btn"
                      @click="openSelectMaterialForm(row)">
                      <Icon icon="ep:plus" />
                      添加物料
                    </el-button>
                    <el-button
                      v-hasPermi="['rq:iot-bom:update']"
                      link
                      type="primary"
                      class="table-action-btn"
                      @click="handleView(row)">
                      <Icon icon="ep:document" />
                      物料详情
                    </el-button>
                    <el-button
                      v-hasPermi="['rq:iot-bom:delete']"
                      link
                      type="danger"
                      class="table-action-btn"
                      @click="handleDelete(row.id)">
                      <Icon icon="ep:delete" />
                      删除
                    </el-button>
                  </div>
                </template>
              </ZmTableColumn>
            </ZmTable>
          </template>
        </el-auto-resizer>
      </div>
    </section>

    <BomFormDevice ref="formRef" :device-id="props.deviceId" @success="getList" />
    <MaterialList ref="materialListRef" @choose="chooseMaterial" />
    <MaterialListDrawerDevice
      ref="showDrawer"
      :model-value="drawerVisible"
      :node-id="currentBomNodeId"
      :device-id="props.deviceId"
      :row-info="currentRowInfo"
      @update:model-value="(val) => (drawerVisible = val)"
      @refresh="getList" />
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, reactive, ref, watch } from 'vue'
import * as BomApi from '@/api/pms/devicebom'
import * as MaterialApi from '@/api/pms/iotdevicematerial'
import { handleTree } from '@/utils/tree'
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
import BomFormDevice from '@/views/pms/device/bom/BomFormDevice.vue'
import MaterialList from '@/views/pms/bom/MaterialList.vue'
import MaterialListDrawerDevice from '@/views/pms/device/MaterialListDrawerDevice.vue'

defineOptions({ name: 'DeviceBomLibrary' })

interface BomNode {
  id?: number
  parentId?: number
  deviceCategoryId?: number
  deviceCategoryName?: string
  name?: string
  sort?: number
  type?: string | number[]
  materials?: number
  children?: BomNode[]
}

interface MaterialItem {
  id: number
  name?: string
  code?: string
  quantity?: number
}

const props = defineProps<{
  deviceId?: number
  deviceCategoryName?: string
}>()

const { ZmTable, ZmTableColumn } = useTableComponents<BomNode>()
const message = useMessage()
const loading = ref(false)
const isExpandAll = ref(true)
const refreshTable = ref(true)
const list = ref<BomNode[]>([])
const selectedNodeId = ref<number>()
const queryFormRef = ref()
const formRef = ref()
const materialListRef = ref()
const showDrawer = ref()
const drawerVisible = ref(false)
const currentBomNodeId = ref<number>()
const currentRowInfo = ref({
  deviceCategoryName: '',
  bomNodeName: ''
})

const commonBomMaterialData = ref({
  deviceCategoryId: undefined as number | undefined
})

const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  name: undefined as string | undefined,
  status: undefined as number | undefined,
  deviceId: undefined as number | undefined
})

const nodeOptions = computed(() => list.value)

const findNodeById = (nodes: BomNode[], id?: number): BomNode | undefined => {
  if (!id) return undefined
  for (const node of nodes) {
    if (node.id === id) return node
    const child = findNodeById(node.children || [], id)
    if (child) return child
  }
  return undefined
}

const displayList = computed(() => {
  if (!selectedNodeId.value) return list.value
  const node = findNodeById(list.value, selectedNodeId.value)
  return node ? [node] : []
})

const getList = async () => {
  if (!props.deviceId) return

  loading.value = true
  queryParams.deviceId = props.deviceId
  try {
    const data = await BomApi.IotDeviceBomApi.getIotDeviceBomList(queryParams)
    list.value = data ? handleTree(data) : []
  } finally {
    loading.value = false
  }
}

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

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

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

const hasBomType = (row: BomNode, type: number) => {
  if (Array.isArray(row.type)) return row.type.includes(type)
  return String(row.type || '')
    .split(',')
    .includes(String(type))
}

const openForm = (type: string, row: BomNode | null) => {
  formRef.value?.open(type, row?.id || null)
}

const openSelectMaterialForm = (row: BomNode) => {
  const rowWithCategory = {
    ...row,
    deviceCategoryName: props.deviceCategoryName
  }
  materialListRef.value?.open(rowWithCategory)
  currentBomNodeId.value = row.id
  commonBomMaterialData.value.deviceCategoryId = row.deviceCategoryId
}

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

const chooseMaterial = async (selectedMaterials: MaterialItem[]) => {
  if (!currentBomNodeId.value) return

  try {
    const materialsData = selectedMaterials.map((material) => ({
      deviceCategoryId: commonBomMaterialData.value.deviceCategoryId,
      deviceId: props.deviceId,
      bomNodeId: currentBomNodeId.value,
      materialId: material.id,
      name: material.name,
      code: material.code,
      quantity: material.quantity
    }))
    const resultCount = await MaterialApi.IotDeviceMaterialApi.addMaterials(materialsData)
    message.success(`成功添加物料数量：${resultCount}`)
    await showDrawer.value?.loadMaterials(currentBomNodeId.value)
    await getList()
  } catch {
    message.error('添加物料失败！')
  }
}

const handleDelete = async (id?: number) => {
  if (!id) return

  const targetNode = findNodeById(list.value, id)
  if (targetNode?.children?.length) {
    message.error('当前BOM节点包含子节点，不可删除')
    return
  }

  try {
    await message.delConfirm()
    await BomApi.IotDeviceBomApi.deleteIotDeviceBom(id)
    message.success('删除成功')
    await getList()
  } catch {}
}

watch(
  () => props.deviceId,
  () => {
    getList()
  },
  { immediate: true }
)
</script>

<style scoped lang="scss">
.device-bom-library {
  display: grid;
  gap: 14px;
}

.library-workbench {
  padding: 14px;
  overflow: hidden;
  background: linear-gradient(180deg, #f8fbff 0, var(--el-bg-color) 96px), var(--el-bg-color);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 8px;
}

.library-workbench__header {
  display: flex;
  gap: 16px;
  min-height: 56px;
  margin-bottom: 14px;
  align-items: center;
  justify-content: space-between;

  :deep(.el-form-item) {
    margin-right: 10px;
    margin-bottom: 0;
  }

  :deep(.el-form-item:last-child) {
    margin-right: 0;
  }

  :deep(.el-button .app-iconify) {
    margin-right: 4px;
  }
}

.library-header-main {
  display: flex;
  gap: 10px;
  min-width: 0;
  align-items: center;
  flex: 1;
  flex-wrap: wrap;
}

.workbench-title {
  display: flex;
  gap: 12px;
  min-width: 0;
  align-items: center;

  h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    line-height: 24px;
    color: var(--el-text-color-primary);
  }
}

.workbench-title__icon {
  display: flex;
  width: 38px;
  height: 38px;
  font-size: 18px;
  color: #3478f6;
  background: #eaf2ff;
  border-radius: 10px;
  flex: none;
  align-items: center;
  justify-content: center;
}

.library-search-input {
  width: 220px;
}

.library-actions {
  flex: none;
}

.library-table-wrap {
  position: relative;
  height: 560px;
  min-width: 0;
}

.library-table {
  --el-table-header-bg-color: var(--el-fill-color-lighter);
  --el-table-row-hover-bg-color: #f6faff;

  overflow: hidden;
  border-radius: 8px;

  :deep(.el-table__cell) {
    padding: 9px 0;
  }
}

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

.table-actions {
  display: flex;
  gap: 4px;
  align-items: center;
  justify-content: center;
}

.table-action-btn {
  gap: 4px;

  :deep(.el-icon),
  :deep(.app-iconify) {
    margin-right: 2px;
  }
}

@media (width <= 767px) {
  .library-workbench__header {
    align-items: stretch;
    flex-direction: column;
  }

  .library-header-main {
    align-items: stretch;
    flex-direction: column;
  }

  .library-search-input {
    width: 100%;
  }
}
</style>
