<script lang="ts" setup>
import DefaultToolButton from "@/components/base/default-tool-button/DefaultToolButton.vue";
import DefaultOperateButtonColumn from "@/components/base/default-column/DefaultOperateButtonColumn.vue";
import { usePage } from "@/composables/use-page";
import { $t } from "@/common/languages";
import { ElMessage, type FormInstance, type FormItemRule, type FormRules } from "element-plus";
import BaseItemDialog from "@/components/base/base-item-dialog/BaseItemDialog.vue";
import BaseFormWithTable from "@/components/base/base-form-with-table/BaseFormWithTable.vue";
import { get } from "@/common/http/request";
import { type FieldMappingConfig, type DetailLoadConfig } from "@/components/base/base-form-with-table/type";
import ExpandablePageableTable from "@/components/base/expandable-pageable-table/ExpandablePageableTable.vue";

/**
 * 必须要的变量
 */

const getPageUrl = "/production/bom/getBomPage";
const addUrl = "/production/bom/addBom";
const editUrl = "/production/bom/updateBom";
const removeUrl = "/production/bom/deleteBom";
const itemUrl = "/production/bom/getBomItemList";
const partNumberExistsUrl = "/warehouse/warehouseitem/existsWarehouseItem";
const searchers = [
  { name: "searchCode", type: "text" as const, placeholder: $t("_prop.production.bom.searchCode") },
  { name: "partNumber", type: "text" as const, placeholder: $t("_prop.production.bom_item.partNumber") },
];
const rules = reactive<FormRules>({
  bomNo: [{ required: true, message: $t("_message.production.bom.input_bomNo"), trigger: "blur" }],
  bomName: [{ required: true, message: $t("_message.production.bom.input_bomName"), trigger: "blur" }],
  manufacturer: [{ required: true, message: $t("_message.production.bom.input_manufacturer"), trigger: "blur" }],
  spec: [{ required: true, message: $t("_message.production.bom.input_spec"), trigger: "blur" }],
  brandName: [{ required: true, message: $t("_message.production.bom.input_brandName"), trigger: "blur" }],
  formMark: [{ required: false, message: $t("_message.production.bom.input_formMark"), trigger: "blur" }],
  partNumber: [
    {
      required: true,
      validator: (rule, value, callback) => {
        if (!value) {
          callback($t("_message.warehouse.warehouse_item.input_productNumber"));
        }
        (async () => {
          try {
            const isExists = await get(partNumberExistsUrl, { partNumber: value }).then(res => res.data);
            if (isExists) {
              callback();
            }
            callback($t("_message.warehouse.warehouse_item.not_exist_partNumber"));
          } catch (err: any) {
            callback(new Error(err));
          }
        })();
      },
      trigger: "blur",
    },
  ],
  bomItems: [
    {
      required: true,
      validator: (rule, value, callback) => {
        if (value === undefined || value.length === 0) {
          callback($t("_message.production.bom.upload_bomitems"));
        }
        callback();
      },
      trigger: "change",
    },
  ],
});
const itemArrayName = "bomItems";
/**
 * 基本不变通用变量
 */
const tableRef = ref<InstanceType<typeof ExpandablePageableTable> | null>(null);
const { useAdd, useEdit, useRemove, useGeneralPageRef } = usePage(tableRef);
const { title, visible, formType, form, itemVisible, itemParentId } = useGeneralPageRef();
const baseFormWithTableRef = ref<InstanceType<typeof BaseFormWithTable>>();
/**
 * 可以自定义的变量
 */

const add = () => {
  form.value = {};
  title.value = "_title.production.bom.add";
  visible.value = true;
  formType.value = false;
};
const edit = (row: any) => {
  title.value = "_title.production.bom.edit";
  form.value = { ...row };
  visible.value = true;
  formType.value = true;
};
const remove = (row: any) => {
  useRemove(removeUrl, row.id, "_message.production.bom.delete_message");
};
const showItem = (row: any) => {
  itemParentId.value = row.id;
  itemVisible.value = true;
};
// const submit = (form: any, formRef: FormInstance | undefined) => {
//   if (formRef !== undefined) {
//     formRef.validate(valid => {
//       if (valid) {
//         if (formType.value) useEdit(editUrl, form, visible);
//         else useAdd(addUrl, form, visible);
//       }
//     });
//   }
// };
const topButtonClick = (eventName: string) => {
  switch (eventName) {
    case "add":
      add();
      break;
  }
};
const operateButtonClick = (eventName: string, row: any) => {
  switch (eventName) {
    case "edit":
      edit(row);
      break;
    case "remove":
      remove(row);
      break;
    case "showItem":
      showItem(row);
      break;
  }
};

const mappingConfig: FieldMappingConfig = {
  partNumber: {
    sourceKey: ["商品编号", "partNumber"],
    header: $t("_prop.production.bom_item.partNumber"),
    width: 20,
    defaultValue: "",
  },
  itemPosition: {
    sourceKey: ["位号", "itemPosition"],
    header: $t("_prop.production.bom_item.itemPosition"),
    width: 20,
    defaultValue: "",
  },
  manufactureCount: {
    sourceKey: ["用量", "manufactureCount"],
    header: $t("_prop.production.bom_item.manufactureCount"),
    width: 15,
    defaultValue: 0,
    transform: (val: any) => {
      const num = Number(val);
      return isNaN(num) ? 0 : num;
    },
  },
  productMark: {
    sourceKey: ["备注", "productMark"],
    header: $t("_prop.production.bom_item.productMark"),
    width: 20,
    defaultValue: "",
  },
  sameUseNum1: {
    sourceKey: ["替换料1", "sameUseNum1"],
    header: $t("_prop.production.bom_item.sameUseNum") + "1",
    width: 20,
    defaultValue: "",
  },
  sameUseNum2: {
    sourceKey: ["替换料2", "sameUseNum2"],
    header: $t("_prop.production.bom_item.sameUseNum") + "2",
    width: 20,
    defaultValue: "",
  },
  sameUseNum3: {
    sourceKey: ["替换料3", "sameUseNum3"],
    header: $t("_prop.production.bom_item.sameUseNum") + "3",
    width: 20,
    defaultValue: "",
  },
  sameUseCount: {
    sourceKey: ["替换料数量", "sameUseCount"],
    header: $t("_prop.production.bom_item.sameUseCount"),
    width: 15,
    defaultValue: 0,
    transform: (val: any) => {
      const num = Number(val);
      return isNaN(num) ? 0 : num;
    },
  },
};

const detailConfig: DetailLoadConfig = {
  url: itemUrl,
  paramName: "bomId",
  dataPath: "data",
};
const validateManufactureCount = (index: number) => {
  return [
    {
      required: true,
      validator: (rule: any, value: any, callback: any) => {
        if (!value) {
          callback($t("_message.production.bom.input_manufactureCount"));
        }
        if (
          form.value["bomItems"][index].itemPosition === undefined ||
          form.value["bomItems"][index].itemPosition.split(",").length !== Number(value)
        ) {
          callback($t("_message.production.bom.unpair_manufactureCount_itemPosition"));
        }
        callback();
      },
      trigger: "blur",
    },
  ];
};

/**
 * 【新增】存储每一行的位号错误信息
 * Key: 行索引 ($index)
 * Value: 错误消息
 */
const itemPositionErrors = ref<Record<number, string>>({});

/**
 * 【核心】查重并更新错误状态
 */
const checkItemPositionUnique = (formRef: FormInstance) => {
  const items = form.value?.[itemArrayName] || [];
  if (!items.length) return true;

  const countMap = new Map<string, number[]>();
  const newErrors: Record<number, string> = {};

  // 1. 统计所有位号
  items.forEach((row: any, index: number) => {
    const val = row.itemPosition;
    if (!val) return;

    const positions = String(val)
      .split(",")
      .map((s: string) => s.trim())
      .filter((s: string) => s !== "");

    positions.forEach((pos: string) => {
      if (!countMap.has(pos)) {
        countMap.set(pos, []);
      }
      countMap.get(pos)!.push(index);
    });
  });

  let hasError = false;

  // 2. 找出重复项，构建新的错误对象
  for (const [pos, indices] of countMap.entries()) {
    if (indices.length > 1) {
      hasError = true;
      const rowNumbers = indices.map(i => i + 1).join("、");
      const errorMsg = `位号 "${pos}" 在第 ${rowNumbers} 行重复`;

      // 将错误信息记录到涉及的所有行
      indices.forEach(rowIndex => {
        // 如果该行已有其他错误，可以追加，这里直接覆盖或保留最新的
        newErrors[rowIndex] = errorMsg;
      });
    }
  }

  // 3. 更新响应式数据
  itemPositionErrors.value = newErrors;

  // 4. 【关键】强制重新验证以触发红框
  if (hasError) {
    // 先清除所有位号列的旧验证状态
    const fieldsToClear = items.map((_: any, idx: number) => `${itemArrayName}.${idx}.itemPosition`);
    formRef.clearValidate(fieldsToClear);

    // 稍微延迟一下（确保 DOM 和响应式更新），然后强制验证有错误的字段
    // 或者直接验证所有，让 validator 去读 itemPositionErrors
    setTimeout(() => {
      const fieldsToValidate = Object.keys(newErrors).map(idx => `${itemArrayName}.${idx}.itemPosition`);
      if (fieldsToValidate.length > 0) {
        formRef.validateField(fieldsToValidate);
      }
    }, 0);
  } else {
    // 如果没有错误，也清除一下可能残留的状态
    const fieldsToClear = items.map((_: any, idx: number) => `${itemArrayName}.${idx}.itemPosition`);
    formRef.clearValidate(fieldsToClear);
  }

  return !hasError;
};

/**
 * 【修改】验证器工厂：增加对 itemPositionErrors 的检查
 */
const validateItemPosition = (index: number): FormItemRule[] => {
  return [
    {
      required: true,
      validator: (rule: any, value: any, callback: any) => {
        // A. 优先检查是否有全局查重产生的错误
        if (itemPositionErrors.value[index]) {
          callback(new Error(itemPositionErrors.value[index]));
          return;
        }

        // B. 原有逻辑：非空检查
        if (!value) {
          callback($t("_message.production.bom.input_itemPosition"));
          return;
        }

        // C. 原有逻辑：与数量匹配检查
        const count = form.value?.[itemArrayName]?.[index]?.manufactureCount;
        if (count !== undefined && count !== null) {
          const len = String(value)
            .split(",")
            .filter((s: string) => s.trim() !== "").length;
          if (len !== Number(count)) {
            callback($t("_message.production.bom.unpair_manufactureCount_itemPosition"));
            return;
          }
        }

        callback();
      },
      trigger: "blur", // 也可以加 'change'
    },
  ];
};

// 【修改】submit 函数
const submit = (form: any, formRef: FormInstance | undefined) => {
  // 获取真实的 formRef (处理封装组件的情况)
  const targetRef = formRef || (baseFormWithTableRef.value as any)?.baseFormRef;

  if (!targetRef) return;

  // 1. 先运行查重逻辑 (这会更新 itemPositionErrors 并触发部分验证)
  const isUniqueValid = checkItemPositionUnique(targetRef);

  // 2. 执行完整表单验证
  // 注意：checkItemPositionUnique 内部已经调用了 validateField 标红错误项
  // 这里再调用 validate 是为了确保其他字段（如 bomNo 等）也被验证
  targetRef.validate((valid: any) => {
    if (valid && isUniqueValid) {
      if (formType.value) useEdit(editUrl, form, visible);
      else useAdd(addUrl, form, visible);
    } else {
      if (!isUniqueValid) {
        ElMessage.error("位号存在重复，请修正标红处后再提交");
      }
    }
  });
};

// 【修改】Blur 处理
const handleItemPositionBlur = (index: number) => {
  const targetRef = (baseFormWithTableRef.value as any)?.baseFormRef;
  if (targetRef) {
    checkItemPositionUnique(targetRef);
  }
};
</script>
<template>
  <ExpandablePageableTable
    :url="getPageUrl"
    :searchers="searchers"
    ref="tableRef"
    :item-url="itemUrl"
    item-id-key="id"
    item-id-name="bomId"
    itemFieldName="bomItems"
  >
    <template #tool-button>
      <DefaultToolButton @top-button-click="topButtonClick" />
    </template>
    <template #columns>
      <!-- <el-table-column prop="id" type="hidden" width="40" /> -->
      <el-table-column :label="$t('_prop.production.bom.customerName')" prop="customerName" />
      <el-table-column :label="$t('_prop.production.bom.bomName')" prop="bomName" />
      <el-table-column :label="$t('_prop.production.bom.bomNo')" prop="bomNo" />
      <el-table-column :label="$t('_prop.production.bom.manufacturer')" prop="manufacturer" />
      <el-table-column :label="$t('_prop.production.bom.spec')" prop="spec" />
      <el-table-column :label="$t('_prop.production.bom.brandName')" prop="brandName" />
      <el-table-column :label="$t('_prop.production.bom.formMark')" prop="formMark" />
      <DefaultOperateButtonColumn @operate-button-click="operateButtonClick" />
    </template>
    <template #item-content="{ itemData }">
      <el-table :data="itemData" size="small" border stripe>
        <el-table-column :label="$t('_prop.production.bom_item.partNumber')" prop="partNumber" width="150" />
        <el-table-column :label="$t('_prop.production.bom_item.productType')" prop="productType" />
        <el-table-column :label="$t('_prop.production.bom_item.productSpecs')" prop="productSpecs" width="200" />
        <el-table-column :label="$t('_prop.production.bom_item.productPackSize')" prop="productPackSize" />
        <el-table-column :label="$t('_prop.production.bom_item.productBrand')" prop="productBrand" />
        <el-table-column :label="$t('_prop.production.bom_item.manufactureCount')" prop="manufactureCount" />
        <el-table-column :label="$t('_prop.production.bom_item.itemPosition')" prop="itemPosition" width="350" />
        <el-table-column :label="$t('_prop.production.bom_item.sameUseCount')" prop="sameUseCount" />
        <el-table-column :label="$t('_prop.production.bom_item.productMark')" prop="productMark" width="100" />
      </el-table>
    </template>
  </ExpandablePageableTable>
  <BaseFormWithTable
    ref="baseFormWithTableRef"
    v-model:visible="visible"
    @submit="submit"
    v-model:form="form"
    :title="$t(title)"
    :rules="rules"
    :base-title="$t('_title.production.bom.baseTitle')"
    :table-title="$t('_title.production.bom.tableTitle')"
    item-array-name="bomItems"
    :mapping-config="mappingConfig"
    :template-file-name="$t('_title.production.bom.templateFileName')"
    :detail-config="detailConfig"
  >
    <template #form-items>
      <el-form-item prop="id" v-if="false"><el-input v-model="form.id" /></el-form-item>
      <el-row :gutter="20">
        <el-col :span="8">
          <el-form-item :label="$t('_prop.production.bom.bomNo')" prop="bomNo">
            <el-input v-model="form.bomNo" :placeholder="$t('_message.production.bom.input_bomNo')" />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('_prop.production.bom.bomName')" prop="bomName">
            <el-input v-model="form.bomName" :placeholder="$t('_message.production.bom.input_bomName')" />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('_prop.production.bom.manufacturer')" prop="manufacturer">
            <el-input v-model="form.manufacturer" :placeholder="$t('_message.production.bom.input_manufacturer')" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="8">
          <el-form-item :label="$t('_prop.production.bom.spec')" prop="spec">
            <el-input v-model="form.spec" :placeholder="$t('_message.production.bom.input_spec')" />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('_prop.production.bom.brandName')" prop="brandName">
            <el-input v-model="form.brandName" :placeholder="$t('_message.production.bom.input_brandName')" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item :label="$t('_prop.production.bom.formMark')" prop="formMark">
        <el-input
          v-model="form.formMark"
          :placeholder="$t('_message.production.bom.input_formMark')"
          type="textarea"
          autosize
        />
      </el-form-item>
    </template>
    <template #form-table-columns>
      <el-table-column :label="$t('_prop.production.bom_item.partNumber')" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.partNumber`" :rules="rules.partNumber">
            <el-input v-model="row.partNumber" size="small" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.production.bom_item.manufactureCount')" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.manufactureCount`" :rules="validateManufactureCount($index)">
            <el-input-number v-model="row.manufactureCount" size="small" :min="1" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.production.bom_item.itemPosition')" width="200">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.itemPosition`" :rules="validateItemPosition($index)">
            <el-input
              v-model="row.itemPosition"
              size="small"
              type="textarea"
              autosize
              @blur="handleItemPositionBlur($index)"
            />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.production.bom_item.productMark')" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.productMark`">
            <el-input v-model="row.productMark" placeholder="请输入备注" size="small" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.production.bom_item.sameUseNum') + '1'" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.sameUseNum1`">
            <el-input v-model="row.sameUseNum1" placeholder="请输入替换料1" size="small" />
          </el-form-item>
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.production.bom_item.sameUseNum') + '2'" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.sameUseNum2`">
            <el-input v-model="row.sameUseNum2" placeholder="请输入替换料2" size="small" />
          </el-form-item>
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.production.bom_item.sameUseNum') + '3'" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.sameUseNum3`">
            <el-input v-model="row.sameUseNum3" placeholder="请输入替换料3" size="small" />
          </el-form-item>
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.production.bom_item.sameUseCount')" width="120">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.sameUseCount`">
            <el-input-number v-model="row.sameUseCount" size="small" :min="0" />
          </el-form-item>
        </template>
      </el-table-column>
    </template>
  </BaseFormWithTable>
  <BaseItemDialog
    :title="$t('_title.production.bom.showItem')"
    v-model:visible="itemVisible"
    :url="itemUrl"
    parent-param-name="bomId"
    v-model:parent-param-value="itemParentId"
  >
    <template #columns>
      <el-table-column :label="$t('_prop.production.bom_item.partNumber')" prop="partNumber" width="150" />
      <el-table-column :label="$t('_prop.production.bom_item.productType')" prop="productType" />
      <el-table-column :label="$t('_prop.production.bom_item.productSpecs')" prop="productSpecs" width="200" />
      <el-table-column :label="$t('_prop.production.bom_item.productPackSize')" prop="productPackSize" />
      <el-table-column :label="$t('_prop.production.bom_item.productBrand')" prop="productBrand" />
      <el-table-column :label="$t('_prop.production.bom_item.manufactureCount')" prop="manufactureCount" />
      <el-table-column :label="$t('_prop.production.bom_item.itemPosition')" prop="itemPosition" width="350" />
      <el-table-column :label="$t('_prop.production.bom_item.sameUseCount')" prop="sameUseCount" />
      <el-table-column :label="$t('_prop.production.bom_item.productMark')" prop="productMark" width="100" />
    </template>
  </BaseItemDialog>
</template>
