package nc.bs.pub.action;

import nc.bs.arap.actions.N_BASE_ACTION;
import nc.bs.arap.gatheringbp.GatherBillBO;
import nc.bs.arap.util.GatheringBillAfter;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.impl.pubapp.env.BSContext;
import nc.pubitf.so.m30.sobalance.ISoBalance4VerifyQryBill;
import nc.vo.arap.gathering.AggGatheringBillVO;
import nc.vo.arap.pub.ArapConstant;
import nc.vo.arap.pub.BillEnumCollection;
import nc.vo.arap.receivable.ReceivableBillItemVO;
import nc.vo.arap.utils.StringUtil;
import nc.vo.fi.pub.SqlUtils;
import nc.vo.fipub.exception.ExceptionHandler;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.compiler.PfParameterVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDouble;
import nccloud.bs.arap.util.commit.ArapCommitUtil;
import nccloud.impl.platform.common.util.StringUtils;
import nccloud.pubitf.arap.arappub.IArapBillPubUtilService;

import java.util.*;


public class N_F2_SAVE extends N_BASE_ACTION {
    private Hashtable<String, Object> m_keyHas = null;


    public String getCodeRemark() {
        return " arap action script not allowed to modify ,all rights reserved!";
    }


    public Object runComClass(PfParameterVO paraVo) throws BusinessException {
        try {
            super.m_tmpVo = paraVo;
            Object obj = null;
            setParameter("context", paraVo.m_preValueVos);

            if (paraVo.isCloudEntry) {

                String actionCode = ArapConstant.SAVE;
                ((IArapBillPubUtilService) NCLocator.getInstance().lookup(IArapBillPubUtilService.class)).interceptorVaildator(paraVo.m_preValueVos, actionCode);
            }


            String code = InvocationInfoProxy.getInstance().getProperty(ArapConstant.NCCFlOW_PARAMTER);
            if (!StringUtils.isEmpty(code)) {
                String[] codes = code.split(",");
                for (int i = 0; i < codes.length; i++) {
                    BSContext.getInstance().setSession(codes[i], UFBoolean.FALSE);
                }
            }

            this.beforeCheck();

            AggregatedValueObject bill = (paraVo.m_preValueVo == null) ? paraVo.m_preValueVos[0] : paraVo.m_preValueVo;
            if (bill != null && bill.getChildrenVO() != null && bill.getChildrenVO().length > 0 && bill.getChildrenVO()[0] != null) {
                String pk_billtype = (String) bill.getChildrenVO()[0].getAttributeValue("pk_billtype");
                String top_billtype = (String) bill.getChildrenVO()[0].getAttributeValue("top_billtype");
                String src_billtype = (String) bill.getChildrenVO()[0].getAttributeValue("src_billtype");

                if ("F2".equals(pk_billtype) && "30".equals(src_billtype) && "F0".equals(top_billtype)) {

                    Map<String, UFDouble> f2mnyMap = new HashMap<>();
                    Map<String, UFDouble> f0mnyMap = new HashMap<>();

                    List<String> orderIds = new ArrayList<>();
                    List<String> f0pks = new ArrayList<>();
                    for (int i = 0; i < bill.getChildrenVO().length; i++) {
                        String src_billid = (String) bill.getChildrenVO()[i].getAttributeValue("src_billid");
                        UFDouble money_bal = (UFDouble) bill.getChildrenVO()[i].getAttributeValue("money_bal");
                        if (!StringUtil.isEmpty(src_billid)) {
                            orderIds.add((String) bill.getChildrenVO()[i].getAttributeValue("src_billid"));
                        }
                        if (f2mnyMap.get(src_billid) == null) {
                            f2mnyMap.put(src_billid, money_bal);
                        } else {
                            f2mnyMap.put(src_billid, ((UFDouble) f2mnyMap.get(src_billid)).add(money_bal));
                        }
                        f0pks.add((String) bill.getChildrenVO()[i].getAttributeValue("top_billid"));
                    }

                    String f0sql = SqlUtils.getInStr("pk_recbill", (String[]) f0pks.toArray(new String[0]), true);

                    Collection<ReceivableBillItemVO> foItemvos = (new BaseDAO()).retrieveByClause(ReceivableBillItemVO.class, f0sql);
                    for (ReceivableBillItemVO vo : foItemvos) {
                        String src_billid = (String) vo.getAttributeValue("src_billid");
                        UFDouble money_bal = (UFDouble) vo.getAttributeValue("money_bal");
                        if (f0mnyMap.get(src_billid) == null) {
                            f0mnyMap.put(src_billid, money_bal);
                            continue;
                        }
                        f0mnyMap.put(src_billid, ((UFDouble) f0mnyMap.get(src_billid)).add(money_bal));
                    }


                    Map<String, Map<String, UFDouble>> soOrderIdTOF2ItemMnyMap = ((ISoBalance4VerifyQryBill) NCLocator.getInstance().lookup(ISoBalance4VerifyQryBill.class)).querySobalanceAccVerifyMnyMap((String[]) orderIds.toArray(new String[0]));
                    if (soOrderIdTOF2ItemMnyMap != null && soOrderIdTOF2ItemMnyMap.size() > 0) {
                        for (String order : orderIds) {
                            Map<String, UFDouble> mnys = (Map) soOrderIdTOF2ItemMnyMap.get(order);
                            UFDouble summny = UFDouble.ZERO_DBL;
                            if (mnys == null || mnys.size() == 0) {
                                continue;
                            }
                            for (String key : mnys.keySet()) {
                                UFDouble mny = (mnys.get(key) == null) ? UFDouble.ZERO_DBL : (UFDouble) mnys.get(key);
                                summny = summny.add(mny);
                            }
                            if (f2mnyMap.get(order) == null) {
                                f2mnyMap.put(order, summny);
                                continue;
                            }
                            f2mnyMap.put(order, ((UFDouble) f2mnyMap.get(order)).add(summny));
                        }


                        for (String order : orderIds) {
                            if (f0mnyMap.get(order) != null && f2mnyMap.get(order) != null && ((UFDouble) f2mnyMap.get(order)).abs().compareTo(((UFDouble) f0mnyMap.get(order)).abs()) > 0) {
                                throw new BusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-1678"));
                            }
                        }
                    }
                }
            }


            String primaryKey = paraVo.m_preValueVos[0].getParentVO().getPrimaryKey();

            if (hasBill(primaryKey)) {
                obj = runClass("nc.bs.arap.actions.GatheringbillEditSaveBatchBSAction", "updateVOs", "&context:nc.vo.pub.AggregatedValueObject[]", paraVo, this.m_keyHas);
            } else {

                paraVo = approveStatusChange(paraVo);
                obj = runClass("nc.bs.arap.actions.GatheringbillSaveBatchBSAction", "insertVOs", "&context:nc.vo.pub.AggregatedValueObject[]", paraVo, this.m_keyHas);
            }
            // 生成收款单后将对应的到账通知cmp_informer的生成状态generateflag修改为已生成hasgenerate
            AggGatheringBillVO[] aggVos = (AggGatheringBillVO[]) paraVo.m_preValueVos;
            GatheringBillAfter.updateInformerGenerateFlag(aggVos, "hasgenerate");

            return (new ArapCommitUtil()).autoCommit(obj);

        } catch (Exception exception) {
            throw ExceptionHandler.handleException(getClass(), exception);
        }
    }

    private boolean hasBill(String primaryKey) throws BusinessException {
        boolean hasBill = false;
        if (primaryKey != null) {
            AggGatheringBillVO[] bvos = null;
            try {
                GatherBillBO payableBO = new GatherBillBO();
                bvos = payableBO.findBillByPrimaryKey(new String[]{primaryKey});
            } catch (Exception e) {
                Logger.error(e.getMessage(), e);
            }
            if (bvos != null && bvos.length != 0 && bvos[0] != null) {
                hasBill = true;
            }
        }
        return hasBill;
    }

    protected void setParameter(String key, Object val) {
        if (this.m_keyHas == null) {
            this.m_keyHas = new Hashtable();
        }
        if (val != null)
            this.m_keyHas.put(key, val);
    }

    private PfParameterVO approveStatusChange(PfParameterVO paraVo) {
        for (AggregatedValueObject vo : paraVo.m_preValueVos) {
            vo.getParentVO().setAttributeValue("approvestatus", BillEnumCollection.ApproveStatus.NOSTATE.VALUE);
        }
        return paraVo;
    }
}