package com.brilliance.isc.common.limmod.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.brilliance.mda.runtime.mda.config.IniConfig;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import com.brilliance.isc.bo.Stb;
import com.brilliance.isc.common.api.bch.service.BchService;
import com.brilliance.isc.common.codetable.service.CodetableService;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.context.SpringEnvContext;
import com.brilliance.isc.common.counter.service.CounterService;
import com.brilliance.isc.common.esb.clm.IClmFeign;
import com.brilliance.isc.common.exception.CommonServiceException;
import com.brilliance.isc.common.limmod.service.LimCecmService;
import com.brilliance.isc.common.limmod.service.LimOptionService;
import com.brilliance.isc.common.limmod.service.LimmodService;
import com.brilliance.isc.common.limmod.vo.LimgrdVo;
import com.brilliance.isc.common.limmod.vo.LimmodVo;
import com.brilliance.isc.common.register.lim.ILimRegister;
import com.brilliance.isc.common.transaction.eventlistener.EventVo;
import com.brilliance.isc.common.transaction.eventlistener.IDoRollback;
import com.brilliance.isc.common.transaction.help.TransactionHelpService;
import com.brilliance.isc.common.trnmod.vo.TrnmodVo;
import com.brilliance.isc.common.wfmmod.vo.WfmmodVo;
import com.brilliance.isc.esb.model.inner.*;
import com.brilliance.isc.mda.dao.StbMapper;
import com.brilliance.isc.mda.dao.WfeMapper;
import com.brilliance.isc.transfer.esb.IEsbMapper;
import com.brilliance.isc.utils.StringUtils;
import com.brilliance.isc.vo.manager.StbVo;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ws.rs.POST;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service("limocc")
public class LimOccServiceImpl implements LimOptionService<InnerResCL43> {

    @Autowired
    private LimmodService limmodService;
    @Autowired
    private CodetableService codetableService;
    @Autowired(required = false)
    private IClmFeign clmFeign;

    @Autowired
    private TransactionHelpService transactionHelpService;

    @Autowired
    private CounterService counterService;
    @Autowired
    private WfeMapper wfeMapper;
    @Autowired
    private StbMapper stbMapper;
    @Resource(name = "limprecal")
    private LimOptionService limprecalService;
    public static final Logger logger = LoggerFactory.getLogger(LimOccServiceImpl.class);

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private BchService bchService;
    @Resource
    private LimCecmService limCecmService;

    //    @WatchDog(name = "额度试算")
    @Override
    public void assertLim(LimmodVo limmodVo) {
        logger.info("-----------开始处理额度占用试算{}{}------------", limmodVo.getRec().getOwnref(), SettleContext.getTransName());
        logger.info("额度计算标志 opnflg {}", limmodVo.getLimpts().getOpnflg());
        limmodService.LimRegParstm(limmodVo);
        if (!limmodService.cL43oPn(limmodVo) || !limmodService.limRegister().needRecalcLimits(limmodVo) || "N".equals(limmodVo.getLimpts().getOpnflg())) {
            return;
        }
        limmodService.checkData(limmodVo);
        checkData(limmodVo);
        limmodService.limRegister().simpleCheck(limmodVo);
        limmodService.limRegister().limOccRegister(limmodVo);
        limmodService.limRegister().resPonseMapping(limmodVo);
        logger.info("-----------额度占用试算结束{}{}------------", limmodVo.getRec().getOwnref(), SettleContext.getTransName());

    }

    @Override
    public void callEsb(LimmodVo limmodVo) {

//        String itfinr = "";

//        itfinr = counterService.dbCounterFormat("CLMSH", 6);

        InnerReqCL43 innerReqCL43 = new InnerReqCL43();
        innerReqCL43.reqCL43 = IEsbMapper.INSTANCE.copyLimOcc(limmodVo.getLimOccVo());
        innerReqCL43.BRANCH = SettleContext.getUserSession().getOrgBch().getBranch();
        innerReqCL43.INIUSR = SettleContext.getUserSession().getUsr().getNam();
        innerReqCL43.QANTLS = limmodVo.getLimOccVo().Qtls;
        InnerReq<InnerReqCL43> innerReqCL43InnerReq = new InnerReq<>(innerReqCL43);
        Header header = new Header();
        innerReqCL43InnerReq.header = header;
        innerReqCL43InnerReq.header.itfinr = limmodVo.getLimOccVo().Qtls;

        limmodVo.setItfinr(limmodVo.getLimOccVo().Qtls);
        innerReqCL43InnerReq.header.ref = limmodVo.getTrninr();
        InnerRes<InnerResCL43> innerResCL43InnerRes = null;
        try {
            innerResCL43InnerRes = clmFeign.callCL43(innerReqCL43InnerReq);
        } catch (Exception e) {
            limmodService.limRePair(limmodVo.getTrninr());
            throw new CommonServiceException(StringUtils.stringAppend("额度占用接口调用失败:", e.getMessage()));
        }
        if ("AAAAAAA".equals(innerResCL43InnerRes.header.code)) {
            limmodVo.setIntsta("D");
            if (logger.isDebugEnabled()) {
                logger.debug("额度占用接口调用成功{}", JSON.toJSONString(limmodVo.getLimOccVo()));
            }
            responseMapping(innerResCL43InnerRes, limmodVo);
            //注册额度占用接口回滚事件
            applicationEventPublisher.publishEvent(EventVo.builder().rollback(() -> {
                rollBack(limmodVo);
            }).srv("LMA").build());
        } else {
            limmodVo.setIntsta("E");
            limmodService.limRePair(limmodVo.getTrninr());
            throw new CommonServiceException(StringUtils.stringAppend("额度占用接口调用失败:", innerResCL43InnerRes.header.description));
        }
    }

    @Override
    public void limDataCal(LimmodVo limmodVo) {
        limmodService.genCL43Data(limmodVo);

    }

    @Override
    public void LimRegParstm(LimmodVo limmodVo) {
        logger.info("-----------开始处理额度占用数据保存{}{}------------", limmodVo.getRec().getOwnref(), SettleContext.getTransName());
        if ("E".equals(limmodVo.getLimpts().getErrorflg())) {
            return;
        }
        logger.info("额度计算标志 opnflg {}", limmodVo.getLimpts().getOpnflg());
        if (!cL43oPn() || "N".equals(limmodVo.getLimpts().getOpnflg())) {
            //查询表上一条
            //如果是pam pdl ppl can pse
            // 那就复制一条 修改trninr  和 inifrm 为总行交易码
            return;
        }
        if (!limmodService.limRegister().needRecalcLimits(limmodVo)) {
            limmodService.rootBchDeal(limmodVo);
            return;
        }
        saveTables(limmodVo);
        limCecmService.saveCecm(limmodVo);
        if ("Y".equals(limmodVo.getLmaflg())) {
            callEsb(limmodVo);
        }else {
            //注册额度非占用回滚事件
            applicationEventPublisher.publishEvent(EventVo.builder().rollback(() -> {
                limmodService.limRePair(limmodVo.getTrninr());
            }).srv("LMO").build());
        }
        logger.info("-----------额度占用保存结束{}{}------------", limmodVo.getRec().getOwnref(), SettleContext.getTransName());
    }

    @Override
    public void responseMapping(InnerRes<InnerResCL43> innerRes, LimmodVo limmodVo) {
        TrnmodVo trnmodVo = transactionHelpService.getTransactionStoreSet().getTrnmodVo();
        WfmmodVo wfmmodVo = trnmodVo.getTrnism().getWfmmod();
        wfmmodVo.getWfe().stream()
                .map(wfe -> {
                    if ("LMA".equals(wfe.getSrv())) {
                        wfe.setSta("D");
                        wfe.setTxt(String.format("接口成功|额度流水号:%s", innerRes.DATA.guiyls));
                        wfe.setItfinr(limmodVo.getItfinr());
                        return wfe;
                    } else {
                        return wfe;
                    }
                }).collect(Collectors.toList());
//        wfmmodVo.getSro().add("LMA");
    }


    @Override
    public void saveTables(LimmodVo limmodVo) {
        limmodService.limSav3000(limmodVo);
    }

    public boolean cL43oPn() {
        StbVo stbVo = new StbVo();
        stbVo.setTbl("CL43OP");
        List<Stb> stbs = stbMapper.queryByPage(stbVo);
        logger.info("额度开关{}", stbs.get(0).getCod());
        return "Y".equals(stbs.get(0).getCod()) ? true : false;
    }

    public void checkData(LimmodVo limmodVo) {
        // 如果没有勾选
        Map rulemap = limmodVo.getErrorVo().getRulemap();

        List<LimgrdVo> list = new ArrayList<>();
        if (limmodVo.getLimQueryVo() != null && CollectionUtil.isNotEmpty(limmodVo.getLimQueryVo().getLimgrdVoList())) {
            for (LimgrdVo limgrdVo : limmodVo.getLimQueryVo().getLimgrdVoList()) {
                if ("X".equals(limgrdVo.getFlg())) {
                    list.add(limgrdVo);
                } else {
                    continue;
                }
            }
        }
        if (CollectionUtil.isEmpty(list)) {
            limmodVo.getLimpts().setErrorflg("E");
//            rulemap.put("limmod.limQueryVo.limgrdVoList", "请勾选统一授信可用额度数据");
        }
        if ("1".equals(limmodVo.getLimpts().getSfzsqyw())) {
            if (StringUtils.isEmpty(limmodVo.getLimpts().getZsqkhbh())) {
                limmodVo.getLimpts().setErrorflg("E");
                rulemap.put("limmod.limpts.zsqkhbh", "转授权业务的转授权客户编号不可为空");
            }
        }
    }

    void rollBack(LimmodVo limmodVo) {
        if ("1".equals(bchService.getStartFlgByBranchInifrm(SettleContext.getUserSession().getBch().getBranch(), SettleContext.getTransName()))) {
            repaireByCl44(limmodVo);
        } else {
            repaireByCl85(limmodVo);
        }
        limmodService.limRePair(limmodVo.getTrninr());
    }

    private void repaireByCl44(LimmodVo limmodVo) {
        if (logger.isDebugEnabled()) {
            logger.debug("---------额度回滚cl44开始执行{}", limmodVo.getItfinr());
        }
        Header header = new Header();
        header.itfinr = StringUtils.stringAppend("CZ_", limmodVo.getItfinr());
        header.ref = limmodVo.getTrninr();
        InnerReq<InnerReqCL44> req = new InnerReq<>();
        InnerReqCL44 data = new InnerReqCL44();
        data.flag = "2";
        req.DATA = data;
        req.header = header;
        InnerRes<InnerResCL44> innerRes = clmFeign.callCL44(req);

        if ("AAAAAAA".equals(innerRes.header.code)) {
            if (logger.isDebugEnabled()) {
                logger.debug("-----------额度回滚cl44接口调用成功{}", limmodVo.getItfinr());
            }
        } else {
            limmodVo.setIntsta("E");
            throw new CommonServiceException(StringUtils.stringAppend("额度回滚cl44接口调用失败"));
        }
    }

    private void repaireByCl85(LimmodVo limmodVo) {
        if (logger.isDebugEnabled()) {
            logger.debug("---------额度回滚cl85开始执行{}", limmodVo.getItfinr());
        }
        Header header = new Header();
        header.ref = limmodVo.getTrninr();
        header.itfinr = limmodVo.getItfinr();
        InnerReq<InnerReqCL85> req = new InnerReq<>();
        InnerReqCL85 data = new InnerReqCL85();
        data.flag = "0";
        req.DATA = data;
        req.header = header;
        InnerRes<InnerResCL85> innerRes = clmFeign.callCL85(req);

        if ("AAAAAAA".equals(innerRes.header.code)) {
            if (logger.isDebugEnabled()) {
                logger.debug("-----------额度回滚cl85接口调用成功{}", limmodVo.getItfinr());
            }
        } else {
            limmodVo.setIntsta("E");
            throw new CommonServiceException(StringUtils.stringAppend("额度回滚cl85接口调用失败"));
        }
    }
}
