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

import com.alibaba.fastjson2.JSON;
import com.brilliance.mda.runtime.mda.util.Dates;
import com.brilliance.mda.runtime.mda.util.Decimals;
import com.brilliance.mda.runtime.mda.util.MdaUtils;
import com.brilliance.mda.runtime.mda.util.Strings;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import cn.hutool.core.date.DateUtil;
import com.brilliance.isc.bo.Stb;
import com.brilliance.isc.common.cache.atpbch.AtpBchCacheService;
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.esb.clm.IClmFeign;
import com.brilliance.isc.common.esb.yapin.IYapinFeign;
import com.brilliance.isc.common.exception.CommonServiceException;
import com.brilliance.isc.common.limmod.service.LimmodService;
import com.brilliance.isc.common.limmod.service.YpnmodService;
import com.brilliance.isc.common.limmod.vo.*;
import com.brilliance.isc.common.register.lim.ILimRegister;
import com.brilliance.isc.common.register.lim.IYpnRegister;
import com.brilliance.isc.common.transaction.newcheck.ValidResult;
import com.brilliance.isc.esb.model.inner.*;
import com.brilliance.isc.mda.dao.StbMapper;
import com.brilliance.isc.transfer.esb.IEsbMapper;
import com.brilliance.isc.utils.BigDecimalUtils;
import com.brilliance.isc.utils.DateUtils;
import com.brilliance.isc.utils.StringUtils;
import com.brilliance.isc.vo.manager.StbVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class YpnmodServiceImpl implements YpnmodService {

    @Autowired(required = false)
    private IClmFeign clmFeign;
    @Autowired(required = false)
    private IYapinFeign yapinFeign;
    @Autowired
    private StbMapper stbMapper;

    @Autowired
    private AtpBchCacheService atpBchCacheService;

    private static final String NULLSTR = "";

    private static final String TRANS = "GITOPN,GITPOP,NITPOP,NITOPN,HITPOP,HITOPN,DITOPN,LITOPN";
    @Autowired(required = false)
    private CodetableService codetableService;

    public static final Logger logger = LoggerFactory.getLogger(YpnmodServiceImpl.class);

    public static final String YP_TYPES = "ZY0102001,ZY0102002,ZY0102005,ZY0102006,ZY0102007";

    @Override
    public void assertYpn(YpnmodVo ypnmodVo) {
        if (!ypnoPn()) {
            logger.info("押品开关关闭不需要计算押品");
            return;
        }
        yapinCheck(ypnmodVo);
        //交易下检核
        IYpnRegister register = bussinessCheck();
        if (register != null) {
            register.yapinCheck(ypnmodVo);
        }
        String mac = calmac(ypnmodVo.getLimmod());
        if (!StringUtils.isEmpty(ypnmodVo.getMac()) && ypnmodVo.getMac().equals(mac)) {
            logger.info("同一笔额度不计算押品");
            ypnmodVo.setMac(mac);
            return;
        }
        ypnmodVo.setMac(mac);
        // todo 加双占的情况
        if (!"2".equals(ypnmodVo.getLimmod().getLimpts().getNonrevflg1())) {
            return;
        }
        ypnmodVo.getLimmod().getLimQueryVo().getLimgrdVoList().forEach(limgrdVo -> {
                    if ("X".equals(limgrdVo.getFlg())) {
                        if ("1".equals(limgrdVo.getBfx())) {
                            ypnmodVo.getYpInfoVo().setEdfxlx("低风险");
                        } else {
                            ypnmodVo.getYpInfoVo().setEdfxlx("一般风险");
                        }
                        ypnmodVo.getYpInfoVo().setLimref(limgrdVo.getLimref());
                    }
                }
        );
        if (StringUtils.isEmpty(ypnmodVo.getYpInfoVo().getLimref())) {
            logger.info("该笔业务额度中没有押品可以计算");
            return;
        }

        ypnmodVo.getYpInfoVos().clear();
        callCl42(ypnmodVo);
        callCs06(ypnmodVo);
    }

    IYpnRegister bussinessCheck() {
        //按照交易码，获取注册Spring的交易Bean
        String transName = SettleContext.getTransName();
        try {
            return SpringEnvContext.getBean(atpBchCacheService.getSdTransNameForRegister().toLowerCase() + "." + "yapinRegister");

        } catch (NoSuchBeanDefinitionException e) {
            logger.info("没有找到交易注册类", e.getMessage());
        }
        return null;
    }

    public void doCheck(YpnmodVo ypnmodVo) throws Exception {
        YpInfoVo ypInfoVo = ypnmodVo.getYpInfoVo();
        YapinBussiVo yapinBussiVo = ypnmodVo.getYapinBussiVo();
        if (yapinBussiVo.getCur() == null ||
                yapinBussiVo.getPtyextkey() == null ||
                yapinBussiVo.getRzflg() == null) {
            return;
        }
        if (ypInfoVo.getLOANCURRENCY().equals(yapinBussiVo.getCur()) &&
                ypInfoVo.getGUARCUSID().equals(yapinBussiVo.getPtyextkey()) &&
                "Y".equals(yapinBussiVo.getRzflg())) {
            yapinBussiVo.setCdje(BigDecimalUtils.add(4, yapinBussiVo.getRat().multiply(yapinBussiVo.getIntday()).divide(BigDecimal.valueOf(360)), BigDecimal.valueOf(1)));
            if (MdaUtils.compareTo(ypInfoVo.getATTRIBUTE11(), yapinBussiVo.getCdje()) < 0) {
                ypnmodVo.getErrorVo().getRulemap().put("ypnmod.ypInfoVo.attribute11", "不符合我行业务管理规定");
            }

            if (MdaUtils.compareTo(Dates.diff(Dates.today(), DateUtil.parseDate(ypInfoVo.getCDQSR())), yapinBussiVo.getDay()) < 0) {
                ypnmodVo.getErrorVo().getRulemap().put("ypnmod.ypInfoVo.cdqsr", "不符合我行业务管理规定");
            }
            LocalDate localDate = LocalDate.now();

            LocalDate v3year = localDate.plusYears(3);
            LocalDate v3year1 = localDate.plusDays(Long.getLong(ypInfoVo.getCDDQR()));
            LocalDate v3year2 = localDate.plusYears(2);

            Instant instant = yapinBussiVo.getMatdat().toInstant();
            ZoneId zoneId = ZoneId.systemDefault();
            LocalDate matdat = instant.atZone(zoneId).toLocalDate();

            if (v3year1.compareTo(v3year) > 0) {
                if (matdat.compareTo(v3year2) > 0) {
                    ypnmodVo.getErrorVo().getRulemap().put("ypnmod.ypInfoVo.syqx", "不符合我行业务管理规定");
                }
            }
            if (v3year1.compareTo(v3year) < 0) {
                if (MdaUtils.compareTo(yapinBussiVo.getIntday(), Decimals.div(ypInfoVo.getSyqx(), 2)) > 0) {
                    ypnmodVo.getErrorVo().getRulemap().put("ypnmod.ypInfoVo.syqx", "不符合我行业务管理规定");
                }
            }
        }

    }

    void callCs06(YpnmodVo ypnmodVo) {
        InnerReqCS06 innerReqCS06 = new InnerReqCS06();
        innerReqCS06.lstCS06 = new ArrayList<>();
        if (CollectionUtils.isEmpty(ypnmodVo.getYpInfoVos())) {
            logger.info("------------未查到押品编号");
            ypnmodVo.setYpInfoVo(new YpInfoVo());
            return;
        }
        ypnmodVo.getYpInfoVos().forEach(ypInfoVo -> {
            InnerReqCS06.lstCS06 lstCS06 = new InnerReqCS06.lstCS06();
            lstCS06.guarno = ypInfoVo.getGuarno();
            innerReqCS06.lstCS06.add(lstCS06);
        });
        InnerReq<InnerReqCS06> innerReqCS06InnerReq = new InnerReq<>(innerReqCS06);
        InnerRes<InnerResCS06> innerResCS06InnerRes = yapinFeign.callCS06(innerReqCS06InnerReq);

        if ("AAAAAAA".equals(innerResCS06InnerRes.header.code)) {
            dealCs06Res(innerResCS06InnerRes, ypnmodVo);
            if (logger.isDebugEnabled()) {
                logger.debug("押品详细信息查询接口调用成功");
            }
        } else {
            throw new CommonServiceException(StringUtils.stringAppend("押品详细信息查询接口调用失败:", innerResCS06InnerRes.header.description));
        }
        /**测试数据
         InnerRes<InnerResCS06> innerResCS06InnerRes = new InnerRes<>();
         InnerResCS06 innerResCS06 = new InnerResCS06();
         for (int i = 0; i < 3; i++) {
         InnerResCS06.ItemCS06 itemCS06 = new InnerResCS06.ItemCS06();
         itemCS06.ATTRIBUTE11 = "11000";
         itemCS06.CDDQR="2023-10-03";
         itemCS06.CDQSR="2023-10-03";
         itemCS06.GUARCUSID="2005348503";
         itemCS06.GUARTYPECD="ZY0102001";
         itemCS06.GUARTYPECDCNNAME="对公大额存单";
         itemCS06.GUARSTATE="01";
         itemCS06.LOANCURRENCY="01";
         itemCS06.STATENAME="正常";
         innerResCS06.lstCS06.add(itemCS06);
         }
         innerResCS06InnerRes.DATA=innerResCS06;
         **/
        dealCs06Res(innerResCS06InnerRes, ypnmodVo);
    }

    /**
     * 查询该笔额度项下押品编号
     *
     * @param ypnmodVo
     */
    void callCl42(YpnmodVo ypnmodVo) {
        InnerReqCL42 innerReqCL42 = new InnerReqCL42();
        innerReqCL42.khtyp = "1";
        innerReqCL42.limtyp = "2";
        innerReqCL42.limnum = ypnmodVo.getYpInfoVo().getLimref();
        innerReqCL42.limsta = "01";
        innerReqCL42.rzbch = SettleContext.getUserSession().getBch().getBranch();
        innerReqCL42.fhyhao = "1";
        innerReqCL42.mytshu = "20";
        innerReqCL42.bchusr = SettleContext.getUserSession().getUsr().getExtkey();
        innerReqCL42.accbch = SettleContext.getUserSession().getBch().getBranch();

        InnerReq<InnerReqCL42> innerResCL42InnerReq = new InnerReq<InnerReqCL42>(innerReqCL42);
        InnerRes<InnerResCL42> innerResCL42InnerRes = clmFeign.callCL42(innerResCL42InnerReq);
        if ("AAAAAAA".equals(innerResCL42InnerRes.header.code)) {
            dealCl42Res(innerResCL42InnerRes, ypnmodVo);
            if (logger.isDebugEnabled()) {
                logger.debug("额度押品编号查询接口调用成功");
            }
        } else {
            throw new CommonServiceException(StringUtils.stringAppend("额度押品编号查询接口调用失败:", innerResCL42InnerRes.header.description));
        }
    }

    /**
     * 查看押品详细信息
     *
     * @param ypnmodVo
     */
    void dealCs06Res(InnerRes<InnerResCS06> innerResCS06InnerRes, YpnmodVo ypnmodVo) {
        IEsbMapper.INSTANCE.copyYpn(innerResCS06InnerRes.DATA, ypnmodVo);
        logger.info("押品返回结果{}", innerResCS06InnerRes.DATA.lstCS06.size());

        ypnmodVo.getYpInfoVos().stream().filter(ypInfoVo -> YP_TYPES.contains(ypInfoVo.getGUARTYPECD()) && "01".equals(ypInfoVo.getGUARSTATE())).collect(Collectors.toList());
        BigDecimal sumamt = BigDecimal.ZERO;
        Date startdate = null;
        Date enddate = null;
        try {
            startdate = DateUtil.parseDate("2001-01-01");
            enddate = DateUtil.parseDate("2299-01-01");

            for (YpInfoVo ypInfoVo : ypnmodVo.getYpInfoVos()) {
                ypnmodVo.getYpInfoVo().setLOANCURRENCY(ypInfoVo.getLOANCURRENCY());
                sumamt = sumamt.add(BigDecimalUtils.string2BigDecimal(ypInfoVo.getATTRIBUTE11()));
                BigDecimalUtils.string2BigDecimal(ypInfoVo.getATTRIBUTE11());
                ypnmodVo.getYpInfoVo().setGUARCUSID(ypInfoVo.getGUARCUSID());
                if (startdate.compareTo(DateUtil.parseDate(ypInfoVo.getCDQSR())) <= 0) {
                    startdate = DateUtil.parseDate(ypInfoVo.getCDQSR());
                }
                if (enddate.compareTo(DateUtil.parseDate(ypInfoVo.getCDDQR())) >= 0) {
                    enddate = DateUtil.parseDate(ypInfoVo.getCDDQR());
                }
//                ypInfoVo.setSyqx(DateUtil.getIntervalDays(DateUtil.parseDate(ypInfoVo.getCDQSR()), DateUtil.parseDate(ypInfoVo.getCDDQR())));
                //测试
//                ypInfoVo.setGuarno("122345555");
                ypInfoVo.setLoancurrencynam(codetableService.getTblKey(ypInfoVo.getLOANCURRENCY(), "CURKEY"));
            }
        } catch (Exception e) {
            logger.error("日期转换出错{}", e);
        }
        ypnmodVo.getYpInfoVo().setATTRIBUTE11(BigDecimalUtils.BigD2stringHalfUP(sumamt, 2));
        ypnmodVo.getYpInfoVo().setCDQSR(DateUtil.format(startdate, "yyyy-MM-dd"));
        ypnmodVo.getYpInfoVo().setCDDQR(DateUtil.format(enddate, "yyyy-MM-dd"));
        ypnmodVo.getYpInfoVo().setLoancurrencynam(codetableService.getTblKey(ypnmodVo.getYpInfoVo().getLOANCURRENCY(), "CURKEY"));
//        ypnmodVo.getYpInfoVo().setSyqx(DateUtil.getIntervalDays(DateUtils.getNowDate(), enddate));
    }

    /**
     * 处理cl42返回
     *
     * @param innerResCL42InnerRes
     * @param ypnmodVo
     */
    void dealCl42Res(InnerRes<InnerResCL42> innerResCL42InnerRes, YpnmodVo ypnmodVo) {

        innerResCL42InnerRes.DATA.lstCL422.forEach(itemCL422 -> {
            YpInfoVo ypInfoVo = new YpInfoVo();
            ypInfoVo.setGuarno(itemCL422.dzywbh);
            ypnmodVo.getYpInfoVos().add(ypInfoVo);
        });
    }

    /**
     * 押品检核验
     *
     * @param ypnmodVo
     */
    void yapinCheck(YpnmodVo ypnmodVo) {
        YpInfoVo ypInfoVo = ypnmodVo.getYpInfoVo();
        BigDecimal day = BigDecimal.ZERO;
        Date date = null;
        if (ypnoPn()) {
            if (!MdaUtils.isEmpty(ypInfoVo.getCDQSR())) {
                if (TRANS.contains(atpBchCacheService.getSdTransNameForRegister())) {
                    day = Strings.parseDecimal(codetableService.getTblLabel("OPN", "QXRCOD"));
                    if (MdaUtils.compareTo(day, 0) <= 0) {
                        day = new BigDecimal("10");
                    }
                    try {
                        date = DateUtil.parseDate(ypInfoVo.getCDQSR());
                    } catch (Exception e) {
                        logger.error("{}", e);
                    }
                    if (MdaUtils.compareTo(Dates.diff(Dates.today(), date), day) < 0) {
                        ypnmodVo.getErrorVo().getRulemap().put("ypnmod.ypInfoVo.cdqsr", "请确认是否符合我行业务管理规定");
                    }
                }
            }
        }
    }

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

    String calmac(LimSimpleVo limSimpleVo) {
        String data = JSON.toJSONString(limSimpleVo.getLimQueryVo().getLimgrdVoList());
        logger.info("######### 押品的 macdata is {}", data);
        String mac = DigestUtils.sha1Hex(DigestUtils.md5(data));
        return mac;
    }
}
