package com.awspaas.user.apps.donenow_ivt.event;

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.core.delegate.ProcessExecutionContext;
import com.actionsoft.bpms.bpmn.engine.listener.InterruptListener;
import com.actionsoft.bpms.commons.database.RowMap;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.exception.BPMNError;
import com.actionsoft.sdk.local.SDK;
import com.awspaas.user.apps.donenow_ivt.constant.IVTConstant;
import com.awspaas.user.apps.donenow_ivt.utils.BigDecimalUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

public class reserveFormBeforeSave extends InterruptListener {
    public String getDescription() {
        return "采购接收/取消接收保存前，校验库存+自动更新接收数+自动更新状态";
    }

    @Override
    public boolean execute(ProcessExecutionContext processExecutionContext) throws Exception {
        UserContext uc = processExecutionContext.getUserContext();
        BO formData = processExecutionContext.getFormData();
        String boName = processExecutionContext.getParameterOfString("$BONAME");
        String bindId = processExecutionContext.getProcessInstance().getId();

        // 采购接收主表保存时执行
        if (IVTConstant.BO_EU_DNIVT_RECEIVE_MAIN.equals(boName)) {
            // 查询当前单据下的所有子表数据
            List<BO> list = SDK.getBOAPI().query(IVTConstant.BO_EU_DNIVT_RECEIVE_SUB).bindId(bindId).list();
            for (BO bo : list) {
                // ===== 1. 基础字段取值 =====
                String benReceiveStr = BigDecimalUtil.isNull(bo.getString("BEN_RECEIVE"));
                int intBenReceive = Integer.parseInt(benReceiveStr); // 本次接收数
                String orderProductId = bo.getString("ORDER_PRODUCT_ID"); // 订单项ID
                String productName = bo.getString("PRODUCT_NAME"); // 产品名称
                int totalPurchaseQty = Integer.parseInt(bo.getString("QUANTITY")); // 采购总数量
                String sns = bo.getString("SN");

                // ===== 2. 原有校验：本次接收数为0，禁止填序列号 =====
                if (intBenReceive == 0) {
                    if (StringUtils.isNotBlank(sns)) {
                        throw new BPMNError("receiveErrorCode0", "本次接收数量为空，不需要输入序列号！");
                    }
                    continue;
                }

                // ===== 3. 原有校验：整体接收产品，必须收完剩余数量 =====
                if ("1".equals(bo.getString("WHOLE"))) {
                    String backorderedStr = BigDecimalUtil.isNull(bo.getString("QUANTITY_BACKORDERED"));
                    int backorderedQty = Integer.parseInt(backorderedStr);
                    // 正向接收/反向取消，都必须等于剩余数量
                    if (intBenReceive != backorderedQty && (0 - intBenReceive) != backorderedQty) {
                        throw new BPMNError("receiveErrorCode6", productName + "只能整体接收，接收数量为" + backorderedQty + "！");
                    }
                }

                // ===== 4. ✅ 核心修复1：查询【正确子表】统计历史累计接收数 =====
                RowMap historyMap = DBSql.getMap(
                        "select sum(QUANTITY_RECEIVED) as QUANTITY_RECEIVED from BO_EU_DNIVT_RECEIVE_SUB where ORDER_PRODUCT_ID=?",
                        new Object[]{orderProductId}
                );
                int historyReceive = 0;
                if (historyMap != null && historyMap.get("QUANTITY_RECEIVED") != null) {
                    historyReceive = historyMap.getInt("QUANTITY_RECEIVED");
                }

                // ===== 5. ✅ 核心校验：取消接收数 不能大于 已接收数 =====
                if (intBenReceive + historyReceive < 0) {
                    throw new BPMNError("receiveErrorCode4", "取消接收的数量不能大于已接收的数量！");
                }

                // ===== 6. ✅ 核心校验：累计接收数 不能大于 采购总数量 =====
                int newTotalReceive = historyReceive + intBenReceive;
                if (newTotalReceive > totalPurchaseQty) {
                    throw new BPMNError("receiveErrorCode5", productName + "接收数量不能大于采购数量【" + totalPurchaseQty + "】！");
                }

                // ===== 7. ✅ 原有校验：序列号唯一性校验 =====
                if (StringUtils.isNotBlank(sns)) {
                    for (String sn : sns.split(",")) {
                        List<RowMap> existSnList = DBSql.getMaps(
                                "select * from BO_EU_DNIVT_WAREHOUSE_PRODUCT_LOT where FIND_IN_SET(?, SN)",
                                new Object[]{sn}
                        );
                        // 正向接收：序列号不能已存在
                        if (intBenReceive > 0 && !existSnList.isEmpty()) {
                            throw new BPMNError("receiveErrorCode1", sn + "已存在此序列号，不能再新增！");
                        }
                        // 反向取消：序列号必须存在+归属当前采购单
                        if (intBenReceive < 0) {
                            if (existSnList.isEmpty()) {
                                throw new BPMNError("receiveErrorCode2", sn + "不存在此序列号，不能删除！");
                            }
                            boolean isCurrentOrder = existSnList.stream()
                                    .anyMatch(row -> orderProductId.equals(row.getString("ORDER_PRODUCT_ID")));
                            if (!isCurrentOrder) {
                                throw new BPMNError("receiveErrorCode3", sn + "不是此采购单接收的，无法取消！");
                            }
                        }
                    }
                }

                // ===== 8. ✅ 核心更新1：计算并赋值 累计接收数、未收货数量 =====
                bo.set("QUANTITY_RECEIVED", newTotalReceive); // 累计接收数（不再是0）
                int newBackorderedQty = totalPurchaseQty - newTotalReceive;
                bo.set("QUANTITY_BACKORDERED", Math.max(newBackorderedQty, 0)); // 未收货数量（最小为0）

                // ===== 9. ✅ 核心更新2：自动更新状态（STATUS） =====
                if (newBackorderedQty == 0) {
                    bo.set("STATUS", "已接收"); // 未收货数量为0 → 自动变已接收
                } else {
                    bo.set("STATUS", "待接收"); // 还有未收 → 保持待接收
                }

                // ===== 10. ✅ 同步更新子表数据到数据库 =====
                SDK.getBOAPI().update(IVTConstant.BO_EU_DNIVT_RECEIVE_SUB, bo);
            }
        }

        // 记录表单修改（原有逻辑保留）
        dn.recordFormChanges.execute(processExecutionContext);
        return true;
    }
}