<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="1000">
    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="auto" v-loading="formLoading"
      :disabled="formDisabled">
      <el-row :gutter="20">
        <el-col :span="8">
          <el-form-item :label="t('ErpStock.Check.no')" prop="no">
            <el-input v-model="formData.no" disabled :placeholder="t('ErpStock.Check.placeholderNoAuto')" />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="t('ErpStock.Check.checkTime')" prop="checkTime">
            <el-date-picker v-model="formData.checkTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss"
              :placeholder="t('ErpStock.Check.placeholderCheckTime')" class="!w-1/1" />
          </el-form-item>
        </el-col>
        <el-col :span="8" />
        <el-col :span="12">
          <el-form-item :label="t('ErpStock.Check.sourceType')" prop="sourceType">
            <el-radio-group v-model="formData.sourceType" @change="handleSourceTypeChange">
              <el-radio :value="1">{{ t('ErpStock.Check.sourceTypeStock') }}</el-radio>
              <el-radio :value="2">{{ t('ErpStock.Check.sourceTypeProduct') }}</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item :label="t('ErpStock.Check.categoryType')" prop="categoryType">
            <el-radio-group v-model="formData.categoryType" @change="handleCategoryTypeChange">
              <el-radio
                v-for="dict in getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)"
                :key="dict.value"
                :label="dict.value"
              >
                {{ dict.label }}
              </el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>

    <ContentWrap>
      <el-form v-if="!isInventoryCheck" class="stock-check-selector-form" label-width="auto"
        :disabled="selectionDisabled">
        <template v-if="formData.sourceType === 1">
          <el-form-item :label="t('ErpStock.Check.warehouse')">
            <el-input :model-value="selectedWarehouseText" readonly
              :placeholder="t('ErpStock.Check.placeholderWarehouse')">
              <template #append>
                <el-button :disabled="selectionDisabled" @click="openWarehouseDialog">{{ t('common.select')
                  }}</el-button>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item v-if="selectedWarehouseIds.length > 0" :label="t('ErpStock.Check.area')">
            <el-input :model-value="selectedAreaText" readonly :placeholder="t('ErpStock.Check.placeholderArea')">
              <template #append>
                <el-button :disabled="selectionDisabled" @click="openAreaDialog">{{ t('common.select') }}</el-button>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item v-if="selectedWarehouseIds.length > 0" :label="t('ErpStock.Check.checkItem')">
            <el-input :model-value="selectedItemText" readonly :placeholder="t('ErpStock.Check.placeholderCheckItem')">
              <template #append>
                <el-button :disabled="selectionDisabled" @click="openGeneratedItemDialog">{{ t('common.select')
                  }}</el-button>
              </template>
            </el-input>
          </el-form-item>
        </template>

        <template v-else>
          <el-form-item :label="t('ErpStock.Check.product')">
            <el-input :model-value="selectedProductText" readonly :placeholder="t('ErpStock.Check.placeholderProduct')">
              <template #append>
                <el-button :disabled="selectionDisabled" @click="openProductDialog">{{ t('common.select') }}</el-button>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item v-if="selectedProductIds.length > 0" :label="t('ErpStock.Check.checkItem')">
            <el-input :model-value="selectedItemText" readonly :placeholder="t('ErpStock.Check.placeholderCheckItem')">
              <template #append>
                <el-button :disabled="selectionDisabled" @click="openGeneratedItemDialog">{{ t('common.select')
                  }}</el-button>
              </template>
            </el-input>
          </el-form-item>
        </template>
      </el-form>

      <el-tabs v-if="isDetail" v-model="detailActiveTab" class="stock-check-detail-tabs">
        <el-tab-pane :label="t('ErpStock.Check.list')" name="items" />
        <el-tab-pane label="审核记录" name="approveRecords" />
      </el-tabs>

      <el-table
        v-if="!isDetail || detailActiveTab === 'items'"
        :data="formData.items || []"
        border
        size="small"
        class="mt-12px"
      >
        <el-table-column :label="t('ErpStock.Item.warehouse')" prop="warehouseName" min-width="120" />
        <el-table-column :label="t('ErpStock.Item.area')" prop="areaName" min-width="100" />
        <el-table-column :label="t('ErpStock.Item.barcode')" prop="productBarCode" min-width="150" />
        <el-table-column :label="t('ErpStock.Item.product')" prop="productName" min-width="160" />
        <el-table-column :label="t('ErpStock.Check.stockCount')" prop="stockCount" min-width="100" />
        <el-table-column v-if="isInventoryCheck" :label="t('ErpStock.Check.actualCount')" align="right" min-width="140">
          <template #default="{ row }">
            <el-input-number v-model="row.actualCount" controls-position="right" :precision="0" :min="0"
              class="!w-100%" />
          </template>
        </el-table-column>
        <el-table-column v-if="formType === 'update'" :label="t('common.operate')" align="center" fixed="right"
          width="80">
          <template #default="{ $index }">
            <el-button link type="danger" @click="handleDeleteItem($index)">
              {{ t('action.delete') }}
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-table v-else :data="formData.approveRecords || []" border size="small" class="mt-12px">
        <el-table-column label="变更前状态" prop="fromStatus" align="center" min-width="110">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.fromStatus" />
          </template>
        </el-table-column>
        <el-table-column label="变更后状态" prop="toStatus" align="center" min-width="110">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.toStatus" />
          </template>
        </el-table-column>
        <el-table-column label="目标审核人" prop="targetUserName" min-width="120" />
        <el-table-column label="操作人" prop="creatorName" min-width="120" />
        <el-table-column
          label="操作时间"
          prop="createTime"
          :formatter="dateFormatter"
          min-width="170"
        />
        <el-table-column
          :label="t('ErpStock.Check.remark')"
          prop="remark"
          min-width="160"
          show-overflow-tooltip
        />
      </el-table>
    </ContentWrap>
    <el-form :model="formData" label-width="auto" :disabled="formDisabled" class="stock-check-bottom-form">
      <el-row :gutter="20">
        <el-col :span="24">
          <el-form-item :label="t('ErpStock.Check.remark')" prop="remark">
            <el-input v-model="formData.remark" type="textarea" :rows="2"
              :placeholder="t('ErpStock.Check.placeholderRemark')" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>

    <template #footer>
      <el-button @click="dialogVisible = false">
        {{ isDetail ? t('common.close') : t('common.cancel') }}
      </el-button>
      <template v-if="!isDetail">
        <template v-if="isInventoryCheck">
          <el-button type="primary" :disabled="formLoading" @click="submitForm(0)">
            {{ t('ErpStock.Check.saveDraft') }}
          </el-button>
          <el-button type="warning" :disabled="formLoading || hasIncompleteActualCount" @click="submitForm(1)">
            {{ t('ErpStock.Check.inventoryCheck') }}
          </el-button>
        </template>
        <el-button v-else type="primary" :disabled="formLoading" @click="submitForm()">
          {{ t('common.save') }}
        </el-button>
      </template>
    </template>
  </Dialog>

  <Dialog :title="t('ErpStock.Check.selectWarehouseDialogTitle')" v-model="warehouseDialogVisible" width="1000">
    <el-form :model="warehouseQueryParams" :inline="true" label-width="auto" class="-mb-15px">
      <el-form-item :label="t('ErpStock.Warehouse.name')">
        <el-input v-model="warehouseQueryParams.name" clearable :placeholder="t('ErpStock.Warehouse.placeholderName')"
          class="!w-240px" @keyup.enter="getWarehouseList" />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleWarehouseQuery">
          <Icon icon="ep:search" class="mr-5px" />{{ t('common.query') }}
        </el-button>
        <el-button @click="resetWarehouseQuery">
          <Icon icon="ep:refresh" class="mr-5px" />{{ t('common.reset') }}
        </el-button>
      </el-form-item>
    </el-form>
    <el-table ref="warehouseTableRef" v-loading="warehouseLoading" :data="warehouseList" row-key="id"
      @row-click="handleWarehouseRowClick" @selection-change="warehouseSelection = $event">
      <el-table-column type="selection" width="55" reserve-selection />
      <el-table-column :label="t('ErpStock.Warehouse.name')" align="center" prop="name" min-width="160" sortable />
      <el-table-column :label="t('ErpStock.Warehouse.categoryType')" align="center" prop="categoryType" min-width="120">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE" :value="scope.row.categoryType" />
        </template>
      </el-table-column>
      <el-table-column :label="t('ErpStock.Warehouse.address')" align="center" prop="address" min-width="180"
        show-overflow-tooltip />
      <el-table-column :label="t('ErpStock.Warehouse.principal')" align="center" prop="principal" min-width="110" />
      <el-table-column :label="t('ErpStock.Warehouse.remark')" align="center" prop="remark" min-width="150"
        show-overflow-tooltip />
      <el-table-column :label="t('ErpStock.Warehouse.sort')" align="center" prop="sort" min-width="90" sortable />
      <el-table-column :label="t('ErpStock.Warehouse.status')" align="center" prop="status" min-width="100" sortable>
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
        </template>
      </el-table-column>
      <el-table-column :label="t('ErpStock.Warehouse.defaultStatus')" align="center" prop="defaultStatus"
        min-width="110" sortable>
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.defaultStatus" />
        </template>
      </el-table-column>
      <el-table-column :label="t('ErpStock.Warehouse.createTime')" align="center" prop="createTime"
        :formatter="dateFormatter" min-width="180" sortable />
    </el-table>
    <div class="stock-check-dialog-pagination">
      <Pagination :total="warehouseTotal" v-model:page="warehouseQueryParams.pageNo"
        v-model:limit="warehouseQueryParams.pageSize" @pagination="getWarehouseList" />
    </div>
    <template #footer>
      <el-button type="primary" @click="confirmWarehouseSelection">{{ t('common.ok') }}</el-button>
      <el-button @click="warehouseDialogVisible = false">{{ t('common.cancel') }}</el-button>
    </template>
  </Dialog>

  <Dialog :title="t('ErpStock.Check.selectAreaDialogTitle')" v-model="areaDialogVisible" width="1000">
    <el-form :model="areaQueryParams" :inline="true" label-width="auto" class="-mb-15px">
      <el-form-item :label="t('ErpStock.WarehouseArea.areaCode')">
        <el-input v-model="areaQueryParams.areaCode" clearable
          :placeholder="t('ErpStock.WarehouseArea.placeholderAreaCode')" class="!w-240px" @keyup.enter="getAreaList" />
      </el-form-item>
      <el-form-item :label="t('ErpStock.WarehouseArea.areaName')">
        <el-input v-model="areaQueryParams.areaName" clearable
          :placeholder="t('ErpStock.WarehouseArea.placeholderAreaName')" class="!w-240px" @keyup.enter="getAreaList" />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleAreaQuery">
          <Icon icon="ep:search" class="mr-5px" />{{ t('common.query') }}
        </el-button>
        <el-button @click="resetAreaQuery">
          <Icon icon="ep:refresh" class="mr-5px" />{{ t('common.reset') }}
        </el-button>
      </el-form-item>
    </el-form>
    <el-table ref="areaTableRef" v-loading="areaLoading" :data="areaList" row-key="id" @row-click="handleAreaRowClick"
      @selection-change="areaSelection = $event">
      <el-table-column type="selection" width="55" reserve-selection />
      <el-table-column :label="t('ErpStock.WarehouseArea.warehouseId')" align="center" prop="warehouseId"
        min-width="140" sortable>
        <template #default="scope">
          {{ getWarehouseName(scope.row.warehouseId) }}
        </template>
      </el-table-column>
      <el-table-column :label="t('ErpStock.WarehouseArea.areaCode')" align="center" prop="areaCode" min-width="130"
        sortable />
      <el-table-column :label="t('ErpStock.WarehouseArea.areaName')" align="center" prop="areaName" min-width="130"
        sortable />
      <el-table-column :label="t('ErpStock.WarehouseArea.areaSize')" align="center" prop="areaSize" min-width="100" />
      <el-table-column :label="t('ErpStock.WarehouseArea.description')" align="center" prop="description"
        min-width="160" show-overflow-tooltip />
      <el-table-column :label="t('ErpStock.WarehouseArea.status')" align="center" prop="status" min-width="100"
        sortable>
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
        </template>
      </el-table-column>
      <el-table-column :label="t('ErpStock.WarehouseArea.createTime')" align="center" prop="createTime"
        :formatter="dateFormatter" min-width="180" sortable />
    </el-table>
    <div class="stock-check-dialog-pagination">
      <Pagination :total="areaTotal" v-model:page="areaQueryParams.pageNo" v-model:limit="areaQueryParams.pageSize"
        @pagination="getAreaList" />
    </div>
    <template #footer>
      <el-button type="primary" @click="confirmAreaSelection">{{ t('common.ok') }}</el-button>
      <el-button @click="areaDialogVisible = false">{{ t('common.cancel') }}</el-button>
    </template>
  </Dialog>

  <Dialog :title="t('ErpStock.Check.selectProductDialogTitle')" v-model="productDialogVisible" width="1100">
    <el-form :model="productQueryParams" :inline="true" label-width="auto" class="-mb-15px">
      <el-form-item :label="t('ErpStock.Item.barcode')">
        <el-input v-model="productQueryParams.barCode" clearable
          :placeholder="t('ErpStock.Check.placeholderProductBarCode')" class="!w-240px" @keyup.enter="getProductList" />
      </el-form-item>
      <el-form-item :label="t('ErpStock.Item.product')">
        <el-input v-model="productQueryParams.name" clearable :placeholder="t('ErpStock.Check.placeholderProductName')"
          class="!w-240px" @keyup.enter="getProductList" />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleProductQuery">
          <Icon icon="ep:search" class="mr-5px" />{{ t('common.query') }}
        </el-button>
        <el-button @click="resetProductQuery">
          <Icon icon="ep:refresh" class="mr-5px" />{{ t('common.reset') }}
        </el-button>
      </el-form-item>
    </el-form>
    <el-table ref="productTableRef" v-loading="productLoading" :data="productList" row-key="id"
      @row-click="handleProductRowClick" @selection-change="productSelection = $event">
      <el-table-column type="selection" width="55" reserve-selection />
      <el-table-column :label="t('ErpStock.Item.barcode')" prop="barCode" min-width="160" />
      <el-table-column :label="t('ErpStock.Item.product')" prop="name" min-width="180" />
      <el-table-column :label="t('ErpStock.Check.materialCategory')" prop="categoryType" align="center" min-width="110">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE" :value="scope.row.categoryType" />
        </template>
      </el-table-column>
      <el-table-column :label="t('ErpStock.Check.materialSubCategory')" prop="subCategoryName" min-width="120" />
      <el-table-column :label="t('ErpStock.Item.unit')" prop="unitName" align="center" min-width="80" />
      <el-table-column :label="t('ErpStock.Check.standard')" prop="standard" min-width="120" show-overflow-tooltip />
    </el-table>
    <div class="stock-check-dialog-pagination">
      <Pagination :total="productTotal" v-model:page="productQueryParams.pageNo"
        v-model:limit="productQueryParams.pageSize" @pagination="getProductList" />
    </div>
    <template #footer>
      <el-button type="primary" @click="confirmProductSelection">{{ t('common.ok') }}</el-button>
      <el-button @click="productDialogVisible = false">{{ t('common.cancel') }}</el-button>
    </template>
  </Dialog>

  <Dialog :title="t('ErpStock.Check.selectCheckItemDialogTitle')" v-model="generatedItemDialogVisible" width="1200">
    <el-table ref="generatedItemTableRef" v-loading="generatedItemLoading" :data="generatedItemList"
      :row-key="getGeneratedItemRowKey" max-height="560" @row-click="handleGeneratedItemRowClick"
      @selection-change="generatedItemSelection = $event">
      <el-table-column type="selection" width="55" reserve-selection />
      <el-table-column :label="t('ErpStock.Item.warehouse')" prop="warehouseName" min-width="120" />
      <el-table-column :label="t('ErpStock.Item.area')" prop="areaName" min-width="100" />
      <el-table-column :label="t('ErpStock.Item.barcode')" prop="productBarCode" min-width="150" />
      <el-table-column :label="t('ErpStock.Item.product')" prop="productName" min-width="160" />
      <el-table-column :label="t('ErpStock.Check.stockCount')" prop="stockCount" align="right" min-width="100" />
    </el-table>
    <template #footer>
      <el-button type="primary" @click="confirmGeneratedItemSelection">{{ t('common.ok') }}</el-button>
      <el-button @click="generatedItemDialogVisible = false">{{ t('common.cancel') }}</el-button>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter, formatDate } from '@/utils/formatTime'
import { StockCheckApi, type StockCheckVO, type StockCheckItemVO } from '@/api/erp/stock/check'
import { WarehouseApi, type WarehouseVO } from '@/api/erp/stock/warehouse'
import { WarehouseAreaApi, type WarehouseAreaVO } from '@/api/erp/stock/warehousearea'
import { ProductApi, type ProductVO } from '@/api/erp/product/product'

type FormData = Partial<StockCheckVO> & {
  items: StockCheckItemVO[]
}

defineOptions({ name: 'StockCheckExecutionForm' })

const { t } = useI18n()
const message = useMessage()

const dialogVisible = ref(false)
const dialogTitle = ref('')
const formLoading = ref(false)
const formType = ref('')
const formRef = ref()
const detailActiveTab = ref('items')

const isDetail = computed(() => formType.value === 'detail')
const isInventoryCheck = computed(() => formType.value === 'check')
const formDisabled = computed(() => isDetail.value || isInventoryCheck.value)
const selectionDisabled = computed(() => isDetail.value)

const formData = ref<FormData>({
  id: undefined,
  no: undefined,
  checkTime: undefined,
  sourceType: 1,
  categoryType: undefined,
  remark: undefined,
  items: []
})

const formRules = reactive({
  checkTime: [{ required: true, message: t('ErpStock.Check.validatorCheckTimeRequired'), trigger: 'change' }],
  sourceType: [{ required: true, message: t('ErpStock.Check.validatorSourceTypeRequired'), trigger: 'change' }],
  categoryType: [{ required: true, message: t('ErpStock.Check.validatorCategoryTypeRequired'), trigger: 'change' }]
})

const getCurrentTime = () => formatDate(new Date())
const isActualCountEmpty = (value: unknown) => value === undefined || value === null || value === ''
const hasIncompleteActualCount = computed(() =>
  (formData.value.items || []).some((item) => isActualCountEmpty(item.actualCount))
)
const getCheckItemName = (item: StockCheckItemVO) =>
  item.productBarCode || item.productName || `${t('ErpStock.Check.checkItem')}${item.id ? `-${item.id}` : ''}`

const selectedWarehouses = ref<WarehouseVO[]>([])
const selectedAreas = ref<WarehouseAreaVO[]>([])
const selectedProducts = ref<ProductVO[]>([])

const selectedWarehouseIds = computed(() => selectedWarehouses.value.map((item) => item.id))
const selectedAreaIds = computed(() => selectedAreas.value.map((item) => item.id))
const selectedProductIds = computed(() => selectedProducts.value.map((item) => item.id))
const selectedTextSeparator = computed(() => t('ErpStock.Check.selectedTextSeparator'))
const selectedWarehouseText = computed(() =>
  selectedWarehouses.value.map((item) => item.name).join(selectedTextSeparator.value)
)
const selectedAreaText = computed(() =>
  selectedAreas.value.map((item) => item.areaName).join(selectedTextSeparator.value)
)
const selectedProductText = computed(() =>
  selectedProducts.value.map((item) => item.name).join(selectedTextSeparator.value)
)
const selectedItemText = computed(() => {
  const count = formData.value.items?.length || 0
  return count ? t('ErpStock.Check.selectedItemCount', { count }) : ''
})

const warehouseDialogVisible = ref(false)
const warehouseLoading = ref(false)
const warehouseTableRef = ref()
const warehouseList = ref<WarehouseVO[]>([])
const warehouseTotal = ref(0)
const warehouseSelection = ref<WarehouseVO[]>([])
const warehouseQueryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  name: undefined as string | undefined
})

const areaDialogVisible = ref(false)
const areaLoading = ref(false)
const areaTableRef = ref()
const areaList = ref<WarehouseAreaVO[]>([])
const areaTotal = ref(0)
const areaSelection = ref<WarehouseAreaVO[]>([])
const areaQueryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  areaCode: undefined as string | undefined,
  areaName: undefined as string | undefined
})

const productDialogVisible = ref(false)
const productLoading = ref(false)
const productTableRef = ref()
const productList = ref<ProductVO[]>([])
const productTotal = ref(0)
const productSelection = ref<ProductVO[]>([])
const productQueryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  barCode: undefined as string | undefined,
  name: undefined as string | undefined
})

const generatedItemDialogVisible = ref(false)
const generatedItemLoading = ref(false)
const generatedItemTableRef = ref()
const generatedItemList = ref<StockCheckItemVO[]>([])
const generatedItemSelection = ref<StockCheckItemVO[]>([])

const getDefaultCategoryType = () => getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)[0]?.value

const open = async (type: string, id?: number) => {
  dialogVisible.value = true
  dialogTitle.value = type === 'check' ? t('ErpStock.Check.inventoryCheck') : t('action.' + type)
  formType.value = type
  resetForm()
  if (!id) {
    return
  }

  formLoading.value = true
  try {
    const data = await StockCheckApi.getStockCheck(id)
    formData.value = {
      ...data,
      sourceType: Number(data?.sourceType ?? 1),
      categoryType: data?.categoryType ?? getDefaultCategoryType(),
      checkTime: data?.checkTime ? formatDate(data.checkTime as Date) : undefined,
      items: data?.items || [],
      approveRecords: data?.approveRecords || []
    }
    if (type === 'detail') {
      await enrichItemsForDisplay()
      hydrateSelectionsFromItems()
    }
  } finally {
    formLoading.value = false
  }
}

defineExpose({ open })

const emit = defineEmits(['success'])

const handleDeleteItem = (index: number) => {
  formData.value.items?.splice(index, 1)
}

const handleSourceTypeChange = () => {
  clearSelections()
}

const handleCategoryTypeChange = () => {
  clearSelections()
}

const clearSelections = () => {
  selectedWarehouses.value = []
  selectedAreas.value = []
  selectedProducts.value = []
  formData.value.items = []
}

const enrichItemsForDisplay = async () => {
  const items = formData.value.items || []
  if (items.length === 0) {
    return
  }
  const warehouseIds = Array.from(new Set(items.map((item) => item.warehouseId).filter(Boolean))) as number[]
  const [warehouses, products, areaData] = await Promise.all([
    WarehouseApi.getWarehouseSimpleList(),
    ProductApi.getProductSimpleList(),
    WarehouseAreaApi.getWarehouseAreaPage({
      pageNo: 1,
      pageSize: 10,
      warehouseId: warehouseIds.length === 1 ? warehouseIds[0] : undefined,
      warehouseIds: warehouseIds.join(',')
    })
  ])
  const warehouseMap = new Map((warehouses || []).map((item) => [item.id, item]))
  const productMap = new Map((products || []).map((item) => [item.id, item]))
  const areaMap = new Map(((areaData?.list || []) as WarehouseAreaVO[]).map((item) => [item.id, item]))

  items.forEach((item) => {
    const warehouse = warehouseMap.get(item.warehouseId)
    const product = productMap.get(item.productId)
    const area = item.areaId ? areaMap.get(item.areaId) : undefined
    item.warehouseName = item.warehouseName || warehouse?.name
    item.areaName = item.areaName || area?.areaName
    item.productName = item.productName || product?.name
    item.productBarCode = item.productBarCode || product?.barCode
    item.productUnitName = item.productUnitName || product?.unitName
    item.productPrice = item.productPrice ?? product?.minPrice ?? product?.purchasePrice
  })
}

const hydrateSelectionsFromItems = () => {
  const items = formData.value.items || []
  if (formData.value.sourceType === 1) {
    selectedWarehouses.value = uniqBy(
      items
        .filter((item) => item.warehouseId)
        .map((item) => ({ id: item.warehouseId, name: item.warehouseName }) as WarehouseVO),
      'id'
    )
    selectedAreas.value = uniqBy(
      items
        .filter((item) => item.areaId)
        .map(
          (item) =>
            ({
              id: item.areaId,
              warehouseId: item.warehouseId,
              areaName: item.areaName
            }) as WarehouseAreaVO
        ),
      'id'
    )
  } else {
    selectedProducts.value = uniqBy(
      items
        .filter((item) => item.productId)
        .map((item) => ({ id: item.productId, name: item.productName }) as ProductVO),
      'id'
    )
  }
}

const uniqBy = <T extends Record<string, any>>(list: T[], key: string) => {
  const map = new Map()
  list.forEach((item) => {
    if (item[key] !== undefined && item[key] !== null && !map.has(item[key])) {
      map.set(item[key], item)
    }
  })
  return Array.from(map.values())
}

const sameIds = (left: number[], right: number[]) =>
  left.length === right.length && left.every((id) => right.includes(id))

const syncTableSelection = async (tableRef, rows: any[], selectedIds: number[]) => {
  await nextTick()
  tableRef.value?.clearSelection()
  rows.forEach((row) => {
    if (selectedIds.includes(row.id)) {
      tableRef.value?.toggleRowSelection(row, true)
    }
  })
}

const getWarehouseList = async () => {
  warehouseLoading.value = true
  try {
    const data = await WarehouseApi.getWarehousePage({
      ...warehouseQueryParams,
      categoryType: formData.value.categoryType
    })
    warehouseList.value = data?.list || []
    warehouseTotal.value = data?.total || 0
    await syncTableSelection(warehouseTableRef, warehouseList.value, selectedWarehouseIds.value)
  } finally {
    warehouseLoading.value = false
  }
}

const openWarehouseDialog = async () => {
  warehouseDialogVisible.value = true
  warehouseSelection.value = [...selectedWarehouses.value]
  await getWarehouseList()
}

const handleWarehouseQuery = () => {
  warehouseQueryParams.pageNo = 1
  getWarehouseList()
}

const resetWarehouseQuery = () => {
  warehouseQueryParams.pageNo = 1
  warehouseQueryParams.name = undefined
  getWarehouseList()
}

const confirmWarehouseSelection = () => {
  const oldIds = selectedWarehouseIds.value
  selectedWarehouses.value = [...warehouseSelection.value]
  warehouseDialogVisible.value = false
  if (!sameIds(oldIds, selectedWarehouseIds.value)) {
    selectedAreas.value = []
  }
}

const handleWarehouseRowClick = (row: WarehouseVO) => {
  warehouseTableRef.value?.toggleRowSelection(row)
}

const getAreaList = async () => {
  areaLoading.value = true
  try {
    const warehouseIds = selectedWarehouseIds.value
    const data = await WarehouseAreaApi.getWarehouseAreaPage({
      ...areaQueryParams,
      warehouseId: warehouseIds.length === 1 ? warehouseIds[0] : undefined,
      warehouseIds: warehouseIds.join(',')
    })
    areaList.value = data?.list || []
    areaTotal.value = data?.total || 0
    await syncTableSelection(areaTableRef, areaList.value, selectedAreaIds.value)
  } finally {
    areaLoading.value = false
  }
}

const openAreaDialog = async () => {
  if (selectedWarehouseIds.value.length === 0) {
    message.warning(t('ErpStock.Check.validatorSelectWarehouseFirst'))
    return
  }
  areaDialogVisible.value = true
  areaSelection.value = [...selectedAreas.value]
  await getAreaList()
}

const handleAreaQuery = () => {
  areaQueryParams.pageNo = 1
  getAreaList()
}

const resetAreaQuery = () => {
  areaQueryParams.pageNo = 1
  areaQueryParams.areaCode = undefined
  areaQueryParams.areaName = undefined
  getAreaList()
}

const confirmAreaSelection = () => {
  selectedAreas.value = [...areaSelection.value]
  areaDialogVisible.value = false
}

const handleAreaRowClick = (row: WarehouseAreaVO) => {
  areaTableRef.value?.toggleRowSelection(row)
}

const getProductList = async () => {
  productLoading.value = true
  try {
    const data = await ProductApi.getProductPage({
      ...productQueryParams,
      categoryType: formData.value.categoryType
    })
    productList.value = data?.list || []
    productTotal.value = data?.total || 0
    await syncTableSelection(productTableRef, productList.value, selectedProductIds.value)
  } finally {
    productLoading.value = false
  }
}

const openProductDialog = async () => {
  productDialogVisible.value = true
  productSelection.value = [...selectedProducts.value]
  await getProductList()
}

const handleProductQuery = () => {
  productQueryParams.pageNo = 1
  getProductList()
}

const resetProductQuery = () => {
  productQueryParams.pageNo = 1
  productQueryParams.barCode = undefined
  productQueryParams.name = undefined
  getProductList()
}

const confirmProductSelection = () => {
  selectedProducts.value = [...productSelection.value]
  productDialogVisible.value = false
}

const handleProductRowClick = (row: ProductVO) => {
  productTableRef.value?.toggleRowSelection(row)
}

const normalizeGeneratedItems = (data: any) => {
  if (Array.isArray(data)) {
    return data
  }
  return data?.list || []
}

const openGeneratedItemDialog = async () => {
  if (formData.value.sourceType === 1 && selectedWarehouseIds.value.length === 0) {
    message.warning(t('ErpStock.Check.validatorSelectWarehouseFirst'))
    return
  }
  if (formData.value.sourceType === 2 && selectedProductIds.value.length === 0) {
    message.warning(t('ErpStock.Check.validatorSelectProductFirst'))
    return
  }
  generatedItemDialogVisible.value = true
  generatedItemLoading.value = true
  try {
    const data =
      formData.value.sourceType === 1
        ? await StockCheckApi.generateItemsByLocation({
          warehouseIds: selectedWarehouseIds.value,
          ...(selectedAreaIds.value.length > 0 ? { areaIds: selectedAreaIds.value } : {}),
          categoryType: formData.value.categoryType,
          allowEmpty: true
        })
        : await StockCheckApi.generateItemsByProduct({
          productIds: selectedProductIds.value,
          categoryType: formData.value.categoryType,
          allowEmpty: true
        })
    generatedItemList.value = normalizeGeneratedItems(data)
    generatedItemSelection.value = [...(formData.value.items || [])]
    await syncGeneratedItemSelection()
  } finally {
    generatedItemLoading.value = false
  }
}

const getGeneratedItemRowKey = (row: StockCheckItemVO) =>
  [row.id, row.warehouseId, row.areaId, row.productId].filter((item) => item !== undefined).join('_')

const syncGeneratedItemSelection = async () => {
  const selectedKeys = new Set((formData.value.items || []).map((item) => getGeneratedItemRowKey(item)))
  await nextTick()
  generatedItemTableRef.value?.clearSelection()
  generatedItemList.value.forEach((row) => {
    if (selectedKeys.has(getGeneratedItemRowKey(row))) {
      generatedItemTableRef.value?.toggleRowSelection(row, true)
    }
  })
}

const handleGeneratedItemRowClick = (row: StockCheckItemVO) => {
  generatedItemTableRef.value?.toggleRowSelection(row)
}

const confirmGeneratedItemSelection = () => {
  formData.value.items = generatedItemSelection.value.map((item) => ({
    ...item,
    actualCount: item.actualCount ?? item.stockCount ?? 0,
    count: item.count ?? 0
  }))
  generatedItemDialogVisible.value = false
}

const getWarehouseName = (warehouseId?: number) => {
  return (
    selectedWarehouses.value.find((item) => item.id === warehouseId)?.name ||
    warehouseList.value.find((item) => item.id === warehouseId)?.name ||
    '-'
  )
}

const getSubmitData = () => {
  const items = (formData.value.items || []).map((item) => {
    const submitItem = {
      id: item.id,
      warehouseId: item.warehouseId,
      areaId: item.areaId,
      productId: item.productId,
      productPrice: item.productPrice,
      stockCount: item.stockCount,
      count: item.count,
      remark: item.remark
    } as Record<string, unknown>
    if (formType.value !== 'create') {
      submitItem.actualCount = item.actualCount
    }
    return submitItem
  })

  return {
    id: formData.value.id,
    checkTime: formData.value.checkTime,
    sourceType: formData.value.sourceType,
    categoryType: formData.value.categoryType,
    checkStatus: isInventoryCheck.value ? formData.value.checkStatus : undefined,
    remark: formData.value.remark,
    items
  } as StockCheckVO
}

const submitForm = async (checkStatus?: 0 | 1) => {
  await formRef.value.validate()
  if (!formData.value.items?.length) {
    message.warning(t('ErpStock.Check.validatorSelectCheckItem'))
    return
  }
  if (checkStatus === 1 && hasIncompleteActualCount.value) {
    message.warning(t('ErpStock.Check.validatorCompleteCheckInfo'))
    return
  }
  if (checkStatus === 1) {
    const zeroCountItems = (formData.value.items || []).filter((item) => Number(item.actualCount) === 0)
    if (zeroCountItems.length > 0) {
      const itemNames = zeroCountItems.map((item) => getCheckItemName(item)).join('、')
      await message.confirm(`${itemNames}${t('ErpStock.Check.confirmActualCountZero')}`)
    }
  }
  if (isInventoryCheck.value) {
    formData.value.checkStatus = checkStatus
    formData.value.items.forEach((item) => {
      if (isActualCountEmpty(item.actualCount)) {
        return
      }
      const actualCount = Number(item.actualCount ?? 0)
      const stockCount = Number(item.stockCount ?? 0)
      item.count = actualCount - stockCount
    })
  }

  formLoading.value = true
  try {
    const data = getSubmitData()
    if (formType.value === 'create') {
      await StockCheckApi.createStockCheck(data)
      message.success(t('common.createSuccess'))
    } else {
      await StockCheckApi.updateStockCheck(data)
      message.success(t('common.updateSuccess'))
    }
    dialogVisible.value = false
    emit('success')
  } finally {
    formLoading.value = false
  }
}

const resetForm = () => {
  formRef.value?.resetFields()
  formData.value = {
    id: undefined,
    no: undefined,
    checkTime: getCurrentTime(),
    sourceType: 1,
    categoryType: getDefaultCategoryType(),
    remark: undefined,
    items: [],
    approveRecords: []
  }
  detailActiveTab.value = 'items'
  clearSelections()
}
</script>

<style scoped>
.stock-check-selector-form {
  max-width: 760px;
}

.stock-check-selector-form :deep(.el-form-item) {
  width: 100%;
}

.stock-check-selector-form :deep(.el-form-item__content) {
  min-width: 0;
}

.stock-check-selector-form :deep(.el-input) {
  width: 100%;
}

.stock-check-bottom-form {
  margin-top: 16px;
}

.stock-check-bottom-form :deep(.el-form-item) {
  margin-bottom: 0;
}

.stock-check-detail-tabs {
  margin-top: 12px;
}

.stock-check-dialog-pagination {
  padding-top: 12px;
  padding-bottom: 56px;
}
</style>
