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

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.core.delegate.ProcessExecutionContext;
import com.actionsoft.bpms.bpmn.engine.listener.ExecuteListener;
import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.exception.BPMNError;
import com.actionsoft.sdk.local.SDK;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
public class costProductShipFormAfterSave extends ExecuteListener {
    public String getDescription() {
        return "合同产品库存配送";
    }

    /**
     *
     * @param processExecutionContext
     * @throws Exception
     */
    @Override
    public void execute(ProcessExecutionContext processExecutionContext) throws Exception {
        BO productBO = SDK.getBOAPI().getByProcess("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", processExecutionContext.getProcessInstance().getId());
        //配送
        if (productBO.getString("IS_SHIP").equals("1")) {
            Connection conn = null;
            try {
                conn = DBSql.open();
                conn.setAutoCommit(false);

                int shipQuantity = ObjToInt(productBO.get("QUANTITY"));//配送数量
                int notShipQuantity = ObjToInt(productBO.get("OLD_QUANTITY")) - shipQuantity;//剩余数量；

                String SN = productBO.getString("SN");//原产品序列号
                String SHIPPING_SN = productBO.getString("SHIPPING_SN");//配送产品序列号
                if (StringUtils.isNotBlank(SN) && StringUtils.isBlank(SHIPPING_SN)) {
                    throw new BPMNError("请选择要配送的产品");
                }
                String notShipSN = "";
                if (StringUtils.isNotBlank(SN) && StringUtils.isNotBlank(SHIPPING_SN)) {
                    notShipSN = "," + SN + ",";
                    for (String spsn : SHIPPING_SN.split(",")) {
                        notShipSN = notShipSN.replaceAll("," + spsn + ",", ",");
                    }
                    if (StringUtils.isNotBlank(notShipSN) && notShipSN.length() > 1 && !notShipSN.equals(",,"))
                        notShipSN = notShipSN.substring(1, notShipSN.length() - 1);//未配送的产品序列号
                    else
                        notShipSN = "";
                }

                String oldStatusId = productBO.getString("STATUS_ID");//原状态
                //全部配送
                if (ObjToInt(productBO.get("OLD_QUANTITY")) == shipQuantity) {
                    productBO.set("IS_SHIP", "2");
                    productBO.set("STATUS_ID", 2159);
                    //SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", productBO, conn);
                } else {
                    //部分配送
                    productBO.set("SN", SHIPPING_SN);
                    productBO.set("IS_SHIP", "2");
                    productBO.set("QUANTITY", shipQuantity);
                    productBO.set("OLD_QUANTITY", shipQuantity);
                    productBO.set("STATUS_ID", 2159);//已配送
                    //SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", productBO, conn);

                    //未配送的生成一个新的物流单
                    BO toCostProductBO = new BO();
                    ProcessInstance processInstance = SDK.getProcessAPI().createBOProcessInstance("obj_6bc913271069455abbd516c556b26d31", processExecutionContext.getUserContext().getUID(), "合同产品物流管理");
                    toCostProductBO.setBindId(processInstance.getId());
                    toCostProductBO.set("IS_SHIP", "0");
                    toCostProductBO.set("WAREHOUSE_ID", productBO.get("WAREHOUSE_ID"));
                    toCostProductBO.set("CONTRACT_COST_ID", productBO.get("CONTRACT_COST_ID"));
                    toCostProductBO.set("QUANTITY", notShipQuantity);
                    toCostProductBO.set("ORDER_ID", productBO.getString("ORDER_ID"));
                    toCostProductBO.set("STATUS_ID", oldStatusId);
                    toCostProductBO.set("OLD_QUANTITY", notShipQuantity);//配送数量
                    toCostProductBO.set("SN", notShipSN);//未配送的产品序列号
                    toCostProductBO.set("SHIPPING_SN", notShipSN);
                    dn.recordFormChanges.record(processExecutionContext.getUserContext(), productBO, "新增", conn);
                    SDK.getBOAPI().create("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", toCostProductBO, processInstance, processExecutionContext.getUserContext(), conn);
                }

                BO costBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_COST", productBO.getString("CONTRACT_COST_ID"));//获取合同产品

                //配送给客户
                ProcessInstance transfeProcessIns = SDK.getProcessAPI().createBOProcessInstance("obj_e15a8fedeaeb43dc85aa258a7e1cffcf", processExecutionContext.getUserContext().getUID(), "配送给客户");
                BO ivtTransfer = new BO();
                ivtTransfer.setBindId(transfeProcessIns.getId());
                ivtTransfer.set("FROM_WAREHOUSE_ID", productBO.get("WAREHOUSE_ID"));
                ivtTransfer.set("PRODUCT_ID", costBO.get("PRODUCT_ID"));

                ivtTransfer.set("TO_ACCOUNT_ID", costBO.get("ACCOUNT_ID"));
                ivtTransfer.set("TO_CONTRACT_ID", costBO.get("CONTRACT_ID"));
                ivtTransfer.set("TO_PROJECT_ID", costBO.get("PROJECT_ID"));
                ivtTransfer.set("TO_TASK_ID", costBO.get("TASK_ID"));

                ivtTransfer.set("QUANTITY", shipQuantity);
                ivtTransfer.set("TYPE_ID", 1482);  // 转移给客户
                ivtTransfer.set("SN", SHIPPING_SN);
                SDK.getBOAPI().create("BO_EU_DNIVT_TRANSFER", ivtTransfer, transfeProcessIns, processExecutionContext.getUserContext(), conn);


                //减少库存
                BO fromWarehouseProductBO = SDK.getBOAPI().query("BO_EU_DNIVT_WAREHOUSE_PRODUCT").connection(conn).addQuery("PRODUCT_ID=", costBO.getString("PRODUCT_ID")).addQuery("WAREHOUSE_ID=", productBO.get("WAREHOUSE_ID")).detail();

                fromWarehouseProductBO.set("QUANTITY", ObjToInt(fromWarehouseProductBO.get("QUANTITY")) - ObjToInt(shipQuantity));
                SDK.getBOAPI().update("BO_EU_DNIVT_WAREHOUSE_PRODUCT", fromWarehouseProductBO, conn);

                List<BO> lots = null;
                //出库方式
                String OUT_RULE = DBSql.getString(conn, "SELECT OUT_RULE FROM BO_EU_DNIVT_PRODUCT WHERE ID=?", new Object[]{fromWarehouseProductBO.getString("PRODUCT_ID")});

                if (OUT_RULE != null && OUT_RULE.equals("1032"))//LIFO后进先出
                {
                    lots = SDK.getBOAPI().query("BO_EU_DNIVT_WAREHOUSE_PRODUCT_LOT").addQuery("BINDID=", fromWarehouseProductBO.getBindId()).addQuery("QUANTITY>0", null).orderByCreated().desc().list();
                } else {
                    //FIFO先进先出
                    lots = SDK.getBOAPI().query("BO_EU_DNIVT_WAREHOUSE_PRODUCT_LOT").addQuery("BINDID=", fromWarehouseProductBO.getBindId()).addQuery("QUANTITY>0", null).orderByCreated().asc().list();
                }

                //减少批次
                double totalCost = 0;//总成本
                int cnt = 0;
                String[] shipSerials = SHIPPING_SN.split(",");//配送的批次
                for (BO lot : lots) {
                    //序列号产品
                    if (StringUtils.isNotBlank(SHIPPING_SN)) {
                        boolean isIn = false;
                        String lotSN = lot.getString("SN");
                        lotSN = "," + lotSN + ",";
                        List<String> toSN = new ArrayList<>();
                        for (String sn : shipSerials) {
                            if (lotSN.contains("," + sn + ",")) {
                                isIn = true;
                                lotSN = lotSN.replace("," + sn + ",", ",");
                                toSN.add(sn);
                                cnt++;
                            }
                            if (cnt >= shipSerials.length)
                                break;
                        }
                        if (isIn) {
                            if (StringUtils.isNotBlank(lotSN)) {
                                lotSN = lotSN.replaceAll("^,+|,+$", "") // 移除首尾一个或多个逗号
                                        .replaceAll(",+", ",");     // 合并中间连续逗号
                                int count = (int) lotSN.chars().filter(c -> c == ',').count();
                                lot.set("SN", lotSN);
                                lot.set("QUANTITY", count + 1);
                            } else {
                                lot.set("SN", "");
                                lot.set("QUANTITY", 0);
                            }
                            totalCost += toSN.size() * Double.parseDouble(lot.getString("UNIT_COST"));
                            lot.set("SHIPPED_SN", StringUtils.join(toSN, ","));
                            //更新批次上序列号
                            SDK.getBOAPI().update("BO_EU_DNIVT_WAREHOUSE_PRODUCT_LOT", lot, conn);

                        }
                        if (cnt >= shipSerials.length)
                            break;
                    } else {
                        //无序列号处理
                        int QUANTITY = Integer.parseInt(lot.get("QUANTITY").toString());
                        int toQu = QUANTITY;
                        if (QUANTITY > shipQuantity) {
                            lot.set("QUANTITY", QUANTITY - shipQuantity);
                            toQu = shipQuantity;
                            shipQuantity = 0;

                        } else {
                            lot.set("QUANTITY", 0);
                            toQu = QUANTITY;
                            shipQuantity = shipQuantity - QUANTITY;
                        }

                        totalCost += toQu * Double.parseDouble(lot.getString("UNIT_COST"));

                        SDK.getBOAPI().update("BO_EU_DNIVT_WAREHOUSE_PRODUCT_LOT", lot, conn);
                        if (shipQuantity <= 0)
                            break;
                    }
                }

                productBO.set("UNIT_COST", totalCost / Integer.parseInt(productBO.getString("QUANTITY")));//计算平均成本

                dn.recordFormChanges.record(processExecutionContext.getUserContext(), productBO, "产品配送后", conn);
                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", productBO, conn);

                //生成运费成本
                // 输入运费的物料计费代码，就会生成新的成本ctt_contract_cost
                if (StringUtils.isNotBlank(productBO.getString("COST_CODE_ID"))) {

                    BO costShipBO = null;
                    ProcessInstance costShipProcessIns = null;
                    String shippingContractCostId = productBO.getString("SHIPPING_CONTRACT_COST_ID");
                    if (StringUtils.isBlank(shippingContractCostId)) {
                        // 场景1：无SHIPPING_CONTRACT_COST_ID，创建新流程和BO
                        costShipProcessIns = SDK.getProcessAPI().createBOProcessInstance("obj_87c6ef75d18f44cc8e85d3d4e818c303",
                                processExecutionContext.getUserContext().getUID(), "合同产品-生成运费成本");
                        costShipBO = new BO();
                        costShipBO.setBindId(costShipProcessIns.getId());
                    } else {
                        // 场景2：有SHIPPING_CONTRACT_COST_ID，先查询
                        costShipBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_COST", shippingContractCostId);
                        if (costShipBO == null) {
                            // 查询结果为空，仍创建新流程和BO
                            costShipProcessIns = SDK.getProcessAPI().createBOProcessInstance("obj_87c6ef75d18f44cc8e85d3d4e818c303",
                                    processExecutionContext.getUserContext().getUID(), "合同产品-生成运费成本");
                            costShipBO = new BO();
                            costShipBO.setBindId(costShipProcessIns.getId());
                        } else {
                            // 查询结果不为空，重置CLOSED状态
                            costShipBO.set("CLOSED", 0);
                        }
                    }

                    costShipBO.set("PRODUCT_ID", null);
                    costShipBO.set("CONTRACT_ID", costBO.get("CONTRACT_ID"));
                    costShipBO.set("COST_CODE_ID", productBO.get("COST_CODE_ID"));
                    costShipBO.set("COST_CODE_NAME", productBO.get("COST_CODE_NAME"));
                    costShipBO.set("NAME", DBSql.getString("select NAME from BO_EU_DND_COST_CODE where OID=? AND ORGID=?", new Object[]{productBO.get("COST_CODE_ID"), processExecutionContext.getUserContext().getCompanyModel().getId()}));

                    costShipBO.set("DATE_PURCHASED", LocalDate.now());
                    costShipBO.set("COST_TYPE_ID", 1228);// 运营成本
                    costShipBO.set("STATUS_ID", 1237);// 已配送
                    costShipBO.set("IS_BILLABLE", 1);
                    costShipBO.set("QUANTITY", 1);

                    costShipBO.set("UNIT_PRICE", productBO.get("COST_CODE_PRICE"));
                    costShipBO.set("UNIT_COST", productBO.get("COST_CODE_COST"));
                    costShipBO.set("EXTENDED_PRICE", productBO.get("COST_CODE_PRICE"));
                    costShipBO.set("SUB_CATE_ID", costBO.get("SUB_CATE_ID"));
                    costShipBO.set("PROJECT_ID", costBO.get("PROJECT_ID"));
                    costShipBO.set("ACCOUNT_ID", costBO.get("ACCOUNT_ID"));
                    costShipBO.set("BILL_ACCOUNT_ID", costBO.get("BILL_ACCOUNT_ID"));

                    if (costShipProcessIns != null)
                        SDK.getBOAPI().create("BO_EU_DNCTT_CONTRACT_COST", costShipBO, costShipProcessIns, processExecutionContext.getUserContext(), conn);
                    else
                        SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST", costShipBO, conn);

                    //关联产品成本
                    DBSql.update(conn, "update BO_EU_DNCTT_CONTRACT_COST_PRODUCT set SHIPPING_CONTRACT_COST_ID=? where ID=?", new Object[]{costShipBO.getId(), productBO.getId()});
                }


                //配送成功后，更新产品成本：产品来源于采购---从采购单获取，成本取自采购单；库存拣货，成本取自库存产品
                if (DBSql.getInt(conn, "select count(ID) from BO_EU_DNCTT_CONTRACT_COST_PRODUCT where CONTRACT_COST_ID=? AND STATUS_ID<2159  AND CLOSED=0", new Object[]{costBO.getId()}) == 0) {
                    //已全部配送完成
                    costBO.set("STATUS_ID", 1237);//已配送
                    Double UNIT_COST = 0.0;
                    if (OUT_RULE != null && OUT_RULE.equals("1030")) {
                        //库存平均单元成本
                        UNIT_COST = DBSql.getDouble(conn, "SELECT UNIT_COST_AVG FROM BO_EU_DNIVT_PRODUCT WHERE ID='" + fromWarehouseProductBO.getString("PRODUCT_ID") + "'", "UNIT_COST_AVG");

                    } else {
                        UNIT_COST = DBSql.getDouble(conn, "SELECT SUM(UNIT_COST*QUANTITY)/SUM(QUANTITY) AS UNIT_COST FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT WHERE CONTRACT_COST_ID='" + costBO.getId() + "' AND CLOSED=0", "UNIT_COST");
                    }

                    costBO.set("UNIT_COST", UNIT_COST.toString());
                    //   costBO.set("EXTENDED_COST", UNIT_COST * (int) Math.round(Double.parseDouble(costBO.getString("QUANTITY"))));

                    Double EXTENDED_COST = UNIT_COST * Integer.parseInt(costBO.getString("QUANTITY"));

                    costBO.set("EXTENDED_COST", EXTENDED_COST.toString());

                    System.out.println("UNIT_COST=" + UNIT_COST);
                    System.out.println("EXTENDED_COST=" + EXTENDED_COST);

                    dn.recordFormChanges.record(processExecutionContext.getUserContext(), costBO, "产品配送后", conn);

                    SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST", costBO, conn);

                }
                conn.commit();
            }catch (Exception e) {
                // 1. 回滚事务（保持原有逻辑）
                if (conn != null) {
                    try {
                        conn.rollback();
                    } catch (SQLException rollbackEx) {
                        // 打印回滚失败日志
                        System.err.println("事务回滚失败：" + rollbackEx.getMessage());
                        rollbackEx.printStackTrace();
                    }
                }

                // 2. 打印详细异常信息（关键：输出异常类型、消息、堆栈，以及关键业务参数）
                System.err.println("===== 库存转移异常详情 =====");
                System.err.println("异常类型：" + e.getClass().getName());
                System.err.println("异常消息：" + e.getMessage());
                System.err.println("关键业务参数：");
                System.err.println("  产品ID：" + (productBO != null ? productBO.getString("PRODUCT_ID") : "null"));
                System.err.println("  配送数量：" + (productBO != null ? productBO.get("QUANTITY") : "null"));
                System.err.println("  仓库ID：" + (productBO != null ? productBO.get("WAREHOUSE_ID") : "null"));
                System.err.println("  产品序列号：" + (productBO != null ? productBO.getString("SHIPPING_SN") : "null"));
                System.err.println("==========================");
                e.printStackTrace();

                // 3. 抛出兜底异常（保持原有逻辑，可补充具体异常消息）
                throw new BPMNError("550", "库存转移失败：" + e.getMessage());
            }finally {
                DBSql.close(conn);
            }
        }
    }


    /**
     * 将Object转换为int
     * @param obj
     * @return
     */
    private int ObjToInt(Object obj) {
        if (obj == null)
            return 0;

        String objStr = obj.toString();
        if (objStr.equals(""))
            return 0;
        //如果有小数点，只取整数
        if (objStr.contains(".")) {
            objStr = objStr.substring(0, objStr.indexOf("."));
        }
        return Integer.parseInt(objStr);
    }
}
