<script lang="ts" setup>
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 { $t } from "@/common/languages";
import { ElMessage, ElMessageBox, type FormInstance, type FormItemRule, type FormRules } from "element-plus";
import BaseFormWithTable from "@/components/base/base-form-with-table/BaseFormWithTable.vue";
import BaseTableForm from "@/components/base/base-table-form/BaseTableForm.vue";
import ExpandablePageableTable from "@/components/base/expandable-pageable-table/ExpandablePageableTable.vue";
import BaseSelect from "@/components/base/base-select/BaseSelect.vue";
import QrCodeDialog from "@/components/base/base-qrcode/QrCodeDialog.vue";
import { get, post } from "@/common/http/request";
import { formatDate } from "@/common/utils/format-utils";
import { generateDucumentNo } from "@/common/utils/document-no-generator/document-no-generator";
import type { FieldMappingConfig } from "@/components/base/base-form-with-table/type";
import Decimal from "decimal.js";

const getPageUrl = "/purchase/purchaseorder/getPurchaseOrderPage";
const addUrl = "/purchase/purchaseorder/addPurchaseOrder";
const editUrl = "/purchase/purchaseorder/updatePurchaseOrder";
const removeUrl = "/purchase/purchaseorder/deletePurchaseOrder";
const getItemsUrl = "/purchase/purchaseorder/getPurchaseOrderItems";
const inboundUrl = "/purchase/purchaseorder/inbound";
const getQrCodeDataUrl = "/purchase/purchaseorder/getQrCodeData";
const getWarehouseSelectListUrl = "/warehouse/warehouse/getWarehouseSelectList";
const getVendorSelectListUrl = "/sys/vendor/getVendorList";
const partNumberExistsUrl = "/warehouse/warehouseitem/existsWarehouseItem";

const searchers = [
  { name: "searchCode", type: "text" as const, placeholder: $t("_prop.purchase.purchase_order.searchCode") },
];

const getFormStatusLabel = (status: number) => {
  const labels: Record<number, string> = {
    0: $t("_status.in_progress"),
    4: $t("_status.completed"),
  };
  return labels[status] ?? String(status);
};

const itemArrayName = "items";

const validatePartNumber = (rule: any, value: string, callback: (error?: Error) => void) => {
  if (!value) {
    callback(new Error($t("_message.purchase.purchase_order.input_partNumber")));
    return;
  }
  get(partNumberExistsUrl, { partNumber: value })
    .then(res => {
      if (res.data === true) {
        callback();
      } else {
        callback(new Error($t("_message.purchase.purchase_order.part_number_not_exists")));
      }
    })
    .catch(() => {
      callback();
    });
};

const rules = reactive<FormRules>({
  vendorName: [{ required: true, message: $t("_message.purchase.purchase_order.input_vendorName"), trigger: "blur" }],
  partNumber: [
    {
      required: true,
      validator: validatePartNumber,
      trigger: "blur",
    },
  ],
  items: [
    {
      required: true,
      validator: (rule, value, callback) => {
        if (value === undefined || value.length === 0) {
          callback(new Error($t("_message.purchase.purchase_order.upload_items")));
          return;
        }
        callback();
      },
      trigger: "change",
    },
  ],
});

const tableRef = ref<InstanceType<typeof ExpandablePageableTable> | null>(null);
const { useAdd, useEdit, useGeneralPageRef } = usePage(tableRef);
const { title, visible, formType, form } = useGeneralPageRef();
const baseFormWithTableRef = ref<InstanceType<typeof BaseFormWithTable>>();
const vendorSelectRef = ref<InstanceType<typeof BaseSelect>>();
const warehouseSelectRef = ref<InstanceType<typeof BaseSelect>>();

const inboundVisible = ref(false);
const inboundWarehouseSelectRef = ref<InstanceType<typeof BaseSelect>>();
const inboundForm = reactive({
  orderId: 0,
  orderCode: "",
  vendorName: "",
  formCode: "",
  storeNo: null as number,
  storeName: "",
  formMark: "",
  items: [] as any[],
});

const qrCodeVisible = ref(false);
const qrCodeData = ref<any[]>([]);

const mappingConfig: FieldMappingConfig = {
  partNumber: {
    sourceKey: "物料编号",
    defaultValue: "",
  },
  productSpecs: {
    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;
    },
  },
  purchaseMark: {
    sourceKey: "备注",
    defaultValue: "",
  },
};

const add = () => {
  form.value = {
    items: [],
  };
  title.value = "_title.purchase.purchase_order.add";
  visible.value = true;
  formType.value = false;
};

const edit = async (row: any) => {
  title.value = "_title.purchase.purchase_order.edit";
  formType.value = true;

  try {
    const response = await get(getItemsUrl, { orderId: row.id });
    form.value = {
      id: row.id,
      vendorName: row.vendorName,
      vendorNo: row.vendorNo,
      storeNo: row.storeNo,
      storeName: row.storeName,
      formMark: row.formMark,
      items: response.data || [],
    };
    visible.value = true;
  } catch {
    ElMessage.error($t("_message.purchase.purchase_order.get_items_error"));
  }
};

const remove = (row: any) => {
  ElMessageBox.confirm($t("_message.purchase.purchase_order.delete_confirm"), $t("_level.warning"), {
    confirmButtonText: $t("_button.confirm"),
    cancelButtonText: $t("_button.cancel"),
    type: "warning",
  }).then(async () => {
    try {
      const res = await post(removeUrl, { id: row.id });
      if (res.code === 0) {
        ElMessage.success($t("_message.purchase.purchase_order.delete_success"));
        tableRef.value?.reload();
      } else {
        ElMessage.error(res.msg || $t("_message.purchase.purchase_order.delete_fail"));
      }
    } catch (err: any) {
      ElMessage.error(err.response?.data?.message || $t("_message.purchase.purchase_order.delete_fail"));
    }
  });
};

const showInbound = async (row: any) => {
  try {
    const response = await get(getItemsUrl, { orderId: row.id });
    const items = (response.data || []).map((item: any) => ({
      ...item,
      inboundCount: item.remainingCount || 0,
    }));

    inboundForm.orderId = row.id;
    inboundForm.orderCode = row.formCode;
    inboundForm.vendorName = row.vendorName;
    inboundForm.formCode = generateDucumentNo("RK");
    inboundForm.storeNo = row.storeNo ?? null;
    inboundForm.storeName = row.storeName ?? "";
    inboundForm.formMark = "";
    inboundForm.items = items;

    inboundVisible.value = true;
  } catch {
    ElMessage.error($t("_message.purchase.purchase_order.get_items_error"));
  }
};

const submitInbound = async () => {
  const validItems = inboundForm.items.filter(item => item.inboundCount > 0);

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

  if (!inboundForm.storeNo) {
    ElMessage.warning($t("_message.purchase.purchase_order.select_store"));
    return;
  }

  ElMessageBox.confirm($t("_message.purchase.purchase_order.inbound_confirm"), $t("_level.warning"), {
    confirmButtonText: $t("_button.confirm"),
    cancelButtonText: $t("_button.cancel"),
    type: "warning",
  }).then(async () => {
    const data = {
      orderId: inboundForm.orderId,
      orderCode: inboundForm.orderCode,
      vendorName: inboundForm.vendorName,
      storeNo: inboundForm.storeNo,
      storeName: inboundWarehouseSelectRef.value?.getLabel() ?? inboundForm.storeName,
      formMark: inboundForm.formMark,
      items: validItems.map(item => ({
        itemId: item.id,
        inboundCount: item.inboundCount,
      })),
    };

    try {
      const res = await post(inboundUrl, data);
      if (res.code === 0) {
        ElMessage.success($t("_message.purchase.purchase_order.inbound_success"));
        inboundVisible.value = false;
        tableRef.value?.reload();
      } else {
        ElMessage.error(res.msg ?? $t("_message.purchase.purchase_order.inbound_fail"));
      }
    } catch (err: any) {
      ElMessage.error(err.response?.data?.message ?? $t("_message.purchase.purchase_order.inbound_fail"));
    }
  });
};

const showQrCode = async (row: any) => {
  try {
    const response = await get(getQrCodeDataUrl, { orderId: row.id });
    qrCodeData.value = response.data ?? [];
    qrCodeVisible.value = true;
  } catch {
    ElMessage.error($t("_message.purchase.purchase_order.get_qrcode_error"));
  }
};

const submit = (formData: any, formRef: FormInstance | undefined) => {
  if (formRef !== undefined) {
    formRef.validate(valid => {
      if (valid) {
        const data = {
          ...formData,
          vendorName: vendorSelectRef.value?.getLabel(),
          storeName: warehouseSelectRef.value?.getLabel(),
        };
        if (formType.value) {
          useEdit(editUrl, data, visible);
        } else {
          useAdd(addUrl, data, 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 "inbound":
      showInbound(row);
      break;
    case "printQrCode":
      showQrCode(row);
      break;
  }
};

const getPartNumberRules = (): FormItemRule[] => {
  return rules.partNumber as FormItemRule[];
};

const getPurchaseCountRules = (): FormItemRule[] => {
  return [
    {
      required: true,
      message: $t("_message.purchase.purchase_order.input_purchaseCount"),
      trigger: "blur",
    },
  ];
};

const getPriceRules = (): FormItemRule[] => {
  return [
    {
      required: true,
      message: $t("_message.purchase.purchase_order.input_price"),
      trigger: "blur",
    },
  ];
};

const authShowFunc = (row: any, button: globalThis.ButtonProp) => {
  if (
    row.formStatus === 4 &&
    (button.eventName === "edit" || button.eventName === "remove" || button.eventName === "inbound")
  ) {
    return false;
  }
  return true;
};

// 表单状态标签类型映射
const getFormStatusTagType = (code: number | null): string => {
  const tagTypeMap: Record<number, string> = {
    0: "info", // 未审核
    1: "success", // 已审核
    2: "danger", // 已驳回
    3: "warning", // 未完成
    4: "success", // 已完成
    5: "primary", // 入库中
    6: "info", // 已导入
    7: "warning", // 审核中
    8: "danger", // 已退回
  };
  return tagTypeMap[code ?? -1] || "info";
};
</script>
<template>
  <ExpandablePageableTable
    :url="getPageUrl"
    :searchers="searchers"
    ref="tableRef"
    :item-url="getItemsUrl"
    item-id-key="id"
    item-id-name="orderId"
  >
    <template #tool-button>
      <DefaultToolButton @top-button-click="topButtonClick" />
    </template>
    <template #columns>
      <el-table-column :label="$t('_prop.purchase.purchase_order.formCode')" prop="formCode" width="180" />
      <el-table-column :label="$t('_prop.purchase.purchase_order.vendorName')" prop="vendorName" width="150" />
      <el-table-column :label="$t('_prop.purchase.purchase_order.totalValue')" prop="totalValue" width="120">
        <template #default="{ row }">
          {{ new Decimal(row.totalValue ?? 0).toFixed(2) }}
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.purchase.purchase_order.formMark')" prop="formMark" />
      <el-table-column :label="$t('_prop.common.createDate')" prop="createDate" width="180" :formatter="formatDate" />
      <DefaultStatusSwitchColumn
        status-param-name="formStatus"
        :status-label-mapping="getFormStatusLabel"
        :tag-type-mapping="getFormStatusTagType"
      />
      <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_order_item.partNumber')" prop="partNumber" width="150" />
        <el-table-column
          :label="$t('_prop.purchase.purchase_order_item.productSpecs')"
          prop="productSpecs"
          width="150"
        />
        <el-table-column
          :label="$t('_prop.purchase.purchase_order_item.purchaseCount')"
          prop="purchaseCount"
          width="100"
        />
        <el-table-column :label="$t('_prop.purchase.purchase_order_item.price')" prop="price" width="100">
          <template #default="{ row }">
            {{ new Decimal(row.price ?? 0).toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column :label="$t('_prop.purchase.purchase_order_item.totalPrice')" prop="totalPrice" width="120">
          <template #default="{ row }">
            {{ new Decimal(row.totalPrice ?? 0).toFixed(2) }}
          </template>
        </el-table-column>
      </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_order.baseTitle')"
    :table-title="$t('_title.purchase.purchase_order.tableTitle')"
    item-array-name="items"
    :mapping-config="mappingConfig"
    :template-file-name="$t('_title.purchase.purchase_order.templateFileName')"
    :template-columns="{ exclude: ['purchaseMark'] }"
  >
    <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_order.vendorName')" prop="vendorName">
            <BaseSelect
              v-model="form.vendorName"
              :url="getVendorSelectListUrl"
              ref="vendorSelectRef"
              :placeholder="$t('_message.purchase.purchase_order.select_vendor')"
            />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('_prop.purchase.purchase_order.storeName')" prop="storeNo">
            <BaseSelect
              v-model="form.storeNo"
              :url="getWarehouseSelectListUrl"
              ref="warehouseSelectRef"
              :placeholder="$t('_message.purchase.purchase_order.select_store')"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item :label="$t('_prop.purchase.purchase_order.formMark')" prop="formMark">
        <el-input
          v-model="form.formMark"
          type="textarea"
          autosize
          :placeholder="$t('_message.purchase.purchase_order.input_formMark')"
        />
      </el-form-item>
    </template>
    <template #form-table-columns>
      <el-table-column :label="$t('_prop.purchase.purchase_order_item.partNumber')" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.partNumber`" :rules="getPartNumberRules()">
            <el-input v-model="row.partNumber" size="small" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.purchase.purchase_order_item.productSpecs')" width="150">
        <template #default="{ row }">
          {{ row.productSpecs ?? "-" }}
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.purchase.purchase_order_item.purchaseCount')" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.purchaseCount`" :rules="getPurchaseCountRules()">
            <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_order_item.price')" width="150">
        <template #default="{ row, $index }">
          <el-form-item :prop="`${itemArrayName}.${$index}.price`" :rules="getPriceRules()">
            <el-input-number v-model="row.price" size="small" :min="0" :step="0.01" :precision="2" />
          </el-form-item>
        </template>
      </el-table-column>

      <el-table-column :label="$t('_prop.purchase.purchase_order_item.totalPrice')" width="150">
        <template #default="{ row }">
          {{ new Decimal(row.purchaseCount ?? 0).mul(row.price ?? 0).toFixed(2) }}
        </template>
      </el-table-column>
    </template>
  </BaseFormWithTable>

  <BaseTableForm
    v-model:visible="inboundVisible"
    :title="$t('_title.purchase.purchase_order.inbound')"
    :table-data="inboundForm.items"
    :selectable="false"
    :use-auth="false"
  >
    <template #filter>
      <el-form :model="inboundForm" label-width="100px">
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item :label="$t('_prop.purchase.purchase_order.inboundCode')">
              <el-input v-model="inboundForm.formCode" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item :label="$t('_prop.purchase.purchase_order.orderCode')">
              <el-input v-model="inboundForm.orderCode" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item :label="$t('_prop.purchase.purchase_order.vendorName')">
              <el-input v-model="inboundForm.vendorName" disabled />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item :label="$t('_prop.purchase.purchase_order.storeName')" required>
              <BaseSelect
                v-model="inboundForm.storeNo"
                :url="getWarehouseSelectListUrl"
                ref="inboundWarehouseSelectRef"
                :placeholder="$t('_message.purchase.purchase_order.select_store')"
              />
            </el-form-item>
          </el-col>
          <el-col :span="16">
            <el-form-item :label="$t('_prop.purchase.purchase_order.formMark')">
              <el-input v-model="inboundForm.formMark" type="textarea" autosize />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </template>
    <template #table-columns>
      <el-table-column :label="$t('_prop.purchase.purchase_order_item.partNumber')" prop="partNumber" width="150" />
      <el-table-column :label="$t('_prop.purchase.purchase_order_item.productSpecs')" prop="productSpecs" width="150" />
      <el-table-column
        :label="$t('_prop.purchase.purchase_order_item.purchaseCount')"
        prop="purchaseCount"
        width="100"
      />
      <el-table-column :label="$t('_prop.purchase.purchase_order_item.receiptCount')" prop="receiptCount" width="100" />
      <el-table-column
        :label="$t('_prop.purchase.purchase_order_item.remainingCount')"
        prop="remainingCount"
        width="100"
      />
      <el-table-column :label="$t('_prop.purchase.purchase_order.inboundCount')" width="150">
        <template #default="{ row }">
          <el-input-number v-model="row.inboundCount" :min="0" :max="row.remainingCount" size="small" />
        </template>
      </el-table-column>
    </template>
    <template #attachment>
      <el-button type="primary" @click="submitInbound">
        {{ $t("_button.inbound") }}
      </el-button>
    </template>
  </BaseTableForm>

  <QrCodeDialog
    v-model:visible="qrCodeVisible"
    :title="$t('_title.purchase.purchase_order.qrcode')"
    :qr-code-list="qrCodeData"
    :qr-code-size="200"
  />
</template>
