package com.brilliance.isc.common.forexmod;

import com.brilliance.isc.bo.Pty;
import com.brilliance.isc.bo.Ptymrm;
import com.brilliance.isc.bo.Ptyrsk;
import com.brilliance.isc.common.cbsmod.service.impl.XrtmodServiceImpl;
import com.brilliance.isc.common.codetable.service.CodetableService;
import com.brilliance.isc.common.esb.ccrm.IRiskCustomerFeign;
import com.brilliance.isc.esb.model.ccrm.*;
import com.brilliance.isc.esb.model.inner.Header;
import com.brilliance.isc.esb.model.inner.InnerReq;
import com.brilliance.isc.esb.model.inner.InnerRes;
import com.brilliance.isc.mda.dao.PtyMapper;
import com.brilliance.isc.mda.dao.PtymrmMapper;
import com.brilliance.isc.mda.dao.PtyrskMapper;
import com.brilliance.isc.utils.ObjectUtils;
import com.brilliance.mda.runtime.mda.impl.Argument;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 
 * @date 2024-08-09
 * @description
 */
@Component
public class RiskCustomerDisposeComponent {

    private static final Logger LOGGER = LoggerFactory.getLogger(RiskCustomerDisposeComponent.class);
    private static final String CR = "<br>";
    private static final String RISK_USELESS_ERR_MSG= "客户外汇合规风险等级分类结果不可用，请在CRM系统进行分类认定";
    private static final String RISK_3_WARN_MSG_1 = "该客户外汇合规风险等级为三类，请根据风险状况，强化审查措施。";
    private static final String RISK_3_WARN_MSG_2 = "此客户为三类客户，请线下办理！";
    private static final String HISTORY_NOT_CONTAIN_1 = "此类业务为首笔，请加强审核！";
    private static final String HISTORY_NOT_CONTAIN_2 = "该业务为首笔业务，请认真审核该业务类型的前三笔资料，确保业务合规办理";
    private static final String BUSINESS_NOT_CONTAIN = "该业务为新需求，请认真审核资料，确保业务合规办理";
    private static final String BUSINESS_SORT_RESULT = "业务分类结果：%s";

    private static final String AMT_ABOVE = "该笔交易金额%s(美元)，已超过%s%s%s单笔平均金额%s(美元)，请认真审核资料，确保业务合规办理";
    private static final String ANNUAL = "上年度";
    private static final String QUARTER = "季度";
    private static final String PROCEED = "收汇";
    private static final String REMITTANCE = "付汇";
    private static final String GOODS = "货物贸易";
    private static final String SERVER = "服务贸易";
    private static final String RETURN_REMITTANCE = "退汇业务";

    private static final Map<String, String> BUSINESS_MAP = new HashMap<>();

    static {
        BUSINESS_MAP.put("01","货物贸易");
        BUSINESS_MAP.put("02","服务贸易");
        BUSINESS_MAP.put("03","初次收入（收益）");
        BUSINESS_MAP.put("04","二次收入（经常转移）");
        BUSINESS_MAP.put("05","资本账户");
        BUSINESS_MAP.put("06","境外直接投资");
        BUSINESS_MAP.put("07","境内直接投资");
        BUSINESS_MAP.put("08","外债");
        BUSINESS_MAP.put("09","境外放款");
        BUSINESS_MAP.put("10","证券投资及金融衍生工具");
        BUSINESS_MAP.put("11","其他投资");
        BUSINESS_MAP.put("12","境内外汇收支交易及其他特殊交易");
        BUSINESS_MAP.put("13","跨境担保");
        BUSINESS_MAP.put("14","国际贸易融资");
        BUSINESS_MAP.put("15","境外贷款");
    }

    @Resource
    private CodetableService codetableService;

    @Resource
    private PtyMapper ptyMapper;

    @Autowired(required = false)
    private IRiskCustomerFeign iRiskCustomerFeign;

    @Resource
    private PtyrskMapper ptyrskMapper;

    @Resource
    private PtymrmMapper ptymrmMapper;

    @Resource
    private XrtmodServiceImpl xrtmodServiceImpl;

    public String errorMessage(String ptyinr, ForexmodVo forexmod){
        if (isCheckInfoRisk()) {
            Pty pty = ptyMapper.selectByPtyinr(ptyinr);
            if (!StringUtils.equals("1",pty.getIdtype())||forexmod==null){
                return null;
            }
            if (!StringUtils.equals("1",forexmod.getState())||!StringUtils.equals("01",forexmod.getType())){
                return RISK_USELESS_ERR_MSG;
            }
        }
        return null;
    }


    public String warningMessage4Automation(String ptyinr, String txcode, String cur, BigDecimal amt, boolean interdiction, boolean proceed, boolean remittance,ForexmodVo forexmod){
        if (isCheckInfoRisk()) {
            Pty pty = ptyMapper.selectByPtyinr(ptyinr);
            if (!StringUtils.equals("1",pty.getIdtype())||forexmod == null){ // 1-对公客户
                return null;
            }
            StringBuilder sb = new StringBuilder();
            if (StringUtils.equals("03",forexmod.getRiskLevel())&&interdiction){ //三类客户展示
                sb.append(RISK_3_WARN_MSG_2);
            }
            if (!interdiction) {
                Ptyrsk ptyrsk = ptyrskMapper.queryByPtyinr(ptyinr);
                String tblKey = getBusinessFromCode(txcode);
                if (ptyrsk == null || StringUtils.isEmpty(ptyrsk.getBusrequirelabel()) || !ptyrsk.getBusrequirelabel().contains(tblKey)) {
                    sb.append(BUSINESS_NOT_CONTAIN).append(CR);
                }
                Ptymrm ptymrm = ptymrmMapper.queryByPtyinr(ptyinr);
                if (ptymrm == null||StringUtils.isEmpty(ptymrm.getIdx041())||!ptymrm.getIdx041().contains(txcode.substring(0,3))){
                    sb.append(HISTORY_NOT_CONTAIN_2).append(CR);
                } else {
                    sb.append(String.format(BUSINESS_SORT_RESULT,BUSINESS_MAP.get(tblKey)));
                }
                String riskTag = checkRiskTag(cur, amt, ptymrm, tblKey, true, proceed, remittance);
                if (StringUtils.isNotEmpty(riskTag)){
                    sb.append(riskTag);
                }
            }
            return sb.toString();
        }
        return null;
    }

    /**
     *
     * @param ptyinr
     * @param txcode
     * @param cur 币种
     * @param amt 金额
     * @param hasCross_border 外管信息
     * @param isCpt 汇款
     * @param isJsh 结售汇
     * @param proceed 收汇
     * @param remittance 付汇
     * @param forexmod
     * @return
     */
    public String warningMessage(String ptyinr, String txcode, String cur, BigDecimal amt, boolean hasCross_border, boolean isCpt, boolean isJsh, boolean proceed, boolean remittance,ForexmodVo forexmod){
        if (isCheckInfoRisk()) {
            Pty pty = ptyMapper.selectByPtyinr(ptyinr);
            if (!StringUtils.equals("1",pty.getIdtype())||forexmod==null){ // 1-对公客户
                return null;
            }
            StringBuilder sb = new StringBuilder();
            if (StringUtils.equals("03",forexmod.getRiskLevel())){ //三类客户展示
                sb.append(RISK_3_WARN_MSG_1).append(CR);
            }


            if (hasCross_border) {//跨境收支
                Ptymrm ptymrm = ptymrmMapper.queryByPtyinr(ptyinr);
                String tblKey = getBusinessFromCode(txcode);
                Ptyrsk ptyrsk = ptyrskMapper.queryByPtyinr(ptyinr);

                if (ptyrsk == null ||  StringUtils.isEmpty(ptyrsk.getBusrequirelabel()) || !ptyrsk.getBusrequirelabel().contains(tblKey)) {
                    sb.append(BUSINESS_NOT_CONTAIN).append(CR);
                }
                if (ptymrm == null||StringUtils.isEmpty(ptymrm.getIdx041())||!ptymrm.getIdx041().contains(txcode.substring(0,3))){
//                    if (isCpt||isJsh) {
//                        sb.append(HISTORY_NOT_CONTAIN_1).append(CR);
//                    } else {
                    sb.append(HISTORY_NOT_CONTAIN_2).append(CR);
//                    }
                } else {
                    if (isCpt||isJsh) {
                        sb.append(String.format(BUSINESS_SORT_RESULT,BUSINESS_MAP.get(tblKey))).append(CR);
                    }
                }
                String riskTag = checkRiskTag(cur, amt, ptymrm, tblKey, isCpt, proceed, remittance);
                if (StringUtils.isNotEmpty(riskTag)){
                    sb.append(riskTag);
                }
            }

            return sb.toString();
        }
        return null;
    }

    public String warningMessage(String ptyinr, String txcode, String cur, BigDecimal amt, boolean hasCross_border, boolean proceed, boolean remittance, ForexmodVo forexmod){
        return warningMessage(ptyinr, txcode, cur, amt, hasCross_border, false, false, proceed, remittance, forexmod);
    }
    public String warningMessage(String ptyinr,  String cur, BigDecimal amt, boolean proceed, boolean remittance, ForexmodVo forexmod){
        return warningMessage(ptyinr, null, cur, amt, false, proceed, remittance,forexmod);
    }

    public String warningMessage(String ptyinr, ForexmodVo forexmod){
        return warningMessage(ptyinr,  null, null, false, false, forexmod);
    }

    /**
     *
     * @param cur
     * @param amt
     * @param ptymrm
     * @param business 业务类型
     * @param cpt 是否是汇款
     * @param proceed 是否是收汇
     * @param remittance 是否是付汇
     * @return
     */
    private String checkRiskTag(String cur, BigDecimal amt, Ptymrm ptymrm, String business, boolean cpt, boolean proceed, boolean remittance){
        if (ptymrm == null || StringUtils.isEmpty(cur)||amt==null){
            return null;
        }
        BigDecimal amtusd;
        if (StringUtils.equals(cur, "USD")) {
            amtusd = amt;
        } else {
            Argument<BigDecimal> rate = new Argument<>();
            Argument<BigDecimal> sqrRat = new Argument<>();
            xrtmodServiceImpl.getratForENT(cur, "S", "USD", "B", new Date(), rate, sqrRat);
            amtusd = amt.multiply(rate.value).setScale(2, BigDecimal.ROUND_CEILING);
        }
        StringBuilder sb = new StringBuilder();
        if ("01".equals(business)){
            if (proceed){
                BigDecimal annualAmt = new BigDecimal(getAmt(ptymrm.getIdx002_desc(), 2));//上年度
                if (annualAmt.compareTo(BigDecimal.ZERO)==0||amtusd.subtract(annualAmt).divide(annualAmt,2,BigDecimal.ROUND_CEILING).compareTo(ptymrm.getIdx002_threshold())==1){
                    sb.append(String.format(AMT_ABOVE,amtusd.toString(),ANNUAL,GOODS,PROCEED,annualAmt.toString())).append(CR);
                }
            }else if (remittance) {
                BigDecimal annualAmt = new BigDecimal(getAmt(ptymrm.getIdx003_desc(), 2));//上年度
                if (annualAmt.compareTo(BigDecimal.ZERO)==0||amtusd.subtract(annualAmt).divide(annualAmt,2,BigDecimal.ROUND_CEILING).compareTo(ptymrm.getIdx003_threshold())==1) {
                    sb.append(String.format(AMT_ABOVE, amtusd.toString(), ANNUAL, GOODS, REMITTANCE, annualAmt.toString())).append(CR);
                }
            }
        } else if ("02".equals(business)){
            if (proceed){
                BigDecimal annualAmt = new BigDecimal(getAmt(ptymrm.getIdx006_desc(), 2));//上年度
                if (annualAmt.compareTo(BigDecimal.ZERO)==0||amtusd.subtract(annualAmt).divide(annualAmt,2,BigDecimal.ROUND_CEILING).compareTo(ptymrm.getIdx006_threshold())==1) {
                    sb.append(String.format(AMT_ABOVE,amtusd.toString(),ANNUAL,SERVER,PROCEED,annualAmt.toString())).append(CR);
                }
            }else if (remittance) {
                BigDecimal annualAmt = new BigDecimal(getAmt(ptymrm.getIdx007_desc(), 2));//上年度
                if (annualAmt.compareTo(BigDecimal.ZERO)==0||amtusd.subtract(annualAmt).divide(annualAmt,2,BigDecimal.ROUND_CEILING).compareTo(ptymrm.getIdx007_threshold())==1) {
                    sb.append(String.format(AMT_ABOVE,amtusd.toString(),ANNUAL,SERVER,REMITTANCE,annualAmt.toString())).append(CR);
                }
            }
        }

        if (cpt&&("01".equals(business)||"02".equals(business))){
            BigDecimal annualAmt = new BigDecimal(getAmt(ptymrm.getIdx038_desc(), 2));//上年度
            if (annualAmt.compareTo(BigDecimal.ZERO)==0||amtusd.subtract(annualAmt).divide(annualAmt,2,BigDecimal.ROUND_CEILING).compareTo(ptymrm.getIdx038_threshold())==1) {
                sb.append(String.format(AMT_ABOVE,amtusd.toString(),ANNUAL,RETURN_REMITTANCE,"",annualAmt.toString())).append(CR);
            }
        }
//        String msg = null;
//        try {
//            msg = getMsg(ptymrm);
//        } catch (Exception e) {
//            LOGGER.error("反射获取失败：{}",e);
//        }
//        if (StringUtils.isNotEmpty(msg)) {
//            sb.append(msg);
//        }
        return sb.toString();
    }

    private String getMsg(Ptymrm ptymrm) throws NoSuchFieldException, IllegalAccessException {
        if (ptymrm == null) {
            return null;
        }
        Class clazz = ptymrm.getClass();
        NumberFormat instance = NumberFormat.getInstance();
        instance.setMaximumIntegerDigits(3);
        instance.setMinimumIntegerDigits(3);
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < 41; i++ ){
            Field idxField = clazz.getDeclaredField("idx".concat(instance.format(i)));
            Field idxThresholdField = clazz.getDeclaredField("idx".concat(instance.format(i)).concat("_threshold"));
            idxField.setAccessible(true);
            idxThresholdField.setAccessible(true);
            BigDecimal idx = (BigDecimal)idxField.get(ptymrm);
            BigDecimal idxThreshold = (BigDecimal)idxThresholdField.get(ptymrm);
            if (idx==null||idxThreshold==null){
                continue;
            }
            if (idx.compareTo(idxThreshold)==1) {
                Field idxDescField = clazz.getDeclaredField("idx".concat(instance.format(i)).concat("_desc"));
                idxDescField.setAccessible(true);
                sb.append((String) idxDescField.get(ptymrm)).append(CR);
            }
        }
        return sb.toString();
    }

    /**
     *
     * @param str
     * @param index 第几个 从1开始
     * @return
     */
    private String getAmt(String str, int index){
        if (StringUtils.isEmpty(str)||index <= 0) {
            return null;
        }
        int firstB = str.indexOf("[");
        int firstA = str.indexOf("]");
        return str.substring(str.indexOf("[",firstB+index-1)+1, str.indexOf("]",firstA+index-1));
    }


    public InnerRes<ResOC51> OC51(String extkey) {
        ReqOC51 reqOC51 = new ReqOC51();
        reqOC51.CUST_NO = extkey;
        InnerReq<ReqOC51> req = new InnerReq<>(reqOC51);
        req.header = new Header();
        req.header.feignid = "NewCcrm";
        req.header.jiaoym = "OC51";

        InnerRes innerRes = iRiskCustomerFeign.callInterface(req);
        if ("AAAAAAA".equals(innerRes.header.code)){
            try {
                innerRes.DATA = ObjectUtils.cashObject(innerRes.DATA, ResOC51.class);
            } catch (Exception e) {
                LOGGER.error("类型转换错误:{}",e);
            }
        }
        return innerRes;
    }


    public InnerRes<ResOC52> OC52(String extkey, String reason, String usr){
        ReqOC52 reqOC52 = new ReqOC52();
        InnerReq<ReqOC52> req = new InnerReq<>(reqOC52);
        req.header = new Header();
        req.header.feignid = "NewCcrm";
        req.header.jiaoym = "OC52";

        reqOC52.CHANNEL_NO = "270";
        reqOC52.CHANNEL_NAME = "国际结算系统";
        ItemFOC521 itemFOC521 = new ItemFOC521();
        List<ItemFOC521> itemFOC521s = new ArrayList<>();
        reqOC52.FOC521 = itemFOC521s;
        itemFOC521s.add(itemFOC521);
        itemFOC521.CUST_NO = extkey;
        itemFOC521.RISK_LEVEL = "03";
        itemFOC521.IDENT_REASON = reason;
        itemFOC521.IDENT_USER = usr;
        itemFOC521.IDENT_TIME= new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        InnerRes innerRes = iRiskCustomerFeign.callInterface(req);
        if ("AAAAAAA".equals(innerRes.header.code)){
            try {
                innerRes.DATA = ObjectUtils.cashObject(innerRes.DATA, ResOC52.class);
            } catch (Exception e) {
                LOGGER.error("类型转换错误:{}",e);
            }
        }
        return innerRes;
    }

    /**
     * 是否校验客户风险信息
     *
     * @return
     */
    public boolean isCheckInfoRisk() {
        String tblKey = codetableService.getTblLabel("RISKCK", "RISKCK");
        LOGGER.info("RISKCK开关:{}", tblKey);
        return StringUtils.equals(tblKey, "Y");
    }


    /**
     * 通过交易编码映射业务需求
     * @param code
     * @return
     */
    private String getBusinessFromCode(String code){
        String tblKey = codetableService.getTblLabel(code, "RISCOD");
        return tblKey;
    }

}
