<script lang="ts" setup>
import BasePageableTable from "@/components/base/base-pageable-table/BasePageableTable.vue";
import DefaultToolButton from "@/components/base/default-tool-button/DefaultToolButton.vue";
import DefaultOperateButtonColumn from "@/components/base/default-column/DefaultOperateButtonColumn.vue";
import DefaultStatusSwitchColumn from "@/components/base/default-column/DefaultStatusSwitchColumn.vue";
import { usePage } from "@/composables/use-page";
import BaseFormWithTable from "@/components/base/base-form-with-table/BaseFormWithTable.vue";
import BaseSelect from "@/components/base/base-select/BaseSelect.vue";
import BaseTableForm from "@/components/base/base-table-form/BaseTableForm.vue";
import { $t } from "@/common/languages";
import type { FormInstance, FormRules } from "element-plus";
import { formatDate } from "@/common/utils/format-utils";
import { get, post } from "@/common/http/request";
import { ElMessage } from "element-plus";
import type { FieldMappingConfig } from "@/components/base/base-form-with-table/type";
import { ref } from "vue";
import { useStatus } from "@/common/languages/mapping/base-info-mapping";
import Decimal from "decimal.js";
import ExpandablePageableTable from "@/components/base/expandable-pageable-table/ExpandablePageableTable.vue";
import BaseItemDialog from "@/components/base/base-item-dialog/BaseItemDialog.vue";

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

const getPageUrl = "/purchase/purchaseplan/getPurchasePlanPage";
const addUrl = "/purchase/purchaseplan/addPurchasePlan";
const editUrl = "/purchase/purchaseplan/updatePurchasePlan";
const removeUrl = "/purchase/purchaseplan/deletePurchasePlan";
const getItemsUrl = "/purchase/purchaseplan/getPurchasePlanItemsWithVendorSuggestions";
const generateOrderUrl = "/purchase/purchaseplan/generatePurchaseOrder";
const getItemUrl = "/purchase/purchaseplan/getPurchasePlanItems";
const partNumberExistsUrl = "/warehouse/warehouseitem/existsWarehouseItem";
const searchers = [
  { name: "searchCode", type: "text" as const, placeholder: $t("_prop.purchase.purchase_plan.searchCode") },
];

const { getPurchasePlanStatusLabel, getPurchasePlanItemStatusLabel } = useStatus();
const rules = reactive<FormRules>({
  planName: [{ required: true, message: $t("_message.purchase.purchase_plan.input_planName"), trigger: "blur" }],
  vendorId: [{ required: true, message: $t("_message.purchase.purchase_plan.select_vendor"), trigger: "blur" }],
  storeNo: [{ required: true, message: $t("_message.purchase.purchase_plan.select_store"), trigger: "blur" }],
  planItems: [
    {
      required: true,
      validator: (rule, value, callback) => {
        if (value === undefined || value.length === 0) {
          callback($t("_message.purchase.purchase_plan.upload_planItems"));
        }
        callback();
      },
      trigger: "change",
    },
  ],
});
const itemArrayName = "planItems";

/**
 * 验证物料编号是否存在
 */
const validatePartNumber = (rule: any, value: string, callback: (error?: Error) => void) => {
  if (!value) {
    callback(new Error($t("_message.purchase.purchase_plan_item.input_partNumber")));
    return;
  }
  get(partNumberExistsUrl, { partNumber: value })
    .then(res => {
      if (res.data === true) {
        callback();
      } else {
        callback(new Error($t("_message.warehouse.warehouse_item.not_exist_partNumber")));
      }
    })
    .catch(() => {
      callback();
    });
};

/**
 * 基本不变通用变量
 */
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 generateOrderVisible = ref(false);
const generateOrderForm = reactive({
  planId: 0,
  planStatus: 0,
  planNo: "",
});
const planItems = ref([] as any[]);
const allVendors = ref([] as any[]);
const partVendorMappings = ref([] as any[]);

const NOT_PURCHASE_VENDOR_ID = -1;

const add = () => {
  form.value = {
    planItems: [],
  };
  title.value = "_title.purchase.purchase_plan.add";
  visible.value = true;
  formType.value = false;
};
const edit = (row: any) => {
  title.value = "_title.purchase.purchase_plan.edit";
  form.value = { ...row };
  visible.value = true;
  formType.value = true;
};
const remove = (row: any) => {
  useRemove(removeUrl, row.id, "_message.purchase.purchase_plan.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 authShowFunc = (row: any, button: globalThis.ButtonProp) => {
  if (row.planStatus === 2 && button.eventName === "generatePurchaseOrder") {
    return false;
  }
  return true;
};

// 采购计划状态标签类型映射
const getPurchasePlanStatusTagType = (code: number | null): string => {
  const tagTypeMap: Record<number, string> = {
    0: "warning", // 待处理
    1: "primary", // 进行中
    2: "success", // 已完成
  };
  return tagTypeMap[code ?? -1] || "info";
};

const operateButtonClick = (eventName: string, row: any) => {
  switch (eventName) {
    case "edit":
      edit(row);
      break;
    case "remove":
      remove(row);
      break;
    case "generatePurchaseOrder":
      showGenerateOrderDialog(row);
      break;
    case "showItem":
      showItem(row);
      break;
  }
};

const buildVendorSuggestions = (item: any) => {
  const suggestions: any[] = [];
  const addedVendorIds = new Set<number>();

  const vendorCode1 = item.vendorCode1;
  const vendorCode2 = item.vendorCode2;
  const vendorCode3 = item.vendorCode3;

  const vendorCodes = [vendorCode1, vendorCode2, vendorCode3];
  for (let i = 0; i < vendorCodes.length; i++) {
    if (vendorCodes[i] != null && !addedVendorIds.has(vendorCodes[i])) {
      const vendor = allVendors.value.find((v: any) => v.vendorId === vendorCodes[i]);
      if (vendor) {
        const mapping = partVendorMappings.value.find(
          (m: any) => m.partNumber === item.partNumber && m.vendorId === vendor.vendorId
        );
        suggestions.push({
          vendorId: vendor.vendorId,
          vendorName: vendor.vendorName,
          priority: i + 1,
          price: mapping?.costPrice || 0,
        });
        addedVendorIds.add(vendor.vendorId);
      }
    }
  }

  const itemMappings = partVendorMappings.value.filter((m: any) => m.partNumber === item.partNumber);
  for (const mapping of itemMappings) {
    if (!addedVendorIds.has(mapping.vendorId)) {
      const vendor = allVendors.value.find((v: any) => v.vendorId === mapping.vendorId);
      if (vendor) {
        suggestions.push({
          vendorId: vendor.vendorId,
          vendorName: vendor.vendorName,
          priority: 2,
          price: mapping.costPrice || 0,
        });
        addedVendorIds.add(vendor.vendorId);
      }
    }
  }

  for (const vendor of allVendors.value) {
    if (!addedVendorIds.has(vendor.vendorId)) {
      suggestions.push({
        vendorId: vendor.vendorId,
        vendorName: vendor.vendorName,
        priority: 3,
        price: 0,
      });
      addedVendorIds.add(vendor.vendorId);
    }
  }

  suggestions.push({
    vendorId: NOT_PURCHASE_VENDOR_ID,
    vendorName: "暂不采购",
    priority: 99,
    price: 0,
  });

  return suggestions;
};

const showGenerateOrderDialog = async (row: any) => {
  generateOrderForm.planId = row.id;
  generateOrderForm.planStatus = row.planStatus;
  generateOrderForm.planNo = row.planNo;

  try {
    const response = await get(getItemsUrl, { planId: row.id });
    const data = response.data;

    allVendors.value = data.allVendors || [];
    partVendorMappings.value = data.partVendorMappings || [];
    planItems.value = (data.items || []).map((item: any) => {
      const currentCount = item.currentCount || item.purchaseCount || 1;
      const price = item.price || 0;

      return {
        ...item,
        currentCount,
        price,
        total: new Decimal(currentCount).mul(price).toNumber(),
        vendorSuggestions: [],
        calculateTotal: function () {
          this.total = new Decimal(this.currentCount).mul(this.price).toNumber();
        },
      };
    });

    for (const item of planItems.value) {
      item.vendorSuggestions = buildVendorSuggestions(item);
      if (item.completeStatus === 0 && item.vendorSuggestions.length > 0) {
        const firstSuggestion = item.vendorSuggestions[0];
        if (firstSuggestion.vendorId !== NOT_PURCHASE_VENDOR_ID) {
          item.vendorId = firstSuggestion.vendorId;
          item.price = firstSuggestion.price || 0;
          item.calculateTotal();
        }
      } else if (item.completeStatus !== 0 && item.vendorId) {
        const vendor = allVendors.value.find((v: any) => v.vendorId === item.vendorId);
        if (vendor) {
          item.vendorName = vendor.vendorName;
        }
      }
    }

    planItems.value.sort((a, b) => a.completeStatus - b.completeStatus);

    generateOrderVisible.value = true;
  } catch (error) {
    ElMessage.error($t("_message.purchase.purchase_plan.get_items_error") + error);
  }
};

const onVendorChange = (item: any, vendorId: number) => {
  if (item.vendorSuggestions && item.vendorSuggestions.length > 0) {
    const selectedVendor = item.vendorSuggestions.find((v: any) => v.vendorId === vendorId);
    if (selectedVendor) {
      if (selectedVendor.vendorId !== NOT_PURCHASE_VENDOR_ID) {
        item.price = selectedVendor.price || 0;
      }
      item.calculateTotal();
    }
  }
};

const generatePurchaseOrder = async () => {
  const validItems = planItems.value.filter(
    item => item.vendorId && item.vendorId !== NOT_PURCHASE_VENDOR_ID && item.completeStatus === 0
  );

  if (validItems.length === 0) {
    ElMessage.warning($t("_message.purchase.purchase_plan.select_vendor"));
    return;
  }

  try {
    const vendorGroups = new Map<number, any[]>();
    validItems.forEach(item => {
      if (!vendorGroups.has(item.vendorId)) {
        vendorGroups.set(item.vendorId, []);
      }
      vendorGroups.get(item.vendorId)!.push(item);
    });

    const now = new Date();
    const baseFormCode =
      "PO" +
      now.getFullYear() +
      String(now.getMonth() + 1).padStart(2, "0") +
      String(now.getDate()).padStart(2, "0") +
      String(now.getHours()).padStart(2, "0") +
      String(now.getMinutes()).padStart(2, "0") +
      String(now.getSeconds()).padStart(2, "0");

    const promises: Promise<any>[] = [];
    let orderIndex = 1;
    vendorGroups.forEach((items, vendorId) => {
      const vendor = allVendors.value.find((v: any) => v.vendorId === vendorId);
      const vendorName = vendor ? vendor.vendorName : "";

      const formCode = baseFormCode + String(orderIndex).padStart(2, "0");
      const formName = `采购订单-${vendorName}-${formCode}`;
      const formMark = `采购计划【${generateOrderForm.planNo}】生成`;

      const totalValue = items.reduce((sum, item) => {
        return new Decimal(sum).add(new Decimal(item.currentCount).mul(item.price)).toNumber();
      }, 0);

      const data = {
        planId: generateOrderForm.planId,
        vendorId: vendorId,
        vendorName: vendorName,
        formCode: formCode,
        formName: formName,
        formMark: formMark,
        totalValue: totalValue,
        selectedItems: items,
      };

      promises.push(post(generateOrderUrl, data));
      orderIndex++;
    });

    await Promise.all(promises);
    ElMessage.success($t("_message.purchase.purchase_plan.generate_order_success"));
    generateOrderVisible.value = false;
    tableRef.value?.reload();
  } catch (err: any) {
    ElMessage.error(err.response?.data?.message || $t("_message.purchase.purchase_plan.generate_order_error"));
  }
};

const mappingConfig: FieldMappingConfig = {
  partNumber: {
    sourceKey: "物料编号",
    defaultValue: "",
  },

  purchaseCount: {
    sourceKey: "计划数量",
    defaultValue: 0,
    transform: (val: any) => {
      const num = Number(val);
      return isNaN(num) ? 0 : num;
    },
  },

  price: {
    sourceKey: "单价",
    defaultValue: 0,
    transform: (val: any) => {
      const num = Number(val);
      return isNaN(num) ? 0 : num;
    },
  },

  currentCount: {
    sourceKey: "本次采购数量",
    defaultValue: 0,
    transform: (val: any) => {
      const num = Number(val);
      return isNaN(num) ? 0 : num;
    },
  },
};
</script>
<template>
  <ExpandablePageableTable
    :url="getPageUrl"
    :searchers="searchers"
    ref="tableRef"
    :item-url="getItemUrl"
    item-id-key="id"
    item-id-name="planId"
    item-field-name="planItems"
  >
    <template #tool-button>
      <DefaultToolButton @top-button-click="topButtonClick" />
    </template>
    <template #columns>
      <el-table-column :label="$t('_prop.purchase.purchase_plan.planNo')" prop="planNo" width="150" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.planName')" prop="planName" width="180" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.storeName')" prop="storeName" width="150" />
      <DefaultStatusSwitchColumn
        status-param-name="planStatus"
        :status-label-mapping="getPurchasePlanStatusLabel"
        :tag-type-mapping="getPurchasePlanStatusTagType"
      />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.remask')" prop="remask" width="200" />
      <el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" width="150" />
      <DefaultOperateButtonColumn @operate-button-click="operateButtonClick" :auth-show-func="authShowFunc" />
    </template>
    <template #item-content="{ itemData }">
      <el-table :data="itemData" size="small" border stripe>
        <el-table-column :label="$t('_prop.purchase.purchase_plan_item.partNumber')" prop="partNumber" width="150" />
        <el-table-column :label="$t('_prop.purchase.purchase_plan.model')" prop="productSpecs" width="150" />
        <el-table-column
          :label="$t('_prop.purchase.purchase_plan_item.purchaseCount')"
          prop="purchaseCount"
          width="120"
        />
        <el-table-column :label="$t('_prop.purchase.purchase_plan_item.price')" prop="price" width="120" />
        <el-table-column
          :label="$t('_prop.purchase.purchase_plan_item.currentCount')"
          prop="currentCount"
          width="120"
        />
      </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.purchase.purchase_plan.baseTitle')"
    :table-title="$t('_title.purchase.purchase_plan.tableTitle')"
    item-array-name="planItems"
    :mapping-config="mappingConfig"
    :template-file-name="$t('_title.purchase.purchase_plan.templateFileName')"
  >
    <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.purchase.purchase_plan.planName')" prop="planName">
            <el-input v-model="form.planName" :placeholder="$t('_message.purchase.purchase_plan.input_planName')" />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('_prop.purchase.purchase_plan.vendorName')" prop="vendorId">
            <BaseSelect
              v-model="form.vendorId"
              :url="'/sys/vendor/getVendorList'"
              :placeholder="$t('_message.purchase.purchase_plan.select_vendor')"
            />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('_prop.purchase.purchase_plan.storeName')" prop="storeNo">
            <BaseSelect
              v-model="form.storeNo"
              :url="'/warehouse/warehouse/getWarehouseSelectList'"
              :placeholder="$t('_message.purchase.purchase_plan.select_store')"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item :label="$t('_prop.purchase.purchase_plan.remask')" prop="remask">
        <el-input
          v-model="form.remask"
          :placeholder="$t('_message.purchase.purchase_plan.input_remask')"
          type="textarea"
          autosize
        />
      </el-form-item>
    </template>
    <template #form-table-columns>
      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.partNumber')" width="150">
        <template #default="{ row, $index }">
          <el-form-item
            :prop="`${itemArrayName}.${$index}.partNumber`"
            :rules="[{ required: true, validator: validatePartNumber, trigger: 'blur' }]"
          >
            <el-input v-model="row.partNumber" size="small" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.purchaseCount')" width="150">
        <template #default="{ row, $index }">
          <el-form-item
            :prop="`${itemArrayName}.${$index}.purchaseCount`"
            :rules="[
              {
                required: true,
                message: $t('_message.purchase.purchase_plan_item.input_purchaseCount'),
                trigger: 'blur',
              },
            ]"
          >
            <el-input-number v-model="row.purchaseCount" size="small" :min="1" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.price')" width="150">
        <template #default="{ row, $index }">
          <el-form-item
            :prop="`${itemArrayName}.${$index}.price`"
            :rules="[
              { required: true, message: $t('_message.purchase.purchase_plan_item.input_price'), trigger: 'blur' },
            ]"
          >
            <el-input-number v-model="row.price" size="small" :min="0" :step="0.01" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.currentCount')" width="150">
        <template #default="{ row, $index }">
          <el-form-item
            :prop="`${itemArrayName}.${$index}.currentCount`"
            :rules="[
              {
                required: true,
                message: $t('_message.purchase.purchase_plan_item.input_currentCount'),
                trigger: 'blur',
              },
            ]"
          >
            <el-input-number v-model="row.currentCount" size="small" :min="1" />
          </el-form-item>
        </template>
      </el-table-column>
    </template>
  </BaseFormWithTable>

  <!-- 生成采购订单对话框 -->
  <BaseTableForm
    v-model:visible="generateOrderVisible"
    :title="$t('_title.purchase.purchase_plan.generateOrder')"
    :table-data="planItems"
    :show-summary="false"
    :selectable="false"
    :use-auth="false"
  >
    <!-- 自定义表格列 -->
    <template #table-columns>
      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.partNumber')" prop="partNumber" width="150" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.model')" prop="productSpecs" width="150" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.vendorName')" width="180">
        <template #default="{ row }">
          <template v-if="row.completeStatus === 0">
            <el-select
              v-model="row.vendorId"
              :placeholder="$t('_message.purchase.purchase_plan.select_vendor')"
              style="width: 100%"
              @change="onVendorChange(row, row.vendorId)"
              :disabled="row.completeStatus !== 0"
            >
              <el-option
                v-for="vendor in row.vendorSuggestions"
                :key="vendor.vendorId"
                :label="vendor.vendorName"
                :value="vendor.vendorId"
              >
                <span>{{ vendor.vendorName }}</span>
                <span v-if="vendor.priority === 1" style="margin-left: 8px; color: #67c23a">(优先)</span>
                <span v-if="vendor.priority === 99" style="margin-left: 8px; color: #909399">(跳过)</span>
                <span
                  v-if="vendor.price && vendor.price > 0 && vendor.priority !== 99"
                  style="margin-left: 8px; color: #909399"
                >
                  ¥{{ vendor.price }}
                </span>
              </el-option>
            </el-select>
          </template>
          <template v-else>
            <span>{{ row.vendorName }}</span>
          </template>
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.purchase.purchase_plan.demandQuantity')" prop="purchaseCount" width="120" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.packQuantity')" prop="productPacking" width="120" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.purchaseQuantity')" width="150">
        <template #default="{ row }">
          <el-input-number
            v-model="row.currentCount"
            :min="1"
            @change="row.calculateTotal()"
            style="width: 100%"
            :disabled="row.completeStatus !== 0"
          />
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.purchase.purchase_plan.unitPrice')" width="130">
        <template #default="{ row }">
          <el-input-number
            v-model="row.price"
            :min="0"
            :step="0.01"
            @change="row.calculateTotal()"
            style="width: 100%"
            :disabled="row.completeStatus !== 0"
          />
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.purchase.purchase_plan.totalPrice')" prop="total" width="120" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.purchaseStatus')" width="120">
        <template #default="{ row }">
          <span>{{ getPurchasePlanItemStatusLabel(row.completeStatus) }}</span>
        </template>
      </el-table-column>
    </template>

    <!-- 底部附加内容：自定义按钮 -->
    <template #attachment>
      <el-button
        type="primary"
        :disabled="
          !planItems.some(
            item => item.vendorId && item.vendorId !== NOT_PURCHASE_VENDOR_ID && item.completeStatus === 0
          )
        "
        @click="generatePurchaseOrder"
      >
        {{ $t("_button.confirm") }}
      </el-button>
    </template>
  </BaseTableForm>
  <BaseItemDialog
    :title="$t('_title.purchase.purchase_plan.showItem')"
    v-model:visible="itemVisible"
    :url="getItemUrl"
    parent-param-name="planId"
    v-model:parent-param-value="itemParentId"
  >
    <template #columns>
      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.partNumber')" prop="partNumber" width="150" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan.model')" prop="productSpecs" width="150" />
      <el-table-column
        :label="$t('_prop.purchase.purchase_plan_item.purchaseCount')"
        prop="purchaseCount"
        width="120"
      />
      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.price')" prop="price" width="120" />
      <el-table-column :label="$t('_prop.purchase.purchase_plan_item.currentCount')" prop="currentCount" width="120" />
    </template>
  </BaseItemDialog>
</template>
