<template>
  <ElDialog
    v-model="dialogVisible"
    :title="editForm.id ? '编辑共享库存组' : '新增共享库存组'"
    width="800px"
    :close-on-click-modal="false"
    destroy-on-close
  >
    <ElForm ref="editFormRef" :model="editForm" label-width="100px">
      <div class="section-title">分组基础信息</div>
      <ElFormItem
        label="库存组名称"
        prop="groupName"
        :rules="[
          { required: true, message: '请输入库存组名称', trigger: 'blur' },
        ]"
      >
        <ElInput
          v-model="editForm.groupName"
          clearable
          placeholder="请输入库存组名称"
          style="width: 100%"
        />
      </ElFormItem>
      <ElFormItem
        label="状态"
        prop="status"
        :rules="[{ required: true, message: '请选择状态', trigger: 'blur' }]"
      >
        <ElSwitch
          v-model="editForm.status"
          :active-value="true"
          :inactive-value="false"
          style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
        />
      </ElFormItem>

      <div class="section-title">组内SPU清单</div>
      <div class="spu-search-bar">
        <ElSelect
          v-model="editForm.warehouseId"
          placeholder="请选择仓库"
          style="width: 160px"
          clearable
        >
          <ElOption
            v-for="item in warehouseList"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          />
        </ElSelect>
        <ElInput
          v-model="spuSearchKeyword"
          clearable
          placeholder="请输入库存SPU"
          style="width: 200px"
          @keyup.enter="handleSearchSpu"
        />
        <ElPopover
          v-model:visible="popoverVisible"
          placement="bottom-start"
          :width="600"
          trigger="manual"
          popper-class="spu-search-popover"
        >
          <template #reference>
            <ElButton type="primary" @click="handleSearchSpu"> 查询 </ElButton>
          </template>
          <div class="popover-table">
            <TableView
              :paginated-data="spuSearchResultList"
              :columns="spuSearchTableColumns"
              size="small"
            >
              <template #spuImage="{ row }">
                <ImageView :src="row.skuImage" width="40px" height="40px" />
              </template>
              <template #operation="{ row }">
                <ElButton
                  type="success"
                  circle
                  size="small"
                  @click="handleAddSpu(row)"
                >
                  <ElIcon><Plus /></ElIcon>
                </ElButton>
              </template>
            </TableView>
          </div>
        </ElPopover>
      </div>
      <div class="spu-drag-tip">
        <el-icon style="color: #409eff; font-size: 16px"><Warning /></el-icon
        ><span>拖动SPU调整扣减顺序</span>
      </div>
      <div
        class="spu-table-wrapper"
        @dragstart="handleRowDragStart"
        @dragover.prevent
        @drop="handleRowDrop"
        @dragend="handleRowDragEnd"
      >
        <TableView
          ref="spuTableRef"
          :paginated-data="editForm.spuList ?? []"
          :columns="spuTableColumns"
          row-key="warehouseSpu"
          size="small"
        >
          <template #sortNo="{ row }">
            {{ row.sortOrder }}
          </template>
          <template #spuImage="{ row }">
            <ImageView :src="row.skuImage" width="40px" height="40px" />
          </template>
          <template #operation="{ index, row }">
            <ElButton link type="danger" @click="handleRemoveSpu(index, row)">
              删除
            </ElButton>
          </template>
        </TableView>
      </div>
    </ElForm>
    <template #footer>
      <div class="dialog-footer">
        <ElButton @click="handleCancel">取消</ElButton>
        <ElButton type="primary" @click="handleSave"> 保存 </ElButton>
      </div>
    </template>
  </ElDialog>
</template>
<script setup lang="ts">
import {
  addSharedInventoryGroupApi,
  getQuerySpuApi,
  updateSharedInventoryGroupApi,
} from '@/api/warehouse/warehouseRuleSetting'
import ImageView from '@/components/ImageView.vue'
import TableView from '@/components/TableView.vue'
import {
  EditForm,
  WarehouseRuleSpuItem,
} from '@/types/api/warehouse/warehouseRuleSetting'
import { Plus, Warning } from '@element-plus/icons-vue'
import { useWarehouseRuleSettingTableColumns } from '../hooks/useWarehouseRuleSettingTableColumns'
import { WarehouseListData } from '@/types'
const emit = defineEmits<{
  (e: 'update:visible', value: boolean): void
  (e: 'saveSuccess'): void
}>()
const props = withDefaults(
  defineProps<{
    visible: boolean
    warehouseList: WarehouseListData[]
  }>(),
  {
    warehouseList: () => [],
  },
)

const dialogVisible = computed({
  get() {
    return props.visible
  },
  set(value: boolean) {
    emit('update:visible', value)
  },
})
const createDefaultForm = (): EditForm => ({
  id: undefined,
  groupName: '',
  status: true,
  spuList: [],
  warehouseId: props.warehouseList[0]?.id,
})

const editForm = ref<EditForm>(createDefaultForm())
const editFormRef = ref()
const spuSearchKeyword = ref('')
const spuSearchResultList = ref<WarehouseRuleSpuItem[]>([])
const popoverVisible = ref(false)
const dragIndex = ref<number | null>(null)
const spuTableRef = ref()

watch(
  () => props.visible,
  (visible) => {
    if (visible && props.warehouseList.length) {
      editForm.value.warehouseId = props.warehouseList[0].id
    }
    if (visible) {
      setupRowDrag()
    }
  },
)

const { spuTableColumns, spuSearchTableColumns } =
  useWarehouseRuleSettingTableColumns()

const updateSortNo = (list: WarehouseRuleSpuItem[]) => {
  return list.map((item, index) => ({
    ...item,
    sortOrder: index + 1,
  }))
}

const resetFields = (data?: EditForm) => {
  if (data) {
    const spuList = data.spuList ?? data.skuList ?? []
    editForm.value = {
      id: data.id,
      groupName: data.groupName ?? '',
      dataVersion: data.dataVersion ?? 0,
      status:
        typeof data.status === 'boolean' ? data.status : data.status === 1,
      spuList: updateSortNo(
        spuList.map((item) => ({
          ...item,
          warehouseSpu: item.warehouseSpu ?? item.warehouseSku,
        })),
      ),
    }
  } else {
    editForm.value = createDefaultForm()
  }
  spuSearchKeyword.value = ''
  spuSearchResultList.value = []
  popoverVisible.value = false
  dragIndex.value = null
  nextTick(() => {
    editFormRef.value?.clearValidate()
  })
}

const getRowIndexFromEvent = (e: DragEvent) => {
  const row = (e.target as HTMLElement).closest('tr.el-table__row')
  if (!row?.parentElement) {
    return null
  }
  return Array.from(row.parentElement.children).indexOf(row)
}

const setupRowDrag = () => {
  nextTick(() => {
    const tableEl = spuTableRef.value?.tableRef?.$el as HTMLElement | undefined
    const rows = tableEl?.querySelectorAll(
      '.el-table__body-wrapper tbody tr.el-table__row',
    )
    rows?.forEach((row) => {
      row.setAttribute('draggable', 'true')
    })
  })
}

watch(() => editForm.value.spuList, setupRowDrag, { deep: true })

const handleRowDragStart = (e: DragEvent) => {
  const target = e.target as HTMLElement
  if (target.closest('button, a, .el-button')) {
    e.preventDefault()
    return
  }
  const index = getRowIndexFromEvent(e)
  if (index === null || index < 0) {
    return
  }
  dragIndex.value = index
  e.dataTransfer!.effectAllowed = 'move'
}

const handleRowDrop = (e: DragEvent) => {
  const index = getRowIndexFromEvent(e)
  if (index === null || index < 0) {
    return
  }
  handleDrop(index)
}

const handleRowDragEnd = () => {
  dragIndex.value = null
}

const handleDrop = (index: number) => {
  if (dragIndex.value === null || dragIndex.value === index) {
    return
  }
  const list = [...(editForm.value.spuList ?? [])]
  const [movedItem] = list.splice(dragIndex.value, 1)
  list.splice(index, 0, movedItem)
  editForm.value.spuList = updateSortNo(list)
  dragIndex.value = null
}

const handleSearchSpu = async () => {
  const keyword = spuSearchKeyword.value.trim()
  if (!keyword) {
    ElMessage.warning('请输入库存SPU')
    popoverVisible.value = false
    return
  }
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  try {
    const res = await getQuerySpuApi(keyword, editForm.value.warehouseId)
    if (res.code !== 200) {
      popoverVisible.value = false
      spuSearchKeyword.value = ''
      return
    }
    spuSearchResultList.value = [res.data]
    if (spuSearchResultList.value.length === 0) {
      ElMessageBox.alert('未查询到SPU数据', '提示', {
        type: 'warning',
      })
      popoverVisible.value = false
    } else {
      popoverVisible.value = true
    }
  } catch (error) {
    console.error(error)
    spuSearchKeyword.value = ''
    popoverVisible.value = false
  } finally {
    loading.close()
  }
}

const handleAddSpu = (row: WarehouseRuleSpuItem) => {
  if (
    editForm.value.spuList?.some(
      (item) => item.warehouseSpu === row.warehouseSpu,
    )
  ) {
    ElMessage.warning('该SPU已添加')
    return
  }
  const existingList = editForm.value.spuList ?? []
  if (
    existingList.length > 0 &&
    existingList[0].warehouseId !== row.warehouseId
  ) {
    ElMessageBox.alert('请选择同一仓库内的SPU', '提示', {
      type: 'warning',
    })
    return
  }
  editForm.value.spuList = updateSortNo([
    ...(editForm.value.spuList ?? []),
    {
      warehouseSpu: row.warehouseSpu,
      skuName: row.skuName,
      skuImage: row.skuImage,
      warehouseId: row.warehouseId,
      warehouseName: row.warehouseName,
    },
  ])
  spuSearchResultList.value = spuSearchResultList.value.filter(
    (item) => item.warehouseSpu !== row.warehouseSpu,
  )
  if (spuSearchResultList.value.length === 0) {
    popoverVisible.value = false
  }
}

const handleRemoveSpu = async (index: number, row: WarehouseRuleSpuItem) => {
  try {
    await ElMessageBox.confirm(
      `确定删除${row.warehouseSpu}与共享库存组${editForm.value.groupName}关系吗?`,
      '提示',
      {
        type: 'warning',
      },
    )
  } catch {
    return
  }
  const list = [...(editForm.value.spuList ?? [])]
  list.splice(index, 1)
  editForm.value.spuList = updateSortNo(list)
}

const handleCancel = () => {
  dialogVisible.value = false
}

const handleSave = async () => {
  const valid = await editFormRef.value?.validate().catch(() => false)
  if (!valid) {
    return
  }
  if (!editForm.value.spuList?.length) {
    ElMessageBox.alert('请添加组内SPU', '提示', {
      type: 'warning',
    })
    return
  }
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  try {
    const editId = editForm.value.id
    const request = editId
      ? updateSharedInventoryGroupApi
      : addSharedInventoryGroupApi
    const res = await request({
      groupName: editForm.value.groupName!,
      status: !!editForm.value.status,
      id: editId,
      dataVersion: editForm.value.dataVersion!,
      skuList: editForm.value.spuList.map((item) => ({
        warehouseSpu: item.warehouseSpu!,
        sortOrder: item.sortOrder!,
        warehouseId: item.warehouseId!,
      })),
    })
    if (res.code !== 200) {
      return
    }
    ElMessage.success('保存成功')
    emit('saveSuccess')
    dialogVisible.value = false
  } catch (error) {
    console.error(error)
  } finally {
    loading.close()
  }
}

defineExpose({
  resetFields,
})
</script>
<style scoped lang="scss">
.section-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 12px;
  padding-left: 8px;
  border-left: 3px solid #409eff;

  & + .el-form-item {
    margin-top: 0;
  }

  &:not(:first-child) {
    margin-top: 8px;
  }
}

.spu-search-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.spu-drag-tip {
  font-size: 12px;
  color: #909399;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.spu-table-wrapper {
  height: 280px;

  :deep(tbody tr.el-table__row) {
    cursor: move;
    user-select: none;
  }

  :deep(img) {
    -webkit-user-drag: none;
  }
}

.dialog-footer {
  display: flex;
  justify-content: center;
}

.popover-table {
  height: 200px;
}
</style>

<style lang="scss">
.spu-search-popover {
  .el-button.is-circle {
    padding: 6px;
  }
}
</style>
