<template>
  <ElDialog
    v-model="visible"
    title="提交入库"
    width="1400px"
    top="10vh"
    :close-on-click-modal="false"
    destroy-on-close
  >
    <div class="submit-warehousing">
      <ElForm
        ref="formRef"
        :model="formData"
        :rules="formRules"
        label-width="100px"
        inline
      >
        <div class="form-row">
          <ElFormItem label="入库申请单" class="form-item">
            <ElInput
              v-model="formData.warehouseApplyNo"
              disabled
              placeholder="自动带出"
            />
          </ElFormItem>
          <ElFormItem label="入库仓库" class="form-item">
            <ElInput
              v-model="formData.warehouseName"
              disabled
              placeholder="自动带出"
            />
          </ElFormItem>
          <ElFormItem label="质检员" prop="checkerUserId" class="form-item">
            <ElSelect
              v-model="formData.checkerUserId"
              placeholder="请选择"
              filterable
              clearable
            >
              <ElOption
                v-for="item in userList"
                :key="item.id"
                :label="item.account"
                :value="item.id"
              />
            </ElSelect>
          </ElFormItem>
          <ElFormItem label="备注" class="form-item remark-item">
            <ElInput v-model="formData.remark" placeholder="请输入" clearable />
          </ElFormItem>
        </div>
      </ElForm>
      <div class="table-section">
        <TableView
          :selectionable="true"
          :serial-numberable="true"
          :data="formData.detailsList"
          :columns="tableColumns"
          @selection-change="handleSelectionChange"
        >
          <template #buyStored="{ row }">
            <ElInput
              v-model="row.buyStored"
              clearable
              size="small"
              style="width: 70px"
              @blur="validateField(row, 'buyStored')"
            />
            <div v-if="row._buyStoredError" class="field-error">
              {{ row._buyStoredError }}
            </div>
          </template>
          <template #rejectsAmount="{ row }">
            <ElInput
              v-model="row.rejectsAmount"
              clearable
              size="small"
              style="width: 70px"
              @blur="validateField(row, 'rejectsAmount')"
            />
            <div v-if="row._rejectsAmountError" class="field-error">
              {{ row._rejectsAmountError }}
            </div>
          </template>
          <template #locationName="{ row }">
            <ElSelect
              v-model="row.locationId"
              placeholder="请选择"
              clearable
              style="width: 100px"
            >
              <ElOption
                v-for="item in allLocationList"
                :key="item.id"
                :label="item.locationCode"
                :value="item.id"
              />
            </ElSelect>
          </template>
        </TableView>
      </div>
      <div class="batch-action">
        <ElButton type="primary" @click="batchSetBuyStored">
          申请数量>>本次入库数量
        </ElButton>
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <ElButton @click="handleCancel">取消</ElButton>
        <ElButton type="primary" @click="handleSubmit"> 入库 </ElButton>
      </div>
    </template>
  </ElDialog>
</template>

<script setup lang="tsx">
import { ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { getUserListApi, LocationInfoGetAll } from '@/api/common'
import { loactionData } from '@/api/warehouse'
import {
  getLocationListApi,
  getStockingApplyOrderDetailById,
  submitWarehousingApi,
} from '@/api/warehouse/stockingApplyOrder'
import {
  StockingApplyOrderDetailData,
  StockingApplyOrderDetailList,
  LocationDataBySkuData,
} from '@/types/api/warehouse/stockingApplyOrder'
import { userData } from '@/types/api/user'
import { BigNumber } from 'bignumber.js'

const emit = defineEmits<{
  (e: 'refresh'): void
}>()

const visible = ref(false)
const formRef = ref<FormInstance>()
const userList = ref<userData[]>([])
const locationList = ref<LocationDataBySkuData[]>([])
const selectedRows = ref<StockingApplyOrderDetailList[]>([])

const formData = ref<StockingApplyOrderDetailData>({
  detailsList: [],
  id: 0,
  warehouseApplyNo: '',
  warehouseName: '',
  warehouseId: undefined,
  checkerUserId: undefined,
  remark: '',
})
type StockingApplyOrderDetailListWithError = StockingApplyOrderDetailList & {
  _buyStoredError?: string
  _rejectsAmountError?: string
}
const tableColumns = ref([
  {
    label: 'SKU图片',
    prop: 'warehouseSkuImage',
    width: 90,
    align: 'center',
    render: (row: StockingApplyOrderDetailList) => (
      <el-image
        preview-teleported
        src={row.warehouseSkuImage}
        preview-src-list={[row.warehouseSkuImage]}
        z-index={9999}
        style="width: 60px;height: 60px;text-align: center;"
      />
    ),
  },
  {
    label: '商品名称',
    prop: 'warehouseSkuName',
    align: 'left',
  },
  {
    label: '款号',
    width: 140,
    prop: 'productNo',
    align: 'center',
  },
  {
    label: '库存SKU',
    prop: 'warehouseSku',
    width: 180,
    align: 'center',
  },
  {
    label: '申请数量',
    width: 120,
    prop: 'shipmentQuantity',
    align: 'right',
  },
  {
    label: '入库数量',
    prop: 'buyStored',
    width: 100,
    align: 'right',
    slot: 'buyStored',
  },
  {
    label: '不良品数',
    prop: 'rejectsAmount',
    width: 100,
    align: 'right',
    slot: 'rejectsAmount',
  },
  {
    label: '实际质检数',
    prop: 'finallyShipmentQuantity',
    width: 100,
    align: 'right',
    render: (row: StockingApplyOrderDetailList) => {
      const buyStored = new BigNumber(row.buyStored || 0).toNumber()
      const rejectsAmount = new BigNumber(row.rejectsAmount || 0).toNumber()
      return new BigNumber(buyStored).plus(rejectsAmount).toNumber()
    },
  },
  {
    label: '库位',
    prop: 'locationId',
    width: 140,
    align: 'right',
    slot: 'locationName',
  },
])
const formRules: FormRules = {
  checkerUserId: [
    { required: true, message: '请选择质检员', trigger: 'change' },
  ],
}

const loadUserList = async () => {
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  try {
    const res = await getUserListApi()
    if (res.code === 200) {
      userList.value = res.data || []
    }
  } catch (e) {
    console.error(e)
  } finally {
    loading.close()
  }
}

const loadDetailList = async (id: number) => {
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  try {
    const res = await getStockingApplyOrderDetailById(id)
    if (res.code !== 200) return
    if (!res.data.checkerUserId) {
      res.data.checkerUserId = JSON.parse(
        localStorage.getItem('user') || '{}',
      ).id
    }
    const skuList = res.data.detailsList.map((item) => item.warehouseSku)
    try {
      const locationRes = await getLocationListApi(
        skuList.join(','),
        res.data.warehouseId as string | number,
      )
      if (locationRes.code !== 200) return
      const { detailsList } = res.data
      if (detailsList && detailsList.length > 0) {
        if (detailsList.some((e) => (e.storedPending as number) > 0)) {
          return ElMessageBox.alert(
            '已存在待审核的入库单，请勿重复操作!',
            '提示',
            {
              confirmButtonText: '确定',
              type: 'warning',
            },
          )
        }
      }
      locationList.value = locationRes.data || []

      res.data.detailsList.forEach((item) => {
        if (!item.buyStored) {
          item.buyStored = item.shipmentQuantity
        }
        if (locationList.value.length > 0) {
          const location = locationList.value.find(
            (location) => location.warehouseSku === item.warehouseSku,
          )
          if (location) {
            item.locationId = location.locationId
          }
        }
      })
    } catch (e) {
      console.error(e)
    }
    formData.value = res.data
    visible.value = true
  } catch (e) {
    console.error(e)
  } finally {
    loading.close()
  }
}
const allLocationList = ref<loactionData[]>([])
const loadAllLocationList = async (
  warehouseId: string | number | undefined,
) => {
  if (!warehouseId) return
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  try {
    const res = await LocationInfoGetAll(warehouseId)
    if (res.code !== 200) return
    allLocationList.value = res.data || []
  } catch (e) {
    console.error(e)
  } finally {
    loading.close()
  }
}

const open = async (row: {
  id: number
  warehouseId: string | number | undefined
}) => {
  selectedRows.value = []
  loadUserList()
  await loadAllLocationList(row.warehouseId)
  loadDetailList(row.id)
}

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

const handleSelectionChange = (rows: StockingApplyOrderDetailList[]) => {
  selectedRows.value = rows
}

const batchSetBuyStored = () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning('请先选择数据')
    return
  }
  selectedRows.value.forEach((row) => {
    row.buyStored = row.shipmentQuantity
  })
}

const validateField = (
  row: StockingApplyOrderDetailListWithError,
  field: 'buyStored' | 'rejectsAmount',
) => {
  const value = row[field]
  const strValue = value === 0 || value === '0' ? '0' : String(value ?? '')
  const fieldLabel = field === 'buyStored' ? '入库数量' : '不良品数'

  if (!strValue) {
    if (field === 'buyStored') row._buyStoredError = '必填项'
  } else if (!/^\d+$/.test(strValue)) {
    if (field === 'buyStored') row._buyStoredError = '只能输入正整数'
    else if (field === 'rejectsAmount')
      row._rejectsAmountError = '只能输入正整数'
  } else if (Number(strValue) === 0) {
    if (field === 'buyStored') row._buyStoredError = `${fieldLabel}不能为0`
    else if (field === 'rejectsAmount') row._rejectsAmountError = ''
  } else {
    if (field === 'buyStored') row._buyStoredError = ''
    else row._rejectsAmountError = ''
  }
}

const validateDetailsList = (): boolean => {
  if (!formData.value.detailsList?.length) {
    return true
  }
  let isValid = true
  formData.value.detailsList.forEach((row) => {
    const extendedRow = row as StockingApplyOrderDetailListWithError
    validateField(extendedRow, 'buyStored')
    validateField(extendedRow, 'rejectsAmount')
    if (extendedRow._buyStoredError || extendedRow._rejectsAmountError) {
      isValid = false
    }
  })
  return isValid
}

const handleSubmit = async () => {
  if (!formRef.value) return
  try {
    await formRef.value.validate()
  } catch {
    return
  }
  if (!validateDetailsList()) {
    ElMessage.warning('请检查入库数量和不良品数是否正确填写')
    return
  }
  const overQuantitySkus = []
  for (const item of formData.value.detailsList) {
    if (Number(item.buyStored) > Number(item.shipmentQuantity)) {
      overQuantitySkus.push(item.warehouseSku)
    }
    const locationCode = allLocationList.value.find(
      (location: loactionData) => location.id === Number(item.locationId),
    )?.locationCode
    item.locationCode = locationCode as string | undefined
    const buyStored = new BigNumber(item.buyStored || 0).toNumber()
    const rejectsAmount = new BigNumber(item.rejectsAmount || 0).toNumber()
    item.finallyShipmentQuantity = new BigNumber(buyStored)
      .plus(rejectsAmount)
      .toNumber()
  }
  if (overQuantitySkus.length > 0) {
    ElMessageBox.alert(
      `<div style="line-height: 1.6;"><span style="white-space: nowrap; flex-shrink: 0;">库存SKU:</span><span style="word-break: break-all; margin-left: 4px;">${overQuantitySkus.join(
        ',',
      )}</span><span style="margin-top: 12px;">入库数量不能大于申请数量</span></div>`,
      '提示',
      {
        confirmButtonText: '确定',
        type: 'warning',
        customClass: 'over-quantity-alert-box',
        dangerouslyUseHTMLString: true,
      },
    )
    return
  }
  const checkerName = userList.value.find(
    (item) => item.id === formData.value.checkerUserId,
  )?.account
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  try {
    const res = await submitWarehousingApi({ ...formData.value, checkerName })
    if (res.code === 200) {
      ElMessage.success('入库成功')
      visible.value = false
      emit('refresh')
    }
  } catch (e) {
    console.error(e)
  } finally {
    loading.close()
  }
}

defineExpose({ open })
</script>

<style lang="scss" scoped>
.submit-warehousing {
  height: 600px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  .form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: flex-start;
  }
  .table-section {
    flex: 1;
    overflow: hidden;
  }
  .batch-action {
    margin-top: 10px;
  }
  .form-item {
    flex: 0 0 auto;
    margin-right: 20px;

    :deep(.el-input),
    :deep(.el-select) {
      width: 180px;
    }
  }

  .remark-item {
    flex: 1;
    :deep(.el-input) {
      width: 100%;
    }
  }
}

.dialog-footer {
  text-align: center;
}
.field-error {
  color: #f56c6c;
  font-size: 12px;
  line-height: 1;
  margin-top: 2px;
  text-align: center;
}
</style>
<style>
.over-quantity-alert-box {
  width: 1000px !important;
  max-width: 90vw !important;
}

.over-quantity-alert-box .el-message-box__message {
  word-break: break-all;
  line-height: 1.6;
  padding: 10px 0;
}
</style>
