<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 { usePage } from "@/composables/use-page";
import BaseForm from "@/components/base/base-form/BaseForm.vue";
import { $t } from "@/common/languages";
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from "element-plus";
import { formatDate } from "@/common/utils/format-utils";
import DefaultStatusSwitchColumn from "@/components/base/default-column/DefaultStatusSwitchColumn.vue";
import BaseSelect from "@/components/base/base-select/BaseSelect.vue";
import { generateDucumentNo } from "@/common/utils/document-no-generator/document-no-generator";
import { get, post } from "@/common/http/request";
import BaseTableForm from "@/components/base/base-table-form/BaseTableForm.vue";
import { DocumentType } from "@/common/enums/DocumentType";
import { useStatus } from "@/common/languages/mapping/base-info-mapping";

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

const getPageUrl = "/production/productionPlan/getProductionPlanPage";
const addUrl = "/production/productionPlan/addProductionPlan";
const editUrl = "/production/productionPlan/updateProductionPlan";
const removeUrl = "/production/productionPlan/deleteProductionPlan";
const getProjectSelectList = "/production/bom/getBomSelectList";
const getWarehouseSelectListUrl = "/warehouse/warehouse/getWarehouseSelectList";
const getProductionPlanShortageListUrl = "/production/productionPlan/getMaterialShortageList";
const generatePurchasePlanUrl = "/production/productionPlan/generatePurchasePlan";
const generateTransferOrderUrl = "/production/productionPlan/generateTransferOrder";
const generateProductionIssueUrl = "/production/productionPlan/generateProductionIssue";
const searchers = [
  { name: "projectName", type: "text" as const, placeholder: $t("_prop.production.production_plan.projectName") },
];
const rules = reactive<FormRules>({
  projectId: [{ required: true, message: $t("_message.production.production_plan.select_projectId"), trigger: "blur" }],
  productionNum: [
    { required: true, message: $t("_message.production.production_plan.input_productionNum"), trigger: "blur" },
  ],
  storeNo: [{ required: true, message: $t("_message.production.production_plan.select_storeNo"), trigger: "blur" }],
  productionCount: [
    { required: true, message: $t("_message.production.production_plan.input_productionCount"), trigger: "blur" },
  ],
  productionMark: [
    { required: false, message: $t("_message.production.production_plan.input_productionMark"), trigger: "blur" },
  ],
  productionNote: [
    { required: false, message: $t("_message.production.production_plan.input_productionNote"), trigger: "blur" },
  ],
});
/**
 * 基本不变通用变量
 */
const tableRef = ref<InstanceType<typeof BasePageableTable> | null>(null);
const { useAdd, useEdit, useRemove, useGeneralPageRef } = usePage(tableRef);
const { title, visible, formType, form } = useGeneralPageRef();
const { getProductionPlanStatusLabel } = useStatus();
const bomSelectRef = ref<InstanceType<typeof BaseSelect>>();
const warehouseSelectRef = ref<InstanceType<typeof BaseSelect>>();
const transferWarehouseSelectRef = ref<InstanceType<typeof BaseSelect>>();
const dialogRef = ref<InstanceType<typeof BaseTableForm>>();
const dialogVisible = ref(false);
const shortageData = ref([]);
const dialogTableData = ref([]);
const dialogSelectable = ref(false);
const transferWarehouse = ref();
const issueDialogVisible = ref(false);
/**
 * 可以自定义的变量
 */

const add = () => {
  form.value = {};
  title.value = "_title.production.production_plan.add";
  form.value["productionNum"] = generateDucumentNo("SCJH");
  visible.value = true;
  formType.value = false;
};
const edit = (row: any) => {
  title.value = "_title.production.production_plan.edit";
  form.value = { ...row };
  visible.value = true;
  formType.value = true;
};
const remove = (row: any) => {
  useRemove(removeUrl, row.id, "_message.production.production_plan.delete_message");
};
const submit = (form: any, formRef: FormInstance | undefined) => {
  setName();
  if (formRef !== undefined) {
    formRef.validate(valid => {
      if (valid) {
        if (formType.value) useEdit(editUrl, form, visible);
        else useAdd(addUrl, form, visible);
      }
    });
  }
};

const validateSelection = (requireStatusZero = false) => {
  const rows = tableRef.value?.tableMainRef?.tableRef?.getSelectionRows();

  if (!rows || rows.length === 0) {
    ElMessage.warning($t("_message.production.production_plan.select_production_plan"));
    return null;
  }

  if (requireStatusZero && !rows.every(row => row.productionStatus === 0)) {
    ElMessage.warning($t("_message.production.production_plan.error_production_status"));
    return null;
  }

  const warehouseId = rows[0].storeNo;
  if (!rows.every(item => item.storeNo === warehouseId)) {
    ElMessage.warning($t("_message.production.production_plan.duplicate_store_no"));
    return null;
  }

  return rows;
};

const buildDocumentInfo = (rows: any[], type: DocumentType | string, markSuffixKey: string, nameSuffixKey: string) => {
  const code = generateDucumentNo(type);
  const productionNums = rows.map((item: any) => item.productionNum).join(",");
  const projectNames = rows.map((item: any) => item.projectName).join(",");

  return {
    code,
    mark:
      $t("_message.common.generate_document_mark_prefix") +
      productionNums +
      $t(markSuffixKey) +
      code +
      $t("_message.common.generate_document_mark_suffix"),
    name: projectNames + $t(nameSuffixKey),
  };
};

const viewMaterialShortage = async () => {
  const rows = validateSelection(true); // 需要校验状态为 0
  if (!rows) return;

  const params = new URLSearchParams();
  rows.forEach(({ id }) => params.append("ids", id));

  shortageData.value = await get(getProductionPlanShortageListUrl, params).then(res => res.data);

  calculateDiffQty();
  dialogRef.value?.clearSelection();
  dialogTableData.value = shortageData.value;
  dialogSelectable.value = false;
  dialogVisible.value = true;
};

const generatePurchasePlan = (selectedShortageRows: any[]) => {
  ElMessageBox.confirm($t("_message.production.production_plan.generate_purchase_plan_confirm"), $t("_level.warning"), {
    confirmButtonText: $t("_button.confirm"),
    cancelButtonText: $t("_button.cancel"),
    type: "warning",
  }).then(async () => {
    const rows = validateSelection();
    if (!rows) return;

    const {
      code: planNo,
      mark: planMark,
      name: planName,
    } = buildDocumentInfo(
      rows,
      "PA",
      "_message.production.production_plan.generate_purchase_plan_mark_suffix",
      "_message.production.production_plan.generate_purchase_plan_name_suffix"
    );

    const plan = {
      planNo,
      storeNo: rows[0].storeNo,
      storeName: rows[0].storeName,
      remask: planMark,
      planName,
      planItems: selectedShortageRows.map(({ partNumber, diffQty, id }) => ({
        partNumber,
        purchaseCount: -diffQty,
        partId: id,
      })),
    };

    try {
      const res = await post(generatePurchasePlanUrl, plan);
      ElMessage[res.code === 0 ? "success" : "error"](
        res.code === 0
          ? $t("_message.production.production_plan.generate_purchase_plan_success")
          : $t("_message.production.production_plan.generate_purchase_plan_fail") + res.msg
      );
    } catch (err) {
      ElMessage.error($t("_message.production.production_plan.generate_purchase_plan_fail") + err);
    }
  });
};

const generateTransferOrder = (selectedShortageRows: any[]) => {
  ElMessageBox.confirm(
    $t("_message.production.production_plan.generate_transfer_order_confirm"),
    $t("_level.warning"),
    {
      confirmButtonText: $t("_button.confirm"),
      cancelButtonText: $t("_button.cancel"),
      type: "warning",
    }
  ).then(async () => {
    const rows = validateSelection();
    if (!rows) return;

    const outWarehouseId = transferWarehouse.value;
    if (!outWarehouseId) {
      ElMessage.warning("仓库不能为空");
      return;
    }

    const outWarehouseName = transferWarehouseSelectRef.value?.getLabel();
    if (rows[0].storeNo === outWarehouseId) {
      ElMessage.warning("仓库不能相同");
      return;
    }

    const {
      code: formCode,
      mark: formMark,
      name: formName,
    } = buildDocumentInfo(
      rows,
      DocumentType.StockTransferOrder,
      "_message.production.production_plan.generate_transfer_order_mark_suffix",
      "_message.production.production_plan.generate_transfer_order_name_suffix"
    );

    const plan = {
      formCode,
      formName,
      formMark,
      storeNo: rows[0].storeNo,
      storeName: rows[0].storeName,
      outStoreNo: outWarehouseId,
      outStoreName: outWarehouseName,
      transferOrderItems: selectedShortageRows.map(({ partNumber, diffQty, productSpec, id }) => ({
        partNumber,
        productCount: -diffQty,
        productSpec,
        partId: id,
      })),
    };

    try {
      const res = await post(generateTransferOrderUrl, plan);
      ElMessage[res.code === 0 ? "success" : "error"](
        res.code === 0
          ? $t("_message.production.production_plan.generate_transfer_order_success")
          : $t("_message.production.production_plan.generate_transfer_order_fail") + res.msg
      );
    } catch (err) {
      ElMessage.error($t("_message.production.production_plan.generate_transfer_order_fail") + err);
    }
  });
};

const generateProductionIssue = async () => {
  const rows = validateSelection(true); // 需要校验状态为 0
  if (!rows) return;

  const params = new URLSearchParams();
  rows.forEach(({ id }) => params.append("ids", id));

  dialogTableData.value = await get(getProductionPlanShortageListUrl, params).then(res => res.data);
  setActualQtyAndDiffQty();
  issueDialogVisible.value = true;
};

const _generateProductionIssue = async () => {
  ElMessageBox.confirm(
    $t("_message.production.production_plan.generate_production_issue_confirm"),
    $t("_level.warning"),
    {
      confirmButtonText: $t("_button.confirm"),
      cancelButtonText: $t("_button.cancel"),
      type: "warning",
    }
  ).then(async () => {
    const rows = validateSelection();
    if (!rows) return;

    const {
      code: formCode,
      mark: formMark,
      name: formName,
    } = buildDocumentInfo(
      rows,
      DocumentType.ProductionIssue,
      "_message.production.production_plan.generate_production_issue_mark_suffix",
      "_message.production.production_plan.generate_production_issue_name_suffix"
    );

    const issue = {
      formCode,
      formName,
      formMark,
      storeNo: rows[0].storeNo,
      storeName: rows[0].storeName,
      items: dialogTableData.value.map(({ partNumber, storeNo, actualQty, requiredQty }) => ({
        partNumber,
        storeNo,
        productCount: actualQty,
        demandCount: requiredQty,
      })),
    };

    try {
      const res = await post(generateProductionIssueUrl, { ids: rows.map(r => r.id), issue });
      if (res.code === 0) {
        issueDialogVisible.value = false;
        tableRef.value?.reload();
        ElMessage.success($t("_message.production.production_plan.generate_production_issue_success"));
      } else {
        ElMessage.error($t("_message.production.production_plan.generate_production_issue_fail") + res.msg);
      }
    } catch (err) {
      ElMessage.error($t("_message.production.production_plan.generate_production_issue_fail") + err);
    }
  });
};

const calculateDiffQty = () => {
  shortageData.value.forEach((item: any) => {
    item.diffQty = computed(() => item.stockQty - item.requiredQty);
  });
};

const setActualQtyAndDiffQty = () => {
  dialogTableData.value.forEach((item: any) => {
    item.actualQty = item.requiredQty;
    item.diffQty = computed(() => item.stockQty - item.requiredQty);
  });
};

const handleShortageFilterSubmit = () => {
  dialogTableData.value = shortageData.value.filter(item => (item as any).diffQty < 0);
  dialogSelectable.value = true;
};

const handleUnfilterSubmit = () => {
  dialogTableData.value = shortageData.value;
  dialogSelectable.value = false;
};

const topButtonClick = (eventName: string) => {
  switch (eventName) {
    case "add":
      add();
      break;
    case "viewMaterialShortage":
      viewMaterialShortage();
      break;
    case "generateProductionIssue":
      generateProductionIssue();
      break;
  }
};
const operateButtonClick = (eventName: string, row: any) => {
  switch (eventName) {
    case "edit":
      edit(row);
      break;
    case "remove":
      remove(row);
      break;
  }
};
const dialogButtonClick = (eventName: string, btn: any, rows: any[]) => {
  switch (eventName) {
    case "generatePurchasePlan":
      generatePurchasePlan(rows);
      break;
    case "generateTransferOrder":
      generateTransferOrder(rows);
      break;
  }
};
const setName = () => {
  form.value["projectName"] = bomSelectRef.value?.getLabel();
  form.value["storeName"] = warehouseSelectRef.value?.getLabel();
};
const handleReset = () => {
  form.value["productionNum"] = generateDucumentNo("SCJH");
};
</script>
<template>
  <BasePageableTable :url="getPageUrl" :searchers="searchers" ref="tableRef">
    <template #tool-button>
      <DefaultToolButton @top-button-click="topButtonClick" />
    </template>
    <template #columns>
      <el-table-column prop="id" type="selection" width="40" />
      <el-table-column :label="$t('_prop.production.production_plan.productionNum')" prop="productionNum" />
      <el-table-column :label="$t('_prop.production.production_plan.projectName')" prop="projectName" />
      <el-table-column :label="$t('_prop.production.production_plan.storeName')" prop="storeName" />
      <el-table-column :label="$t('_prop.production.production_plan.productionCount')" prop="productionCount" />
      <el-table-column :label="$t('_prop.production.production_plan.productionMark')" prop="productionMark" />
      <el-table-column :label="$t('_prop.common.createDate')" prop="createDate" :formatter="formatDate" />
      <DefaultStatusSwitchColumn
        status-param-name="productionStatus"
        :status-label-mapping="getProductionPlanStatusLabel"
      />
      <DefaultOperateButtonColumn @operate-button-click="operateButtonClick" />
    </template>
  </BasePageableTable>
  <BaseForm
    v-model:visible="visible"
    @submit="submit"
    v-model:form="form"
    :title="$t(title)"
    :rules="rules"
    @reset="handleReset"
  >
    <template #form-items>
      <el-form-item prop="id" v-if="false"><el-input v-model="form.id" /></el-form-item>
      <el-form-item prop="projectName" v-if="false"><el-input v-model="form.projectName" /></el-form-item>
      <el-form-item prop="storeName" v-if="false"><el-input v-model="form.storeName" /></el-form-item>

      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item :label="$t('_prop.production.production_plan.projectId')" prop="projectId">
            <BaseSelect v-model="form.projectId" :url="getProjectSelectList" ref="bomSelectRef" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item :label="$t('_prop.production.production_plan.productionNum')" prop="productionNum">
            <el-input
              v-model="form.productionNum"
              :placeholder="$t('_message.production.production_plan.input_productionNum')"
              disabled
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item :label="$t('_prop.production.production_plan.storeNo')" prop="storeNo">
            <BaseSelect v-model="form.storeNo" :url="getWarehouseSelectListUrl" ref="warehouseSelectRef" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item :label="$t('_prop.production.production_plan.productionCount')" prop="productionCount">
            <el-input-number
              :min="1"
              v-model="form.productionCount"
              :placeholder="$t('_message.production.production_plan.input_productionCount')"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item :label="$t('_prop.production.production_plan.productionMark')" prop="productionMark">
        <el-input
          v-model="form.productionMark"
          type="textarea"
          autosize
          :placeholder="$t('_message.production.production_plan.input_productionMark')"
        />
      </el-form-item>
      <el-form-item :label="$t('_prop.production.production_plan.productionNote')" prop="productionNote">
        <el-input
          v-model="form.productionNote"
          type="textarea"
          autosize
          :placeholder="$t('_message.production.production_plan.input_productionNote')"
        />
      </el-form-item>
    </template>
  </BaseForm>
  <BaseTableForm
    ref="dialogRef"
    v-model:visible="dialogVisible"
    :title="$t('_title.production.production_plan.dialog')"
    :tableData="dialogTableData"
    :selectable="dialogSelectable"
    row-key="partNumber"
    @dialog-button-click="dialogButtonClick"
  >
    <template #filter>
      <el-button type="danger" @click="handleShortageFilterSubmit">{{ $t("_button.shortageFilterButton") }}</el-button>
      <el-button type="primary" @click="handleUnfilterSubmit">{{ $t("_button.unfilterButton") }}</el-button>
    </template>
    <template #table-columns>
      <el-table-column :label="$t('_prop.production.bom_item.partNumber')" prop="partNumber" />
      <el-table-column :label="$t('_prop.production.bom_item.productSpecs')" prop="productSpecs" />
      <el-table-column :label="$t('_prop.production.production_plan.requiredQty')" prop="requiredQty">
        <template #default="{ row }">
          <el-input-number v-model="row.requiredQty" :min="0" />
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.production.production_plan.stockQty')" prop="stockQty" />
      <el-table-column :label="$t('_prop.production.production_plan.diffQty')" prop="diffQty" />
    </template>
    <template #attachment="{ checkPermission }">
      <div v-if="checkPermission('generateTransferOrder')" style="display: flex; align-items: center">
        <span style="width: 200px; padding-right: 20px">{{ $t("_prop.production.production_plan.outStoreNo") }}</span>
        <BaseSelect v-model="transferWarehouse" :url="getWarehouseSelectListUrl" ref="transferWarehouseSelectRef" />
      </div>
    </template>
  </BaseTableForm>
  <BaseTableForm
    ref="dialogRef"
    v-model:visible="issueDialogVisible"
    :title="$t('_title.production.production_plan.issueDialog')"
    :tableData="dialogTableData"
    :selectable="false"
    :useAuth="false"
  >
    <template #table-columns>
      <el-table-column :label="$t('_prop.production.bom_item.partNumber')" prop="partNumber" />
      <el-table-column :label="$t('_prop.production.bom_item.productSpecs')" prop="productSpecs" />
      <el-table-column :label="$t('_prop.production.production_plan.requiredQty')" prop="requiredQty" />
      <el-table-column :label="$t('_prop.production.production_plan.actualQty')" prop="actualQty">
        <template #default="{ row }">
          <el-input-number v-model="row.actualQty" :min="0" />
        </template>
      </el-table-column>
      <el-table-column :label="$t('_prop.production.production_plan.stockQty')" prop="stockQty" />
      <el-table-column :label="$t('_prop.production.production_plan.diffQty')" prop="diffQty" />
    </template>
    <template #attachment>
      <el-button type="primary" @click="_generateProductionIssue">
        {{ $t("_button.submit") }}
      </el-button>
    </template>
  </BaseTableForm>
</template>
