package nccloud.resources.ic.ic.saleout;

import nc.bs.businessevent.BdUpdateEvent;
import nc.bs.businessevent.BusinessEvent;
import nc.bs.businessevent.IBusinessEvent;
import nc.bs.businessevent.IBusinessListener;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.NCLocator;
import nc.bs.ic.general.businessevent.ICGeneralCommonEvent;
import nc.bs.trade.business.HYSuperDMO;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.ic.general.define.ICBillBodyVO;
import nc.vo.ic.m4c.entity.SaleOutHeadVO;
import nc.vo.ic.m4c.entity.SaleOutVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.tmpub.util.ModuleEnum;
import nc.vo.tmpub.util.ModuleUtil;
import nccloud.baseapp.core.log.NCCForUAPLogger;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


/**
 * 发货时保存时验证销售订单累计发货数量，并校验销售发票标识，并验证发货款比例
 * zhangxinah
 * 2005适配2312
 */
public class saveBeforeCheck implements IBusinessListener {

    @Override
    public void doAction(IBusinessEvent event) throws BusinessException {

        String pk_group = AppContext.getInstance().getPkGroup();
        if (ModuleUtil.isEnableByGroup(pk_group, ModuleEnum.SSCRP, false)) {
            if (event != null) {
                Map<String, SaleOutVO[]> map = this.getBills(event);
                SaleOutVO[] obills = map.get("obj");
                // 判断是否是需要控制的业务单元
                SaleOutHeadVO parentVO = obills[0].getHead();
                String pkstockorgStr = getPk_stockorg(parentVO.getPk_org());
                if (pkstockorgStr == null || pkstockorgStr.isEmpty()) {
                    return;
                }
                ICBillBodyVO[] childrenVO = obills[0].getChildrenVO();
                for (int i = 0; i < childrenVO.length; ++i) {
                    ICBillBodyVO vo = childrenVO[i];
                    Map<String, Object> valMap = getSaleorderPK(vo.getCsourcebillbid());
                    if (valMap == null || valMap.isEmpty()) {
                        return;
                    }
                    // 历史数据不考虑
                    String storedDateStr = (String) valMap.get("creationtime");
                    String targetDateStr = "2024-12-31 00:00:00";
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime storedDate = LocalDateTime.parse(storedDateStr, formatter);
                    LocalDateTime targetDate = LocalDateTime.parse(targetDateStr, formatter);
                    if (storedDate.isBefore(targetDate)) {
                        return;
                    }
                    // 在销售发票业务日期6.26号之前的不参与控制
                    String invDateStr = (String) valMap.get("dbilldate");
                    String invTargetDateStr = "2025-06-26 00:00:00";
                    LocalDateTime invDate = LocalDateTime.parse(invDateStr, formatter);
                    LocalDateTime invTargetDate = LocalDateTime.parse(invTargetDateStr, formatter);
                    if (invDate.isBefore(invTargetDate)) {
                        return;
                    }
                    // 销售发票表头pk_billtypecode=30-Cxx-12
                    Set<String> billTypeCodes = Set.of(
                            "30-Cxx-12", "30-Cxx-02", "30-Cxx-08", "30-Cxx-13", "30-Cxx-16"
                    );
                    if (billTypeCodes.contains(valMap.get("pk_billtypecode"))) {
                        return;
                    }

                    // 销售发票表头vdef21=是
                    if (valMap.get("vdef20") == null || !valMap.get("vdef20").equals("Y")) {
                        throw new BusinessException("销售出库单明细" + (i + 1) + "，销售发票验证不通过，无法保存！");
                    }
                    if (valMap.get("sqty") == null) {
                        throw new BusinessException("销售出库单明细" + (i + 1) + "，累计发货申请数量为0，无法保存！");
                    } else {
                        try {
                            double sQty = Double.parseDouble((String) valMap.get("sqty"));// 累计发货申请数量
                            UFDouble bdnumUF = vo.getNshouldassistnum();// 本单应发数量
                            double bdnum = 0;
                            if (bdnumUF != null) {
                                bdnum = bdnumUF.getDouble();
                            }
                            // 应发数量判断
                            Object ntotaloutnumsObj = valMap.get("ntotaloutnums");
                            String ntotaloutnums = (ntotaloutnumsObj != null) ? ntotaloutnumsObj.toString() : "";
                            double ntotaloutnum = (ntotaloutnums.isEmpty()) ? 0 : Double.parseDouble(ntotaloutnums);// 累计出库主数量

                            /*if (sQty < (ntotaloutnum + bdnum)) {
                                throw new BusinessException("销售出库单明细" + (i + 1) + "，累计出库应发数量'" + (ntotaloutnum + bdnum)
                                        + "'大于销售订单累计发货申请数量'" + sQty + "'，无法保存！");
                            }*/
                            // 实发数量判断
                            UFDouble bdsfnumUF = vo.getNassistnum();// 本单实发数量
                            double bdsfnum = 0;
                            if (bdsfnumUF != null) {
                                bdsfnum = bdsfnumUF.getDouble();
                            }
                            Object nassistnumObj = valMap.get("nassistnum");
                            String nassistnums = (nassistnumObj != null) ? nassistnumObj.toString() : "";
                            double nassistnum = (nassistnums.isEmpty()) ? 0 : Double.parseDouble(nassistnums);// 累计出库主数量
                            if (sQty < (nassistnum + bdsfnum)) {
                                throw new BusinessException("销售出库单明细" + (i + 1) + "，累计出库实发数量'" + (nassistnum + bdsfnum)
                                        + "'大于销售订单累计发货申请数量'" + sQty + "'，无法保存！");
                            }
                        } catch (NumberFormatException e) {
                            throw new BusinessException("累计发货申请数量、累计出库数量转化数值失败" + e);
                        }
                    }

                }

            }

        }

    }

    private Map<String, Object> getSaleorderPK(String csourcebillbidStr) throws BusinessException {
        IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);

        SqlBuilder sqlBuilder = new SqlBuilder();
        sqlBuilder.append("SELECT s.creationtime, bt.pk_billtypecode, sb.csaleorderbid, si.dbilldate, ");
        sqlBuilder.append("sb.vbdef2 AS sQty, s.vdef11, si.vdef20, sbv.nassistnum, sbv.ntotaloutnums ");
        sqlBuilder.append("FROM so_saleinvoice_b sib ");
        sqlBuilder.append("INNER JOIN so_saleinvoice si ON si.csaleinvoiceid = sib.csaleinvoiceid ");
        sqlBuilder.append("INNER JOIN so_saleorder_b sb ON sb.csaleorderbid = sib.csrcbid ");
        sqlBuilder.append("LEFT JOIN ( ");
        sqlBuilder.append("    SELECT SUM(b.nshouldassistnum) AS ntotaloutnums, SUM(nassistnum) AS nassistnum, c.csaleorderbid ");
        sqlBuilder.append("    FROM so_saleorder_b c ");
        sqlBuilder.append("    INNER JOIN so_saleinvoice_b a ON c.csaleorderbid = a.csrcbid ");
        sqlBuilder.append("    INNER JOIN ic_saleout_b b ON b.csourcebillbid = a.csaleinvoicebid ");
        sqlBuilder.append("    WHERE a.dr = 0 AND b.dr = 0 ");
        sqlBuilder.append("    GROUP BY c.csaleorderbid ");
        sqlBuilder.append(") sbv ON sbv.csaleorderbid = sb.csaleorderbid ");
        sqlBuilder.append("INNER JOIN so_saleorder s ON s.csaleorderid = sb.csaleorderid ");
        sqlBuilder.append("INNER JOIN bd_billtype bt ON bt.pk_billtypeid = s.ctrantypeid ");
        sqlBuilder.append("INNER JOIN so_saleorder_exe se ON sb.csaleorderbid = se.csaleorderbid ");
        sqlBuilder.append("WHERE ");
        sqlBuilder.append("sib.csaleinvoicebid", csourcebillbidStr);

        String sql = sqlBuilder.toString();
        Map<String, Object> valList = (Map<String, Object>) queryBS.executeQuery(sql, new MapProcessor());

        return valList;
    }

    public IUAPQueryBS getQueryService() {
        return NCLocator.getInstance().lookup(IUAPQueryBS.class);
    }

    private Map<String, SaleOutVO[]> getBills(IBusinessEvent event) throws BusinessException {
        Object object = null;
        Object old = null;
        Map<String, SaleOutVO[]> retMap = new HashMap<>();
        // 类型判断和赋值
        if (event instanceof BusinessEvent) {
            BusinessEvent bills = (BusinessEvent) event;
            object = bills.getObject();
        } else if (event instanceof BdUpdateEvent) {
            BdUpdateEvent e = (BdUpdateEvent) event;
            object = e.getNewObject();
            old = e.getOldObject();
        } else if (event instanceof ICGeneralCommonEvent) {
            ICGeneralCommonEvent e = (ICGeneralCommonEvent) event;
            object = e.getNewObjs();
            old = e.getOldObjs();
        } else {
            throw new BusinessException("未找到单据类型");
        }
        // 将 object 和 old 转换为 SaleOutVO[] 并添加到 retMap
        retMap.put("new", toSaleOutVOArray(object));
        retMap.put("old", toSaleOutVOArray(old));
        // 根据 new 或 old 来设置 "obj"
        retMap.put("obj", retMap.get("new") != null ? retMap.get("new") : retMap.get("old"));
        return retMap;
    }

    // 辅助方法：将对象转换为 SaleOutVO 数组
    private SaleOutVO[] toSaleOutVOArray(Object object) {
        if (object == null) {
            return null;
        }
        if (object.getClass().isArray()) {
            return (SaleOutVO[]) object;
        } else {
            return new SaleOutVO[]{(SaleOutVO) object};
        }
    }

    private String getPk_stockorg(String pk_stockorg) throws BusinessException {
        Map<String, String> defMap = checkOrgCtrl();
        if (defMap.isEmpty() || "".equals(defMap.getOrDefault("so_out", ""))) {
            return "";
        }
        String orgStr = defMap.getOrDefault("so_out", "");
        // 将数组转换为字符串，并添加单引号
        String newOrgStr = orgStr.replace(",", "','");
        String sql = " select pk_stockorg from org_stockorg where code in ('" + newOrgStr + "') and pk_stockorg='"
                + pk_stockorg + "' ";
        NCCForUAPLogger.debug("so_out-getPk_stockorg-sql:" + sql);
        String saleorderPK = (String) getQueryService().executeQuery(sql, new ColumnProcessor());
        return saleorderPK;
    }

    private Map<String, String> checkOrgCtrl() {
        Map<String, String> map = new HashMap<String, String>();
        String strWhere = " pk_defdoclist in (select pk_defdoclist from bd_defdoclist where code='org-ctrl' and dr=0 )  and dr=0";
        try {
            DefdocVO[] defdocVOs = (DefdocVO[]) new HYSuperDMO().queryByWhereClause(DefdocVO.class, strWhere);
            if (defdocVOs != null && defdocVOs.length > 0) {
                for (DefdocVO defdocVO : defdocVOs) {
                    map.put(defdocVO.getCode().trim(), defdocVO.getMemo());
                }
            }
        } catch (DAOException e) {
            e.printStackTrace();
        }
        return map;
    }

}
