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

import cn.hutool.core.date.DateUtil;
import com.brilliance.mda.runtime.mda.util.MdaUtils;
import com.brilliance.isc.bo.Bch;
import com.brilliance.isc.bo.bop.jsh.Dbjgrp;
import com.brilliance.isc.bo.bop.jsh.Dbwgrp;
import com.brilliance.isc.common.api.bch.service.BchService;
import com.brilliance.isc.common.bop.service.JshmapService;
import com.brilliance.isc.common.bopset.service.CtlmodService;
import com.brilliance.isc.common.bopset.service.JshmodService;
import com.brilliance.isc.common.context.BopContext;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.jshmod.common.JshObjType;
import com.brilliance.isc.common.jshmod.vo.Jshmod;
import com.brilliance.isc.common.setglg.vo.SetglgVo;
import com.brilliance.isc.common.setgll.vo.SetgllVo;
import com.brilliance.isc.common.transaction.help.TransactionHelpService;
import com.brilliance.isc.common.util.BopUtils;
import com.brilliance.isc.common.util.JshmodUtils;
import com.brilliance.isc.common.util.Utils;
import com.brilliance.isc.common.vo.BizInfoVo;
import com.brilliance.isc.mda.dao.TrmMapper;
import com.brilliance.isc.vo.derivative.JsdBizInfoVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class JshmodServiceImpl implements JshmodService {

    @Autowired
    private JshmapService jshmapService;

    @Autowired
    private CtlmodService ctlmodService;

    @Autowired
    private BchService bchService;

    @Autowired
    private TransactionHelpService transactionHelpService;

    @Autowired
    private TrmMapper trmMapper;

    @Override
    public void mappingJSHDataAAAAAA(Jshmod jshmod) {
        Dbjgrp dbjgrp = jshmod.getDbjgrp();
        Dbwgrp dbwgrp = jshmod.getDbwgrp();

        BizInfoVo bizInfo = BopContext.getBizInfo();
        String tranName = SettleContext.getTransName();
        String tranRol = JshmodUtils.getTransRol();
        dbjgrp.getBas().setActiontype("A");
        dbwgrp.getBas().setActiontype("A");

        //给地区机构号赋值
        Bch wrkbch = Optional.ofNullable(SettleContext.getUserSession().getWrkbch()).orElseGet(Bch::new);
        dbjgrp.getBas().setOwnextkey(wrkbch.getBranch());
        dbwgrp.getBas().setOwnextkey(wrkbch.getBranch());
        //给银行业务编号赋值
        if ("MCTFEE".equals(tranName)) {
            dbjgrp.getBas().setBuscode(bizInfo.getSubref());
            dbwgrp.getBas().setBuscode(bizInfo.getSubref());
        } else {
            dbjgrp.getBas().setBuscode(bizInfo.getOwnref());
            dbwgrp.getBas().setBuscode(bizInfo.getOwnref());
        }
        //获得客户类型custype
        String idtype = JshmodUtils.getPty2(tranRol).getIdtype();
        //idtype等于1或2时 赋值为空
        if (!dbjgrp.getBas().isModified("custype") && !dbwgrp.getBas().isModified("custype")) {
            if ("1".equals(idtype) || "2".equals(idtype)) {
                dbjgrp.getBas().setCustype("C");
                dbwgrp.getBas().setCustype("C");
            } else {
                dbjgrp.getBas().setCustype(idtype);
                dbwgrp.getBas().setCustype(idtype);
            }
        }


        //获得组织机构代码
        JshObjType jshObjType = jshmod.getCtlmod().getJshObjectMap().get(JshmodUtils.getJshSetTyp(jshmod));
        String subtyp = jshObjType.getSubtyp();
        String currentCusType = "DBJ".equals(subtyp) ? dbjgrp.getBas().getCustype() : dbwgrp.getBas().getCustype();
        if ("C".equals(currentCusType)) {
            String juscod = JshmodUtils.getPty2("APL").getJuscod();
            dbjgrp.getBas().setCustcod(juscod);
            dbwgrp.getBas().setCustcod(juscod);
            dbjgrp.getBas().setIdcode("");
            dbwgrp.getBas().setIdcode("");
        } else {    //给身份证号赋值
            String idcode = JshmodUtils.getPty2(tranRol).getIdcode();
            dbjgrp.getBas().setIdcode(idcode);
            dbwgrp.getBas().setIdcode(idcode);
            dbjgrp.getBas().setCustcod("");
            dbwgrp.getBas().setCustcod("");
        }
        //给结汇/购汇申请人名称赋值
        String nam1 = JshmodUtils.getPty2(tranRol).getNam1();
        dbjgrp.getBas().setCustnm(JshmodUtils.getPty2(tranRol).getNam1());
        dbwgrp.getBas().setCustnm(JshmodUtils.getPty2(tranRol).getNam1());

        dbjgrp.getVrf().setActiontype("A");
        dbwgrp.getVrf().setActiontype("A");

        //国际收支申报交易编码
        String txcode = (String) Utils.getField(bizInfo, "txcode").orElseGet(String::new);
        if (StringUtils.isNotEmpty(txcode)) {
            dbjgrp.getVrf().setTxcode(txcode);
            dbwgrp.getVrf().setTxcode(txcode);
        }
        //外汇局批件号/备案表号/业务编号
        String regno = (String) Utils.getField(bizInfo, "regno").orElseGet(String::new);
        if (StringUtils.isNotEmpty(regno)) {
            dbjgrp.getVrf().setRegno(regno);
            dbwgrp.getVrf().setRegno(regno);
        }
        dbjgrp.getVrf().setRptdate(DateUtil.date());
        dbwgrp.getVrf().setRptdate(DateUtil.date());
        //给填报人赋值
        dbjgrp.getVrf().setCrtuser(JshmodUtils.getPtc().getNam());
        dbwgrp.getVrf().setCrtuser(JshmodUtils.getPtc().getNam());
        //给填报人电话赋值
        dbwgrp.getVrf().setInptelc(JshmodUtils.getPtc().getTelmob());
        dbjgrp.getVrf().setInptelc(JshmodUtils.getPtc().getTelmob());
        //给人民币/外币收款人名称赋值
        if ("1".equals(jshmod.getSzflg())) {
            String cnyact = dbjgrp.getBas().getLcyacc();
            oppval(jshmod, jshmod.getSzflg(), cnyact, nam1);
        } else {
            String account = dbwgrp.getBas().getFcyacc();
            oppval(jshmod, jshmod.getSzflg(), account, nam1);
        }
    }

    /**
     * 给人民币/外币收款人名称
     * 给人民币/外币账户开户行赋值
     */
    private void oppval(Jshmod jshmod, String szsbflg, String account, String nam) {
        String oppbank = "";
        //--ZMQZMQ---
        String ownextkey = "";
        if (StringUtils.isNotEmpty(account)) {
            if ("ZMQ".equals(StringUtils.substring(account, 0, 3))) {
                ownextkey = StringUtils.substring(account, 3, 7);
            } else {
                if ("FT".equals(StringUtils.substring(account, 0, 2)) || "EF".equals(StringUtils.substring(account, 0, 2))) {
                    ownextkey = StringUtils.substring(account, 7, 11);
                } else {
                    if (account.length() == 17) {
                        ownextkey = StringUtils.substring(account, 0, 4);
                    } else if (account.length() == 21) {
                        ownextkey = StringUtils.substring(account, 2, 6);
                    }
                }
            }
        }
        if (StringUtils.isNotEmpty(ownextkey)) {
            Bch bch = bchService.getByBranch(ownextkey);
            oppbank = Optional.ofNullable(bch).orElseGet(Bch::new).getBchname();
        }

        if (StringUtils.isNotEmpty(oppbank)) {
            if ("1".equals(szsbflg)) {
                jshmod.getDbjgrp().getBas().setOppbank(oppbank);
                jshmod.getDbjgrp().getBas().setOppuser(nam);
            } else {
                jshmod.getDbwgrp().getBas().setOppbank(oppbank);
                jshmod.getDbwgrp().getBas().setOppuser(nam);
            }
        } else {
            jshmod.getDbjgrp().getBas().setOppbank("");
            jshmod.getDbjgrp().getBas().setOppuser("");
            jshmod.getDbwgrp().getBas().setOppbank("");
            jshmod.getDbwgrp().getBas().setOppuser("");
        }
    }

    /**
     * 数据提取交易存盘时自动产生临时参考号
     * ===================================
     * 返回值：无
     * 变量:   path 存储路径
     * ===================================
     * //数据提取交易和补录交易中才产生申报号码
     *
     * @param jshmod 结售汇模型
     */
    private void savBopnoJSH(Jshmod jshmod) {
        String dectyp = jshmod.getCtlmod().getDectyp();
        if (!"3".equals(jshmod.getSzflg()) && ("V".equals(dectyp) || "A".equals(dectyp))) {
            JshmodUtils.getReference(jshmod);
        }

    }

    @Override
    public boolean ruleMtabutSavN221(Jshmod jshmod) {

        jshmapService.savIfNotChanged(jshmod);
        return true;
    }

    @Override
    public void saveJshmod(Jshmod jshmod) {
        String jshSetTyp = JshmodUtils.getJshSetTyp(jshmod);
        if (StringUtils.isNotEmpty(jshSetTyp)) {
            JshObjType jshObjType = jshmod.getCtlmod().getJshObjectMap().get(jshSetTyp);
            String subtyp = jshObjType.getSubtyp();

            Object recgrp = "DBJ".equals(subtyp) ? jshmod.getDbjgrp() : jshmod.getDbwgrp();
            JshmodUtils.setDectyp(jshmod);

            savBuscodeJSH(recgrp);
            savBopnoJSH(jshmod);
            ctlmodService.setDblStatus(jshmod, jshSetTyp); //设置交易存盘状态

            ctlmodService.jshStoreContract(jshmod);
            ctlmodService.setDblData(subtyp, jshmod.getCtlmod(), recgrp); //设置交易存盘状态
            ctlmodService.jshStoreDBL(jshmod.getCtlmod(), "当前交易的状态");
        }

    }


    /**
     * 存盘时存储业务编号
     * ===================================
     * 返回值：无
     * 变量:   path 存储路径
     * ===================================
     *
     * @param dbjwgrp 结汇或者售汇麻烦
     */
    private void savBuscodeJSH(Object dbjwgrp) {
        String ownref = transactionHelpService.getTransactionStoreSet().getTrnmodVo().getTrn().getOwnref();
        String buscode = "";
        if (dbjwgrp instanceof Dbjgrp) {
            buscode = ((Dbjgrp) dbjwgrp).getBas().getBuscode();
        } else if (dbjwgrp instanceof Dbwgrp) {
            buscode = ((Dbwgrp) dbjwgrp).getBas().getBuscode();
        }
        if (!MdaUtils.isEmpty(ownref) && MdaUtils.isEmpty(buscode)) {
            if (dbjwgrp instanceof Dbjgrp) {
                ((Dbjgrp) dbjwgrp).getBas().setBuscode(ownref);
            } else if (dbjwgrp instanceof Dbwgrp) {
                ((Dbwgrp) dbjwgrp).getBas().setBuscode(ownref);
            }
        }

    }


    /**
     * 用于初始化wg页面的default方法
     * 目前此方法用于对报送重要数据赋值
     *
     * @param jshmod Jshmod
     */
    private void wg(Jshmod jshmod) {
        String transName = SettleContext.getTransName();
        if (transName.substring(0, 3).equals("JST")) {
            JsdBizInfoVo bizInfo = (JsdBizInfoVo) BopContext.getBizInfo();
            if ("1".equals(bizInfo.getShfobz())) {
                if (transName.equals("JSTOPN")) {
                    if ("4".equals(bizInfo.getMaimpz())) {
                        //给外汇账户账号赋值
                        jshmod.getDbjgrp().getBas().setFcyacc(bizInfo.getZha1zh());
                        jshmod.getDbwgrp().getBas().setFcyacc(bizInfo.getZha1zh());
                        //给结汇、购汇币种赋值
                        jshmod.getDbjgrp().getBas().setFcyccy(BopContext.getCbsMap().get("MAX1").getCur());
                        jshmod.getDbwgrp().getBas().setLcyccy(BopContext.getCbsMap().get("MAX1").getCur());
                        //给结汇、购汇金额赋值
                        jshmod.getDbjgrp().getBas().setFcyamt(BopContext.getCbsMap().get("MAX1").getAmt());
                        jshmod.getDbwgrp().getBas().setLcyamt(BopContext.getCbsMap().get("MAX2").getAmt());
                        //给汇率赋值
                        jshmod.getDbjgrp().getBas().setExrate(BigDecimal.ZERO);
                        jshmod.getDbwgrp().getBas().setExrate(BigDecimal.ZERO);
                        //给人民币账户账号赋值
                        jshmod.getDbjgrp().getBas().setLcyacc(bizInfo.getZhangh());
                        jshmod.getDbwgrp().getBas().setLcyacc(bizInfo.getZhangh());
                    } else if ("5".equals(bizInfo.getMaimpz())) {
                        //给外汇账户账号赋值
                        jshmod.getDbjgrp().getBas().setFcyacc(bizInfo.getZhangh());
                        jshmod.getDbwgrp().getBas().setFcyacc(bizInfo.getZhangh());
                        //给结汇、购汇币种赋值
                        jshmod.getDbjgrp().getBas().setFcyccy(BopContext.getCbsMap().get("MAX2").getCur());
                        jshmod.getDbwgrp().getBas().setLcyccy(BopContext.getCbsMap().get("MAX2").getCur());
                        //给结汇、购汇金额赋值
                        jshmod.getDbjgrp().getBas().setFcyamt(BopContext.getCbsMap().get("MAX2").getAmt());
                        jshmod.getDbwgrp().getBas().setLcyamt(BopContext.getCbsMap().get("MAX1").getAmt());
                        //给汇率赋值
                        jshmod.getDbjgrp().getBas().setExrate(BigDecimal.ZERO);
                        jshmod.getDbwgrp().getBas().setExrate(BigDecimal.ZERO);
                        //给人民币账户账号赋值
                        jshmod.getDbjgrp().getBas().setLcyacc(bizInfo.getZha1zh());
                        jshmod.getDbwgrp().getBas().setLcyacc(bizInfo.getZha1zh());
                    }
                } else if (transName.equals("JSTSET")) {
                    if ("4".equals(bizInfo.getMaimpz()) || "6".equals(bizInfo.getMaimpz())) {
                        //给外汇账户账号赋值
                        jshmod.getDbjgrp().getBas().setFcyacc(bizInfo.getZha1zh());
                        jshmod.getDbwgrp().getBas().setFcyacc(bizInfo.getZha1zh());
                        //给结汇、购汇币种赋值
                        jshmod.getDbjgrp().getBas().setFcyccy(bizInfo.getHuobdh());
                        jshmod.getDbwgrp().getBas().setLcyccy(bizInfo.getHuobdh());
                        //给结汇、购汇金额赋值
                        jshmod.getDbjgrp().getBas().setFcyamt(bizInfo.getMairje());
                        jshmod.getDbwgrp().getBas().setLcyamt(bizInfo.getMaicje());
                        //给汇率赋值
                        jshmod.getDbjgrp().getBas().setExrate(bizInfo.getJqmrhl());
                        jshmod.getDbwgrp().getBas().setExrate(bizInfo.getJqmrhl());
                        //给人民币账户账号赋值
                        jshmod.getDbjgrp().getBas().setLcyacc(bizInfo.getZhangh());
                        jshmod.getDbwgrp().getBas().setLcyacc(bizInfo.getZhangh());
                    } else {
                        //给外汇账户账号赋值
                        jshmod.getDbjgrp().getBas().setFcyacc(bizInfo.getZhangh());
                        jshmod.getDbwgrp().getBas().setFcyacc(bizInfo.getZhangh());
                        //给结汇、购汇币种赋值
                        jshmod.getDbjgrp().getBas().setFcyccy(bizInfo.getDfhbdh());
                        jshmod.getDbwgrp().getBas().setLcyccy(bizInfo.getDfhbdh());
                        //给结汇、购汇金额赋值
                        jshmod.getDbjgrp().getBas().setFcyamt(bizInfo.getMaicje());
                        jshmod.getDbwgrp().getBas().setLcyamt(bizInfo.getMairje());
                        //给汇率赋值
                        jshmod.getDbjgrp().getBas().setExrate(bizInfo.getJqmrhl());
                        jshmod.getDbwgrp().getBas().setExrate(bizInfo.getJqmrhl());
                        //给人民币账户账号赋值
                        jshmod.getDbjgrp().getBas().setLcyacc(bizInfo.getZha1zh());
                        jshmod.getDbwgrp().getBas().setLcyacc(bizInfo.getZha1zh());
                    }
                }

            }
        }
        SetglgVo setglg = BopContext.getSetglg();
        //统计是否是多借多贷
        int count = (int) setglg.getSetgll().stream()
                .filter(setgll -> !StringUtils.equals(setgll.getAcccur(), setgll.getCur()))
                .count();

        for (SetgllVo setgll : setglg.getSetgll()) {
            String act = setgll.getAct();
            String acccur = setgll.getAcccur();
            String cur = setgll.getCur();
            String trnman = setgll.getTrnman();
            String acttrmtyp = setgll.getActtrmtyp();
            BigDecimal rat = setgll.getRat();
            //当原始币种与记账币种不同，交易主体不能为空，且交易主体不能为银行自身 时出现结售汇
            if (!StringUtils.equals(acccur, cur) && StringUtils.isNotEmpty(trnman) && !"01".equals(trnman)) {
                //不论是否有手续费，获取结售汇的金额
                Pair<BigDecimal, BigDecimal> amtPair = JshmodUtils.isFeeAndGetAMT(setgll);
                BigDecimal ghcnyamt = amtPair.getLeft();
                BigDecimal jhamt = amtPair.getRight();
                List<String> cusacttrm = jshmod.getCusacttrm();
                //无多借多贷，结售汇金额大于等于0.5
                if (count <= 1 && jhamt.compareTo(BigDecimal.valueOf(0.5)) > 0) {
                    //当原始币种是外币
                    if (StringUtils.isNotEmpty(acccur) && !"CNY".equals(acccur)) {
                        if (cusacttrm.contains(acttrmtyp)) {
                            //找人民币账户
                            Optional<SetgllVo> optionalSetgll = setglg.getSetgll().stream()
                                    .filter(i -> "CNY".equals(i.getAcccur()) && ghcnyamt.equals(i.getFmtaccamt()))
                                    .findAny();
                            if (optionalSetgll.isPresent()) {
                                //给外汇账户账号赋值
                                jshmod.getDbjgrp().getBas().setFcyacc(act);
                                jshmod.getDbwgrp().getBas().setFcyacc(act);
                                //给结汇、购汇币种赋值
                                jshmod.getDbjgrp().getBas().setFcyccy(acccur);
                                jshmod.getDbwgrp().getBas().setLcyccy(acccur);
                                //给结汇、购汇金额赋值
                                jshmod.getDbjgrp().getBas().setFcyamt(jhamt);
                                jshmod.getDbwgrp().getBas().setLcyamt(ghcnyamt);
                                //给汇率赋值
                                jshmod.getDbjgrp().getBas().setExrate(rat);
                                jshmod.getDbwgrp().getBas().setExrate(rat);
                                //给人民币账户账号赋值
                                jshmod.getDbjgrp().getBas().setLcyacc(optionalSetgll.get().getAct());
                                jshmod.getDbwgrp().getBas().setLcyacc(optionalSetgll.get().getAct());
                                break;
                            }
                        }
                        //当原始币种是人民币
                    } else {
                        //找外币账户
                        Optional<SetgllVo> optionalSetgll = setglg.getSetgll().stream()
                                .filter(i -> cusacttrm.contains(i.getActtrmtyp()))
                                .filter(i -> StringUtils.isNotEmpty(i.getAcccur()) && !"CNY".equals(i.getAcccur()))
                                .findAny();
                        if (optionalSetgll.isPresent()) {
                            //给外汇账户账号赋值
                            jshmod.getDbjgrp().getBas().setFcyacc(optionalSetgll.get().getAct());
                            jshmod.getDbwgrp().getBas().setFcyacc(optionalSetgll.get().getAct());
                            //给结汇、购汇币种赋值
                            jshmod.getDbjgrp().getBas().setFcyccy(optionalSetgll.get().getAcccur());
                            jshmod.getDbwgrp().getBas().setLcyccy(optionalSetgll.get().getAcccur());
                            //给结汇、购汇金额赋值
                            jshmod.getDbjgrp().getBas().setFcyamt(jhamt);
                            jshmod.getDbwgrp().getBas().setLcyamt(ghcnyamt);
                            //给汇率赋值
                            jshmod.getDbjgrp().getBas().setExrate(rat);
                            jshmod.getDbwgrp().getBas().setExrate(rat);
                            //给人民币账户账号赋值
                            jshmod.getDbjgrp().getBas().setLcyacc(act);
                            jshmod.getDbwgrp().getBas().setLcyacc(act);
                            break;
                        }
                    }
                }
            }

        }


    }


    // JSHSET init order 2031
    private void init(Jshmod jshmod) {
        // CTLSET init order 1091
        JshObjType jsh1 = new JshObjType("JSH1", "DBJ", "E", "N", "N");
        JshObjType jsh2 = new JshObjType("JSH2", "DBJ", "E", "N", "E");
        JshObjType jsh3 = new JshObjType("JSH3", "DBW", "E", "N", "N");
        JshObjType jsh4 = new JshObjType("JSH4", "DBW", "E", "N", "E");
        Map<String, JshObjType> jshObjectMap = jshmod.getCtlmod().getJshObjectMap();
        jshObjectMap.put("JSH1", jsh1);
        jshObjectMap.put("JSH2", jsh2);
        jshObjectMap.put("JSH3", jsh3);
        jshObjectMap.put("JSH4", jsh4);

        //客户帐科目
        jshmod.setCusacttrm(trmMapper.getJshTrmTyp());
    }

    @Override
    public void calcJshmod(Jshmod jshmod) {
        jshmod.reset();
        init(jshmod);
        if ("1".equals(jshmod.getSzflg()) || "2".equals(jshmod.getSzflg())) {
            Map<String, Object> modifiedFields = BopUtils.backupModifiedFields(jshmod);
            wg(jshmod);
            mappingJSHDataAAAAAA(jshmod);
            BopUtils.restoreModifiedFields(jshmod, modifiedFields);
        } else {
            jshmod.clear();
        }
    }
}
