package com.friday.custody.service.trustService.swhy.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.friday.base.common.response.DubboResult;
import com.friday.custody.entity.*;
import com.friday.custody.service.basicService.impl.*;
import com.friday.custody.service.trustService.swhy.common.SWConstants;
import com.friday.custody.service.trustService.swhy.utils.SWHYUtils;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.service.basicService.DataDictionaryTypeCertificateCsdcService;
import com.friday.custody.service.basicService.InvokeRecordService;
import com.friday.custody.service.basicService.PullDataFailureLogService;
import com.friday.custody.service.logicService.DataDictionaryBasicService;
import com.friday.custody.service.trustService.OutsourceService;
import com.friday.custody.utils.BigDecimalUtil;
import com.friday.custody.utils.MatchDataDictionaryKeyUtil;
import com.friday.custody.utils.R;
import com.friday.custody.utils.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class OutSourceSWServiceImpl implements OutsourceService {
    @Autowired
    private InvokeRecordService invokeRecordService;
    @Autowired
    private PullDataFailureLogService pullDataFailureLogService;
    @Autowired
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    private DataDictionaryTypeCertificateCsdcService certificateCsdcService;
    @Autowired
    private AccountInfoServiceImpl accountInfoService;
    @Autowired
    private FundInfoServiceImpl fundInfoService;//a
    @Autowired
    private InvestorInfoServiceImpl investorInfoService;//b
    @Autowired
    private InvestorBankInfoServiceImpl investorBankInfoService;//b
    @Autowired
    private FundNetValueInfoServiceImpl fundNetValueInfoService;//c
    @Autowired
    private CustShareInfoServiceImpl custShareInfoService;//d
    @Autowired
    private TgAccountBalanceInfoServiceImpl tgAccountBalanceInfoService;//e
    @Autowired
    private TgAccountSeqInfoServiceImpl tgAccountSeqInfoService;//f
    @Autowired
    private MjAccountBalanceInfoServiceImpl mjAccountBalanceInfoService;//g
    @Autowired
    private MjAccountSeqInfoServiceImpl mjAccountSeqInfoService;//h
    @Autowired
    private FundTradeInfoServiceImpl fundTradeInfoService;//i
    @Autowired
    private FundValueTableDataInfoServiceImpl fundValueTableDataInfoService;//j
    @Autowired
    private FundProfitInfoServiceImpl fundProfitInfoService;//j
    @Autowired
    private DataDictionarySellerServiceImpl sellerService;
    @Autowired
    private ChargeFeeDetailInfoServiceImpl chargeFeeDetailInfoService;
    @Autowired
    private PayFeeDetailInfoServiceImpl payFeeDetailInfoService;
    @Autowired
    private FundOpenInfoServiceImpl fundOpenInfoService;
    @Autowired
    private DataDictionaryOpenStateServiceImpl openStateService;
    @Autowired
    private SWHYUtils swhyUtils;
    @Resource(name = "pullDataThreadPool")
    private ExecutorService pullDataThreadPool;

    @Value("${custody.remote.url.swhy.swhyUrlPrefix}")
    private String swUrl;

    private final static LinkedBlockingDeque<String> bankAccoTaskQueue = new LinkedBlockingDeque<>();
    private final static LinkedBlockingDeque<String> tgAccountTaskQueue = new LinkedBlockingDeque<>();
    private final static LinkedBlockingDeque<String> mgAccountTaskQueue = new LinkedBlockingDeque<>();

    @Override
    public R initTenantData(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R initTenantDataSingle(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("申万托管数据初始化...");
        getDataFromSW(tenant, CustodyContants.INIT_BY_MONTH_LOOP_TIME); //先都拿1年，客户有需求再增加到3年
        log.info("申万托管数据初始化结束:");
        return R.ok("申万托管数据初始化结束！");
    }

    private void getDataFromSW(TenantEscrowAuthorizationInfoDto tenant, int loopTime) {
        String trustNo = "45";
        try {
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo);//end
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo, loopTime);//end20210101-20210122
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant, trustNo);//endSA0121
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo, loopTime);//end20160801-20160822
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo, loopTime);//end 20200901-20200925
            //15 资金账户基本信息表 account_info，16 托管户银行账户余额信息表（TGAccount_balance_info,MJAccount_balance_info）
            processAccountInfoData(tenant, trustNo);//end
            //19 募集户流水表（MJAccount_seq_info）托管户流水表（TGAccount_seq_info）
            processAccountSeqInfoData(tenant, trustNo, loopTime);//end20211001-20211029
            //2 基金出资人信息表（investor_info,investor_bank_info）
            processInvestorInfoData(tenant, trustNo);//end
            //20 基金估值报表数据表 fund_value_table_data_info
            processFundValueTableDataInfoData(tenant, trustNo, loopTime);//endSSQ422 20220401-20220422
            //费用计提明细表（charge_fee_detail_info） 费用支付明细表 (pay_fee_detail_info)
            processChargeAndPayFeeDetailInfo(tenant, trustNo, loopTime);
            //基金开放日信息表
            processFundOpenInfoData(tenant, trustNo, loopTime);
            List<String> bankAccoList = accountInfoService.getBankAcco(trustNo,tenant.getTenantName());
            if (!CollectionUtils.isEmpty(bankAccoList)) {
                for (String bankAcco : bankAccoList) {
                    if (StringUtils.isEmpty(bankAcco)) {
                        continue;
                    }
                    if (!bankAccoTaskQueue.contains(bankAcco)) {
                        bankAccoTaskQueue.put(bankAcco);
                    }
                }
            }
            List<String> mgBankAccoList = mjAccountSeqInfoService.getBankAccoList(trustNo,tenant.getTenantName());
            if (!CollectionUtils.isEmpty(mgBankAccoList)) {
                for (String mgBankAcco : mgBankAccoList) {
                    if (StringUtils.isEmpty(mgBankAcco)) {
                        continue;
                    }
                    if (!mgAccountTaskQueue.contains(mgBankAcco)) {
                        mgAccountTaskQueue.put(mgBankAcco);
                    }
                }
            }
            List<String> tgBankAccoList = tgAccountSeqInfoService.getBankAccoList(trustNo,tenant.getTenantName());
            if (!CollectionUtils.isEmpty(tgBankAccoList)) {
                for (String tgBankAcco : tgBankAccoList) {
                    if (StringUtils.isEmpty(tgBankAcco)) {
                        continue;
                    }
                    if (!mgAccountTaskQueue.contains(tgBankAcco)) {
                        mgAccountTaskQueue.put(tgBankAcco);
                    }
                }
            }

        } catch (Exception e) {
            log.error("申万托管数据拉取失败:", e);
            Thread.currentThread().interrupt();
        }
    }
    private void getUpdateDataFromSW(TenantEscrowAuthorizationInfoDto tenant, int loopTime) {
        String trustNo = "45";
        try {
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, trustNo);//end
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant, trustNo);//endSA0121
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, trustNo, loopTime);//end20160801-20160822
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, trustNo, loopTime);//end 20200901-20200925
            //2 基金出资人信息表（investor_info,investor_bank_info）
            processInvestorInfoData(tenant, trustNo);//end
            //20 基金估值报表数据表 fund_value_table_data_info
            processFundValueTableDataInfoData(tenant, trustNo, loopTime);//endSSQ422 20220401-20220422
            //费用计提明细表（charge_fee_detail_info） 费用支付明细表 (pay_fee_detail_info)
            processChargeAndPayFeeDetailInfo(tenant, trustNo, loopTime);
            //基金开放日信息表
            processFundOpenInfoData(tenant, trustNo, loopTime);
        } catch (Exception e) {
            log.error("申万托管数据拉取失败:", e);
        }
    }
    public void processFundOpenInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        try {
            String url = swUrl + SWConstants.FUND_OPEN_INFO_API;
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            endDate = dateTimeFormatter.format(localDate);
            String params;
            List<String> innerFundCodeList = fundInfoService.getInnerFundCode(trustNo, tenant.getTenantName());
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusMonths(1);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                int page = 1;
                int pageSize = 1000;
                List<JSONObject> resultDataSet;
                for (String innerFundCode : innerFundCodeList) {
                    while (true) {
                        if (page != 1) {
                            TimeUnit.SECONDS.sleep(60);
                        }
                        params = "{'beginDate':'" + finalStartDate + "','endDate':'" + finalEndDate + "','fundCode':'" + innerFundCode + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                        log.info("params:" + params);
                        Map<String, Object> map = swhyUtils.call(url, params, tenant);
                        log.info("申万processFundOpenInfoData上游数据:", JSON.toJSONString(map));
                        if (!(Boolean) map.get("result")) {
                            break;
                        }
                        Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                        Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                        resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                        log.info("申万获取processFundOpenInfoData数据{}条", resultDataSet.size());
                        //封装成标准表的对象
                        if (!CollectionUtils.isEmpty(resultDataSet)) {
                            List<FundOpenInfoEntity> fundOpenInfoEntities = getFundOpenInfo(tenant, trustNo, resultDataSet);
                            log.info("申万封装processFundOpenInfoData数据{}条", fundOpenInfoEntities);
                            fundOpenInfoService.saveData(null, fundOpenInfoEntities);
                        }
                        if (page * pageSize > totalCount) {
                            break;
                        }
                        page++;
                    }
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        } catch (InterruptedException ie) {
            log.error("申万processFundOpenInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("申万获取processFundOpenInfoData数据异常！", e);
        }
    }

    private List<FundOpenInfoEntity> getFundOpenInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<JSONObject> resultDataSet) {
        //获取数据字典
        //开放日类型字典
        Map<String, String> typeOfOpenDayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_OPEN_DAY_SERVICE, trustNo);
        //开放状态字典
        Map<String, Map<String, String>> openStateDic = openStateService.queryOpenStateWithDetail(trustNo);
        //封装数据
        List<FundOpenInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        for (JSONObject data : resultDataSet){
            dataMap = JSONObject.toJavaObject(data, Map.class);
            //转义开放日类型
            String openType = MatchDataDictionaryKeyUtil.getKey(typeOfOpenDayDic, dataMap.get("opensrc"));
            //转义开放状态
            String openStatus = MatchDataDictionaryKeyUtil.getKey(openType, openStateDic, dataMap.get("opentype"));
            //获得fundCode、fundName
            FundInfoEntity fundInfoEntity = fundInfoService.queryByInnerFundCode(trustNo, tenant.getTenantName(), dataMap.get("fundcode"));
            String fundCode = "";
            String fundName = "";
            if (Objects.nonNull(fundInfoEntity)) {
                fundCode = fundInfoEntity.getFundCode();
                fundName = fundInfoEntity.getFundName();
            }
            entityList.add(FundOpenInfoEntity.builder()
                    .innerFundCode(dataMap.get("fundcode"))
                    .fundOpenDate(dataMap.get("opendate"))
                    .openType(openType)
                    .openStatus(openStatus)
                    .fundCode(fundCode)
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    private void processChargeAndPayFeeDetailInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        try {
            String url = swUrl + SWConstants.CHARGE_AND_PAY_FEE_DETAIL_INFO_API;
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            endDate = dateTimeFormatter.format(localDate);
            String params;
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusMonths(1);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                // todo 测试
                finalStartDate = "20210701";
                finalEndDate = "20210830";
                int page = 1;
                int pageSize = 1000;
                List<JSONObject> resultDataSet;
                while (true) {
                    if(page!=1){
                        TimeUnit.SECONDS.sleep(60);
                    }
                    params = "{'dateBeg':'" + finalStartDate + "','dateEnd':'" + finalEndDate + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                    log.info("params:" + params);
                    Map<String, Object> map = swhyUtils.call(url, params, tenant);
                    log.info("申万processChargeAndPayFeeDetailInfoData上游数据:" , JSON.toJSONString(map));
                    if (!(Boolean) map.get("result")) {
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                    Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                    resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                    log.info("申万获取chargeFeeDetailInfo、payFeeDetailInfo数据{}条", resultDataSet.size());
                    //封装成标准表的对象
                    if (!CollectionUtils.isEmpty(resultDataSet)) {
                        Map<String, Object> entityMap = getChargeAndPayFeeDetailInfo(tenant, resultDataSet, trustNo);
                        List<ChargeFeeDetailInfoEntity> chargeFeeDetailInfoEntityList = JSONObject.parseArray(JSONObject.toJSONString(entityMap.get("charge")), ChargeFeeDetailInfoEntity.class);
                        List<PayFeeDetailInfoEntity> payFeeDetailInfoEntityList = JSONObject.parseArray(JSONObject.toJSONString(entityMap.get("pay")), PayFeeDetailInfoEntity.class);
                        log.info("申万封装chargeFeeDetailInfo数据{}条, 封装payFeeDetailInfo数据{}条", chargeFeeDetailInfoEntityList.size(), payFeeDetailInfoEntityList.size());
                        if (!CollectionUtils.isEmpty(chargeFeeDetailInfoEntityList)) {
                            chargeFeeDetailInfoService.saveData(null, chargeFeeDetailInfoEntityList);
                        }
                        if (!CollectionUtils.isEmpty(payFeeDetailInfoEntityList)) {
                            payFeeDetailInfoService.saveData(null, payFeeDetailInfoEntityList);
                        }
                    }
                    if (page * pageSize > totalCount) {
                        break;
                    }
                    page++;
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        } catch (InterruptedException ie) {
            log.error("申万processChargeAndPayFeeDetailInfo睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("申万processChargeAndPayFeeDetailInfo批量新增chargeFeeDataInfo、payFeeDetailInfo异常", e);
        }
    }


    private Map<String, Object> getChargeAndPayFeeDetailInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //获取字典
        //费用类型
        Map<String, String> typesOfFeeDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPES_OF_FEE_SERVICE, trustNo);
        //币种
        Map<String, String> currencyDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        //封装数据
        Map<String, Object> listMap = new HashMap<>();
        List<ChargeFeeDetailInfoEntity> chargeFeeEntityList = new ArrayList<>();
        List<PayFeeDetailInfoEntity> payFeeEntityList = new ArrayList<>();
        Map<String, String> remoteDataMap;
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String jdfx = remoteDataMap.get("jdfx");
            String summary = null;
            if (remoteDataMap.get("jt_desc") instanceof String){
                summary = remoteDataMap.get("jt_desc");
            }else {
                summary = JSONObject.toJSONString(remoteDataMap.get("jt_desc"));
            }
            if (!StringUtils.isEmpty(jdfx)) {
                if ("贷".equals(jdfx)) {
                    chargeFeeEntityList.add(ChargeFeeDetailInfoEntity.builder()
                            .feeDate(remoteDataMap.get("valdate"))
                            .fundCode(remoteDataMap.get("amaccode"))
                            .innerFundCode(remoteDataMap.get("fundcode"))
                            .fundName(remoteDataMap.get("fundname"))
                            .feeType(MatchDataDictionaryKeyUtil.getKey(typesOfFeeDic, remoteDataMap.get("feetype")))
                            .summary(summary)
                            .currency(MatchDataDictionaryKeyUtil.getKey(currencyDic, remoteDataMap.get("bz")))
                            .chargeFee(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("occurbala")))
                            .feeBalance(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("closebala")))
                            .trustNo(trustNo)
                            .admin(tenant.getTenantName())
                            .createTime(new Date())
                            .updateTime(new Date())
                            .build());
                }
                if ("借".equals(jdfx)){
                    payFeeEntityList.add(PayFeeDetailInfoEntity.builder()
                            .feeDate(remoteDataMap.get("valdate"))
                            .fundCode(remoteDataMap.get("amaccode"))
                            .innerFundCode(remoteDataMap.get("fundcode"))
                            .fundName(remoteDataMap.get("fundname"))
                            .feeType(MatchDataDictionaryKeyUtil.getKey(typesOfFeeDic, remoteDataMap.get("feetype")))
                            .summary(summary)
                            .currency(MatchDataDictionaryKeyUtil.getKey(currencyDic, remoteDataMap.get("bz")))
                            .chargeFee(BigDecimalUtil.obj2BigDecimalTrunToZero(remoteDataMap.get("occurbala")))
                            .feeBalance(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("closebala")))
                            .trustNo(trustNo)
                            .admin(tenant.getTenantName())
                            .createTime(new Date())
                            .updateTime(new Date())
                            .build());
                }
            }
        }
        listMap.put("charge", chargeFeeEntityList);
        listMap.put("pay", payFeeEntityList);
        return listMap;
    }

    private void processFundValueTableDataInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        try {
            List<String> fundCodeList = fundInfoService.getFundCodeList(trustNo, tenant.getTenantName());
            String url = swUrl + SWConstants.FUND_VALUE_TABLE_DATA_INFO_API;
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            endDate = dateTimeFormatter.format(localDate);
            String params;
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusDays(30);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                // todo 测试
                finalStartDate = "20181010";
                finalEndDate = "20181022";
                List<JSONObject> resultDataSet;
                for (String fundCode : fundCodeList) {
                    if (StringUtils.isEmpty(fundCode)) {
                        log.info("fundCode为null！");
                        continue;
                    }
                    TimeUnit.SECONDS.sleep(60);
                    params = "{'valDateBeg':'" + finalStartDate + "','valDateEnd':'" + finalEndDate + "','requestId':'" + UUID.randomUUID().toString().trim().replace("-", "").toUpperCase() + "','amacCode':'" + fundCode + "'}";
                    // todo 测试
                    params = "{'valDateBeg':'" + finalStartDate + "','valDateEnd':'" + finalEndDate + "','requestId':'20220807','amacCode':'PB1616'}";
                    log.info("params:" + params);
                    Map<String, Object> map = swhyUtils.call(url, params, tenant);
                    log.info("申万processFundValueTableDataInfoData上游数据:" + JSON.toJSONString(map));
                    if (!(Boolean) map.get("result")) {
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                    resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                    //封装成标准表的对象
                    if (!CollectionUtils.isEmpty(resultDataSet)) {
                        List<FundValueTableDataInfoEntity> entities = getFundValueTableDataInfo(tenant, resultDataSet, trustNo, fundCode);
                        fundValueTableDataInfoService.saveData(null, entities);
                    }
                }

                localDate = lastMonth;
                endDate = startDate;
            }
        } catch (InterruptedException ie){
            log.error("申万processFundValueTableDataInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
           log.error("申万processFundValueTableDataInfoData数据获取失败！", e);
        }
    }

    private List<FundValueTableDataInfoEntity> getFundValueTableDataInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo, String fundCode) {
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);

        //封装数据
        List<FundValueTableDataInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Map<String, String> map;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            log.info("remoteDataMap" + JSON.toJSONString(remoteDataMap));
            result.add(FundValueTableDataInfoEntity.builder()
                    .fundCode(fundCode)
                    .valueDate(remoteDataMap.get("valdate").replace("-", ""))
                    .fundName(remoteDataMap.get("fundname"))
                    .kmCode(remoteDataMap.get("kmdm"))
                    .kmName(remoteDataMap.get("kmmc"))
                    .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("bz")))
                    .vaRate(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("hl"), 4))
                    .amount(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("sl")))
                    .perCost(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("dwcb")))//
                    .origCost(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ybcb")))
                    .portCost(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("cb")))//cb
                    .costBi(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("cbzb"), 4))//cbzjz
                    .vapPrice(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("hq")))//hqjz
                    .portMv(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("sz")))//sz
                    .mvBl(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("szzb"), 4))//szzjz
                    .origIv(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ybgz")))
                    .portIv(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("gz")))//gzzz
                    .suspension(remoteDataMap.get("tpxx"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());

        }
        return result;
    }

    private void processInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            String url = swUrl + SWConstants.INVESTOR_INFO_API;
            String params;
            int page = 1;
            int pageSize = 1000;
            List<JSONObject> resultDataSet;
            while (true) {
                if(page!=1){
                    TimeUnit.SECONDS.sleep(60);
                }
                params = "{'reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                log.info("params:" + params);
                Map<String, Object> map = swhyUtils.call(url, params, tenant);
                log.info("申万processInvestorInfoData上游数据:" + JSON.toJSONString(map));
                if (!(Boolean) map.get("result")) {
                    break;
                }
                Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                //封装成标准表的对象
                if (!CollectionUtils.isEmpty(resultDataSet)) {
                    List<InvestorInfoEntity> investorInfoEntities = getInvestorInfo(tenant, resultDataSet, trustNo);
                    investorInfoService.saveData(null, investorInfoEntities);
                    //托管户封装成标准表的对象
                    List<InvestorBankInfoEntity> investorBankInfoEntities = getInvestorBankInfo(tenant, resultDataSet, trustNo);
                    investorBankInfoService.saveData(null, investorBankInfoEntities);
                }
                if (page * pageSize > totalCount) {
                    break;
                }
                page++;
            }
        } catch (InterruptedException ie) {
            log.error("申万processInvestorInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("申万processInvestorInfoData获取数据异常！", e);
        }
    }

    private List<InvestorBankInfoEntity> getInvestorBankInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "申万宏源TA");
        //2、封装数据
        List<InvestorBankInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> remoteDataMap;
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String bankNo = MatchDataDictionaryKeyUtil.getKey(bankCodeDir, remoteDataMap.get("bankno"));
            log.info("getInvestorBankInfo:bankNo为" + remoteDataMap.get("bankno") + " 转义后bankCode为" + bankNo);
            result.add(InvestorBankInfoEntity.builder()
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .bankCode(bankNo)
                    .bankNo(remoteDataMap.get("bankacco"))
                    .branchBankName(remoteDataMap.get("openbankname"))
                    .nameInBank(remoteDataMap.get("nameinbank"))
                    .bankNoType("银行账号")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private List<InvestorInfoEntity> getInvestorInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> custTypeCsdcDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CUST_TYPE_CSDC_SERVICE, trustNo);
        Map<String, Map<String, String>> identityTypeCsdcDic = certificateCsdcService.queryCertificateWithDetail(trustNo);

        //2、封装数据
        List<InvestorInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        List<JSONObject> list = JSONObject.parseArray(JSONObject.toJSONString(resultDataSet), JSONObject.class);
        for (JSONObject remoteData : list) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String key = MatchDataDictionaryKeyUtil.getKey(custTypeCsdcDic, remoteDataMap.get("custtype"));
            String certiType = remoteDataMap.get("certitype");
            String identityType = MatchDataDictionaryKeyUtil.getKey(key, identityTypeCsdcDic, certiType);
            result.add(InvestorInfoEntity.builder()
                    .custName(remoteDataMap.get("custname"))
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .custType(key)
                    .identityType(identityType)
                    .identityNo(remoteDataMap.get("certino"))
                    .accoOpenDate(Objects.isNull(remoteDataMap.get("opendate")) ? null : remoteDataMap.get("opendate").replace("-", ""))
                    .address(remoteDataMap.get("address"))
                    .mobileNo(remoteDataMap.get("tel"))
                    .email(remoteDataMap.get("zipcode"))
                    .updateDate(Objects.isNull(remoteDataMap.get("lastmodify")) ? null : remoteDataMap.get("lastmodify") + " 00:00:00")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processAccountSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        try {
            String url = swUrl + SWConstants.ACCOUNT_SEQ_INFO_API_OFFLINE;
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            endDate = dateTimeFormatter.format(localDate);
            String params;
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusMonths(1);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                // todo 测试
                finalStartDate = "20211001";
                finalEndDate = "20211029";
                int page = 1;
                int pageSize = 10000;
                List<JSONObject> resultDataSet;
                while (true) {
                    if(page!=1||i!=0){
                        TimeUnit.SECONDS.sleep(60);
                    }
                    params = "{'beginDate':'" + finalStartDate + "','endDate':'" + finalEndDate + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                    log.info("params:" + params);
                    Map<String, Object> map = swhyUtils.call(url, params, tenant);
                    log.info("申万processAccountSeqInfoData上游数据:" + JSON.toJSONString(map));
                    if (!(Boolean) map.get("result")) {
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                    Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                    resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                    //封装成标准表的对象
                    if (!CollectionUtils.isEmpty(resultDataSet)) {
                        List<MjAccountSeqInfoEntity> entities = getMJAccountSeqInfo(tenant, resultDataSet, trustNo);
                        if (!CollectionUtils.isEmpty(entities)) {
                            mjAccountSeqInfoService.saveData(null, entities);
                        }
                        List<TgAccountSeqInfoEntity> tgAccountSeqInfoEntities = getTGAccountSeqInfo(tenant, resultDataSet, trustNo);
                        if (!CollectionUtils.isEmpty(tgAccountSeqInfoEntities)) {
                            tgAccountSeqInfoService.saveData(null, tgAccountSeqInfoEntities);
                        }
                    }
                    if (page * pageSize > totalCount) {
                        break;
                    }
                    page++;
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        } catch (InterruptedException ie) {
            log.error("申万processAccountSeqInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("申万processAccountSeqInfoData获取数据异常！", e);
        }
    }

    private List<TgAccountSeqInfoEntity> getTGAccountSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> paymentDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_DIRECTION_SERVICE, trustNo);
        //2、封装数据
        List<TgAccountSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            if ("04".equals(remoteDataMap.get("accType"))) {
                String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"), trustNo);
                result.add(TgAccountSeqInfoEntity.builder()
                        .fundCode(fundCode)
                        .innerFundCode(remoteDataMap.get("fundCode"))
                        .fundName(remoteDataMap.get("fundName"))
                        .transferInOut(MatchDataDictionaryKeyUtil.getKey(paymentDir, remoteDataMap.get("directFlag")))
                        .account(remoteDataMap.get("bankAcco"))
                        .accountName(remoteDataMap.get("accName"))
                        .bankName(remoteDataMap.get("openBankName"))
                        .opAccount(remoteDataMap.get("othBankAcco"))
                        .opAccountName(remoteDataMap.get("othAccName"))
                        .opBankName(remoteDataMap.get("othOpenBankName"))
                        .amount(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("occurAmt"))))
                        .transferDate(remoteDataMap.get("occurTime").split(" ")[0].replace("-", ""))
                        .transferTime(remoteDataMap.get("occurTime").split(" ")[1])
                        .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("curType")))
                        .summary(remoteDataMap.get("bankNote"))
                        .seqNo(StrUtil.getSeqNoWithoutNoRandom(remoteDataMap.get("bankvoucherid")))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    private List<MjAccountSeqInfoEntity> getMJAccountSeqInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> pay = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_DIRECTION_SERVICE, trustNo);

        //2、封装数据
        List<MjAccountSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            if ("02".equals(remoteDataMap.get("accType"))) {
                String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"), trustNo);
                result.add(MjAccountSeqInfoEntity.builder()
                        .fundCode(fundCode)
                        .innerFundCode(remoteDataMap.get("fundCode"))
                        .fundName(remoteDataMap.get("fundName"))
                        .transferInOut(MatchDataDictionaryKeyUtil.getKey(pay, remoteDataMap.get("directFlag")))
                        .account(remoteDataMap.get("bankAcco"))
                        .accountName(remoteDataMap.get("accName"))
                        .bankName(remoteDataMap.get("openBankName"))
                        .opAccount(remoteDataMap.get("othBankAcco"))
                        .opAccountName(remoteDataMap.get("othAccName"))
                        .opBankName(remoteDataMap.get("othOpenBankName"))
                        .amount(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("occurAmt"))))
                        .transferDate(remoteDataMap.get("occurTime").split(" ")[0].replace("-", ""))
                        .transferTime(remoteDataMap.get("occurTime").split(" ")[1])
                        .currency(MatchDataDictionaryKeyUtil.getKey(currencyDir, remoteDataMap.get("curType")))
                        .summary(remoteDataMap.get("bankNote"))
                        .seqNo(StrUtil.getSeqNoWithoutNoRandom(remoteDataMap.get("bankvoucherid")))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    private void processAccountInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            String url = swUrl + SWConstants.ACCOUNT_INFO_API_OFFLINE;
            String params;
            int page = 1;
            int pageSize = 10000;
            List<JSONObject> resultDataSet;
            while (true) {
                if(page!=1){
                    TimeUnit.SECONDS.sleep(60);
                }
                params = "{'reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                log.info("params:" + params);
                Map<String, Object> map = swhyUtils.call(url, params, tenant);
                log.info("申万processAccountInfoData上游数据:" + JSON.toJSONString(map));
                if (!(Boolean) map.get("result")) {
                    break;
                }
                Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                //封装成标准表的对象
                if (!CollectionUtils.isEmpty(resultDataSet)) {
                    List<AccountInfoEntity> accountEntities = getAccountInfo(tenant, resultDataSet, trustNo);
                    accountInfoService.saveData(null, accountEntities);
                    List<MjAccountBalanceInfoEntity> entities = getMJAccountBanlance(tenant, resultDataSet, trustNo);
                    if(!CollectionUtils.isEmpty(entities)){
                        mjAccountBalanceInfoService.saveData(null, entities);
                    }
                    List<TgAccountBalanceInfoEntity> tgAccountEntities = getTGAccountBanlance(tenant, resultDataSet, trustNo);
                    if(!CollectionUtils.isEmpty(tgAccountEntities)){
                        tgAccountBalanceInfoService.saveData(null, tgAccountEntities);
                    }
                }
                if (page * pageSize > totalCount) {
                    break;
                }
                page++;
            }
        } catch (InterruptedException ie) {
            log.error("申万processAccountInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("申万processAccountInfoData获取数据异常！", e);
        }
    }

    private List<TgAccountBalanceInfoEntity> getTGAccountBanlance(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currency = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        //2、封装数据
        List<TgAccountBalanceInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        //for (JSONObject remoteData : resultDataSet) {
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
            if ("04".equals(remoteDataMap.get("accType"))) {
                result.add(TgAccountBalanceInfoEntity.builder()
                        .currency(MatchDataDictionaryKeyUtil.getKey(currency, remoteDataMap.get("curType")))
                        .bankAcco(remoteDataMap.get("bankAcco"))
                        .accoBalance(BigDecimalUtil.obj2BigDecimal(String.valueOf(remoteDataMap.get("acctBal"))))
                        .updateDate(remoteDataMap.get("retTime"))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    private List<MjAccountBalanceInfoEntity> getMJAccountBanlance(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> currency = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);

        //2、封装数据
        List<MjAccountBalanceInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        //for (JSONObject remoteData : resultDataSet) {
        for (int i = resultDataSet.size() - 1; i >= 0; i--) {
            remoteDataMap = JSONObject.toJavaObject(resultDataSet.get(i), Map.class);
            if ("02".equals(remoteDataMap.get("accType"))) {
                result.add(MjAccountBalanceInfoEntity.builder()
                        .bankAcco(remoteDataMap.get("bankAcco"))
                        .accoBalance(BigDecimalUtil.str2BigDecimal(String.valueOf(remoteDataMap.get("acctBal"))))
                        .updateDate(remoteDataMap.get("retTime"))
                        .currency(MatchDataDictionaryKeyUtil.getKey(currency, remoteDataMap.get("curType")))
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .createTime(now)
                        .updateTime(now)
                        .build());
            }
        }
        return result;
    }

    private List<AccountInfoEntity> getAccountInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "申万宏源TA");
        Map<String, String> currency = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        Map<String, String> type = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.ACCOUNT_TYPE_SERVICE, trustNo);

        //2、封装数据
        List<AccountInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"), trustNo);
            result.add(AccountInfoEntity.builder()
                    .fundCode(fundCode)
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .currency(MatchDataDictionaryKeyUtil.getKey(currency, remoteDataMap.get("curType")))
                    .accoTypeCode(MatchDataDictionaryKeyUtil.getKey(type, remoteDataMap.get("accType")))
                    .bankAcco(remoteDataMap.get("bankAcco"))
                    .nameInBank(remoteDataMap.get("accName"))
                    .bankCode(MatchDataDictionaryKeyUtil.getKey(bankCodeDir, remoteDataMap.get("bankNo")))
                    .branchBankName(remoteDataMap.get("openBankName"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        try {
            String url = swUrl + SWConstants.FUND_PROFIT_INFO_API;
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            endDate = dateTimeFormatter.format(localDate);
            String params;
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusMonths(1);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                // todo 测试
                finalStartDate = "20200930";
                finalEndDate = "20200930";
                int page = 1;
                int pageSize = 10000;
                List<JSONObject> resultDataSet;
                while (true) {
                    if(page!=1||i!=0){
                        TimeUnit.SECONDS.sleep(60);
                    }
                    params = "{'confDateBegin':'" + finalStartDate + "','confDateEnd':'" + finalEndDate + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                    log.info("params:" + params);
                    Map<String, Object> map = swhyUtils.call(url, params, tenant);
                    log.info("申万processFundProfitInfoData上游数据:" + JSON.toJSONString(map));
                    if (!(Boolean) map.get("result")) {
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                    Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                    resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                    //封装成标准表的对象
                    if (!CollectionUtils.isEmpty(resultDataSet)) {
                        List<FundProfitInfoEntity> entities = getFundProfitInfo(tenant, resultDataSet, trustNo);
                        fundProfitInfoService.saveData(null, entities);
                    }
                    if (page * pageSize > totalCount) {
                        break;
                    }
                    page++;
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        } catch (InterruptedException ie){
            log.error("申万processFundProfitInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("申万processFundProfitInfoData获取数据失败！", e);
        }
    }

    private List<FundProfitInfoEntity> getFundProfitInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "申万宏源");
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> handle = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.HANDLE_TYPE_SERVICE, trustNo);

        //2、封装数据
        List<FundProfitInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String agencyName = sellerService.queryAgencyName("申万宏源", remoteDataMap.get("agencyno"));
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            result.add(FundProfitInfoEntity.builder()
                    .fundCode(fundCode)
                    .confirmDate(remoteDataMap.get("confdate").replace("-", ""))
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(sellerDic, remoteDataMap.get("agencyno")))
                    .agencyName(agencyName)
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .fundName(remoteDataMap.get("fundname"))
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("busitype")))
                    .sortFlag(MatchDataDictionaryKeyUtil.getKey(handle, remoteDataMap.get("sortflag")))
                    .requestDate(remoteDataMap.get("ddate").replace("-", ""))
                    .registDate(remoteDataMap.get("registdate").replace("-", ""))
                    .oriDate(remoteDataMap.get("dbegindate"))
                    .holdDay(remoteDataMap.get("lhold"))
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .shares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("shares")))
                    .oriNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("orinav"), 4))
                    .oriTotalNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oritotalnav"), 4))
                    .nav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("nav"), 4))
                    .totalNav(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalnav"), 4))
                    .currRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("currratio"), 4))
                    .yearRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("yearratio"), 4))
                    .standardRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("standardratio")))
                    .returnFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("returnfare")))
                    .oriBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("oribalance")))
                    .factBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factbalance")))
                    .factShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("factshares")))
                    .bonusBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("bonusbalance")))
                    .income(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("income")))
                    .deductRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("deductratio")))
                    .valueAddedFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("valueaddedfare")))
                    .costPrice(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("costprice")))
                    .totalUnitBonus(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalunitbonus")))
                    .oriCserialNo(remoteDataMap.get("oricserialno"))
                    .cserialNo(remoteDataMap.get("cserialno"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        try {
            String url = swUrl + SWConstants.FUND_TRADE_INFO_API;
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            endDate = dateTimeFormatter.format(localDate);
            String params;
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusMonths(1);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                // todo 测试
                finalStartDate = "20220805";
                finalEndDate = "20220810";
                int page = 1;
                int pageSize = 10000;
                List<JSONObject> resultDataSet;
                while (true) {
                    if(page!=1||i!=0){
                        TimeUnit.SECONDS.sleep(60);
                    }
                    params = "{'confDateBegin':'" + finalStartDate + "','confDateEnd':'" + finalEndDate + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                    log.info("params:" + params);
                    Map<String, Object> map = swhyUtils.call(url, params, tenant);
                    log.info("申万processFundTradeInfoData上游数据:" + JSON.toJSONString(map));
                    if (!(Boolean) map.get("result")) {
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                    Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                    resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                    //封装成标准表的对象
                    if (!CollectionUtils.isEmpty(resultDataSet)) {
                        List<FundTradeInfoEntity> entities = getFundTradeInfo(tenant, resultDataSet, trustNo);
                        fundTradeInfoService.saveData(null, entities);
                    }
                    if (page * pageSize > totalCount) {
                        break;
                    }
                    page++;
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        } catch (InterruptedException ie){
            log.error("申万processFundTradeInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("申万processFundTradeInfoData获取数据失败！", e);
        }

    }

    private List<FundTradeInfoEntity> getFundTradeInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> flag = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TA_LAUNCH_FLAG_SERVICE, trustNo);
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);
        Map<String, String> businessTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, trustNo);
        Map<String, String> sell = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "申万宏源");

        //2、封装数据
        List<FundTradeInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            result.add(FundTradeInfoEntity.builder()
                    .fundCode(fundCode)
                    .confirmDate(remoteDataMap.get("confdate").replace("-", ""))
                    .requestDate(remoteDataMap.get("applydate").replace("-", ""))
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .fundName(remoteDataMap.get("fundname"))
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(sell, remoteDataMap.get("agencyno")))
                    .agencyName(remoteDataMap.get("agencyname"))
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .taFlag(MatchDataDictionaryKeyUtil.getKey(flag, remoteDataMap.get("taflag")))
                    .confirmStatus(remoteDataMap.get("confstatus"))
                    .agio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("agio")))
                    .bonusMethod(MatchDataDictionaryKeyUtil.getKey(dividendDir, remoteDataMap.get("bonustype")))
                    .applyBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("balance")))
                    .applyShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("shares")))
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netvalue"), 4))
                    .confirmBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confbalance")))
                    .confirmShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("confshares")))
                    .tradeFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("tradefare")))
                    .taFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("tafare")))
                    .stampTax(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("stamptax")))
                    .backFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("backfare")))
                    .breachFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("breachfare")))
                    .breachFareAgt(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("breachfare4agt")))
                    .breachFareFund(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("breachfare4fund")))
                    .profitBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("profitbalance")))
                    .profitBalanceAgt(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("profitbalance4agt")))
                    .totalFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("totalfare")))
                    .agencyFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("agencyfare")))
                    .fundFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("fundfare")))
                    .registFare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("registfare")))
                    .interest(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interest")))
                    .interestTax(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interesttax")))
                    .interestShare(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("interestshare")))
                    .frozenBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("frozenbalance")))
                    .unfrozenBalance(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("unfrozenbalance")))
                    .unShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("unshares")))
                    .confirmNavVol(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("netconfbalance")))
                    .cserialNo(remoteDataMap.get("cserialno"))
                    .businessName(MatchDataDictionaryKeyUtil.getKey(businessTypeDir, remoteDataMap.get("busiflag")))
                    .requestNo(remoteDataMap.get("originalno"))
                    .currency("156")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processCustShareInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            List<String> innerFundCodeList = fundInfoService.getInnerFundCode(trustNo, tenant.getTenantName());
            String url = swUrl + SWConstants.CUST_SHARE_INFO_API;
            String params;
            List<JSONObject> resultDataSet;
            List<CustShareInfoEntity> allList =  new ArrayList<>();
            for (String innerFundCode : innerFundCodeList) {
                if (StringUtils.isEmpty(innerFundCode)) {
                    continue;
                }
                int page = 0;
                int pageSize = 500;
                List<CustShareInfoEntity> entityList = new ArrayList<>();
                while (true) {
                    TimeUnit.SECONDS.sleep(60);
                    page++;
                    params = "{'fundCode':'" + innerFundCode + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                    log.info("params:" + params);
                    Map<String, Object> map = swhyUtils.call(url, params, tenant);
                    log.info("申万processCustShareInfoData上游数据:" + JSON.toJSONString(map));
                    if (!(Boolean) map.get("result")) {
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                    Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                    resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                    //封装成标准表的对象
                    if (!CollectionUtils.isEmpty(resultDataSet)) {
                        List<CustShareInfoEntity> entities = getCustShareInfo(tenant, resultDataSet, trustNo);
                        entityList.addAll(entities);
                    }
                    if (page * pageSize > totalCount) {
                        break;
                    }
                }
                allList.addAll(entityList);
            }
            custShareInfoService.saveData(null, allList);
        } catch (InterruptedException ie){
            log.error("申万processCustShareInfoData获取数据失败！", ie);
            Thread.currentThread().interrupt();
        }catch (Exception e) {
            log.error("申万processCustShareInfoData获取数据失败！", e);
        }
    }

    private List<CustShareInfoEntity> getCustShareInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> serviceDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "申万宏源");
//        Map<String, String> fundTypeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_TYPE_SERVICE, trustNo);
        Map<String, String> dividendDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, trustNo);

        //2、封装数据
        List<CustShareInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            String agencyName = sellerService.queryAgencyName("申万宏源", remoteDataMap.get("agencyno"));
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundcode"), trustNo);
            //处理updateDate
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String updateDate = null;
            if (!StringUtils.isEmpty(remoteDataMap.get("lastmodify"))) {
                try {
                    Date parse = sdf.parse(remoteDataMap.get("lastModify"));
                    updateDate = sdf1.format(parse);
                } catch (ParseException e) {
                    e.printStackTrace();
                    log.error("upadteDate转化失败！", e);
                }
            }
            result.add(CustShareInfoEntity.builder()
                    .fundCode(fundCode)
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .fundName(remoteDataMap.get("fundname"))
                    .fundAcco(remoteDataMap.get("fundacco"))
                    .agencyNo(MatchDataDictionaryKeyUtil.getKey(serviceDir, remoteDataMap.get("agencyno")))
                    .agencyName(agencyName)
                    .tradeAcco(remoteDataMap.get("tradeacco"))
                    .enableShares(new BigDecimal(remoteDataMap.get("enableShares") == null ? "0" : remoteDataMap.get("enableShares").replace(",", "")).setScale(2))
                    .lastHoldShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("realshares").replace(",", "")))//
                    .shareRatio(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("shareratio")))
                    .netValueDate(remoteDataMap.get("busidate"))
                    .frozenShares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("frozenshares").replace(",", "")))
                    .bonusMethod(MatchDataDictionaryKeyUtil.getKey(dividendDir, remoteDataMap.get("bonustype")))
                    .updateDate(updateDate)
                    .enableShares(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("enableshares")))
                    .income(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("income")))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private void processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        try {
            String url = swUrl + SWConstants.FUND_NET_VALUE_INFO_API;
            String startDate;
            String endDate;
            LocalDate localDate = LocalDate.now();
            LocalDate lastMonth;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            endDate = dateTimeFormatter.format(localDate);
            String params;
            for (int i = 0; i < loopTime; i++) {
                lastMonth = localDate.minusMonths(1);
                startDate = dateTimeFormatter.format(lastMonth);
                String finalStartDate = startDate;
                String finalEndDate = endDate;
                //todo 测试账号
                finalStartDate = "20210301";
                finalEndDate = "20210430";
                int page = 1;
                int pageSize = 500;
                List<JSONObject> fundNetValueResultDataSet;
                while (true) {
                    if(page!=1||i!=0){
                        TimeUnit.SECONDS.sleep(60);
                    }
                    params = "{'netDateBegin':'" + finalStartDate + "','netDateEnd':'" + finalEndDate + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                    log.info("params:" + params);
                    Map<String, Object> map = swhyUtils.call(url, params, tenant);
                    log.info("申万processFundNetValueInfoData上游数据:" + JSON.toJSONString(map));
                    if (!(Boolean) map.get("result")) {
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                    Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                    fundNetValueResultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                    //封装成标准表的对象
                    if (!CollectionUtils.isEmpty(fundNetValueResultDataSet)) {
                        List<FundNetValueInfoEntity> entities = getSWFundNetValInfo(tenant, fundNetValueResultDataSet, trustNo);
                        log.info("fudNetValueInfo表开始入库！！");
                        fundNetValueInfoService.saveData(null, entities);
                        log.info("fudNetValueInfo表入库完成！！");
                    }
                    if (page * pageSize > totalCount) {
                        break;
                    }
                    page++;
                }
                localDate = lastMonth;
                endDate = startDate;
            }
        } catch (InterruptedException ie){
            log.error("申万processFundNetValueInfoData睡眠被打断！", ie);
            Thread.currentThread().interrupt();
        }catch (Exception e) {
            log.error("申万processFundNetValueInfoData获取数据失败！", e);
        }
    }

    private List<FundNetValueInfoEntity> getSWFundNetValInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> fundNetValueResultDataSet, String trustNo) {
        //1、获取字典表数据
        //Map<String, String> currencyDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);

        //2、封装数据
        if (CollectionUtils.isEmpty(fundNetValueResultDataSet)){
            return Collections.emptyList();
        }
        List<FundNetValueInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        int  fundNetValueResultDataSetSize= fundNetValueResultDataSet.size();
        for (int i = fundNetValueResultDataSetSize - 1; i >= 0; i--) {
            log.info("i="+i);
            log.info("fundNetValueRemoteDatas数据为:"+JSON.toJSONString(fundNetValueResultDataSet.get(i)));
            remoteDataMap = JSONObject.toJavaObject(fundNetValueResultDataSet.get(i), Map.class);
            log.info("remoteDataMap数据为:"+JSON.toJSONString(remoteDataMap));
            String fundCode = fundInfoService.getInnerFundCodeByInnerFundCode(remoteDataMap.get("fundcode"));
            log.info("fundNetValueInfo的fundCode:"+fundCode);
            FundNetValueInfoEntity build = FundNetValueInfoEntity.builder()
                    .fundCode(fundCode)
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .netValueDate(remoteDataMap.get("netdate"))
                    .fundName(remoteDataMap.get("fundname"))
                    .shares(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("assetshares")))
                    .totalAsset(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("totalasset")))
                    .assetValue(BigDecimalUtil.str2BigDecimalDefaultZero(remoteDataMap.get("assetnet")))
                    .netValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("unitnv"), 4))
                    .totalNetValue(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("accumunitnv"), 4))
                    .ettFundIncome(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("ettfundincome")))
                    .sevenDayRate(BigDecimalUtil.str2BigDecimal(remoteDataMap.get("sevendayrate")))
                    .currency("156")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build();
            log.info("fundNetValue标准表结果：" + JSON.toJSONString(build));
            result.add(build);
        }
        log.info("result_size:"+result.size());
        return result;
    }

    private void processFundInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            String url = swUrl + SWConstants.FUND_INFO_API;
            // todo 测试
            String params = "{'fundCode':'TEST19'}";
            Map<String, Object> map = swhyUtils.call(url, params, tenant);
            log.info("申万processFundInfoData上游数据:" + JSON.toJSONString(map));
            List<JSONObject> resultDataSet;
            if ((Boolean) map.get("result")) {
                resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(map.get("data")), JSONObject.class);
                if (!CollectionUtils.isEmpty(resultDataSet)) {
                    //封装成标准表的对象
                    List<FundInfoEntity> entities = getFundInfo(tenant, resultDataSet, trustNo);
                    fundInfoService.saveData(null, entities);
                }
            }
        } catch (Exception e) {
            log.error("申万processFundInfoData获取数据失败！", e);
        }

    }

    private List<FundInfoEntity> getFundInfo(TenantEscrowAuthorizationInfoDto tenant, List<JSONObject> resultDataSet, String trustNo) {
        //1、获取字典表数据
        Map<String, String> day = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TA_TRANSACTION_CONFIRM_ATION_DAYS_SERVICE, trustNo);
        Map<String, String> serviceCode = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SERVICE_MODEL_SERVICE, trustNo);
        Map<String, String> status = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRODUCT_STATUS_SERVICE, trustNo);
        Map<String, String> type = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_TYPE_SERVICE, trustNo);
        Map<String, String> privateType = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRIVATE_FUND_TYPE_SERVICE, trustNo);
        //2、封装数据
        List<FundInfoEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (JSONObject remoteData : resultDataSet) {
            remoteDataMap = JSONObject.toJavaObject(remoteData, Map.class);
            result.add(FundInfoEntity.builder()
                    .fundCode(remoteDataMap.get("amacfundcode"))
                    .innerFundCode(remoteDataMap.get("fundcode"))
                    .fundName(remoteDataMap.get("fundname"))
                    .confDays(String.valueOf(MatchDataDictionaryKeyUtil.getKey(day, String.valueOf(remoteDataMap.get("confdays")))))
                    .serviceMode(MatchDataDictionaryKeyUtil.getKey(serviceCode, remoteDataMap.get("servicemode")))//
                    .fundStatus(MatchDataDictionaryKeyUtil.getKey(status, remoteDataMap.get("fundstatus")))//
                    .fundType(MatchDataDictionaryKeyUtil.getKey(type, remoteDataMap.get("fundtype")))//
                    .peType(MatchDataDictionaryKeyUtil.getKey(privateType, remoteDataMap.get("fundtype")))//
                    .createDate(remoteDataMap.get("establishdate"))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    @Override
    public R updateDataDaily(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R updateSingleDataDaily(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("申万托管数据初始化...");
        getUpdateDataFromSW(tenant, 1);
        log.info("申万托管数据初始化结束:");
        return R.ok("申万托管数据初始化结束！");
    }

    @Override
    public R PullRemoteDataFirstQueueJob() {
        return null;
    }

    @Override
    public R initLaterTenantData(String versionStr, List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R initLaterSingleTenantData(String versionStr, TenantEscrowAuthorizationInfoDto tenant) {
        log.info("sw:initLaterSingleTenantData", versionStr, JSON.toJSONString(tenant));
        String trustNo = tenant.getTrustNo();
        Integer loopNum = CustodyContants.INIT_BY_MONTH_LOOP_TIME;
//        Integer loopNum = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
        try {
            switch (versionStr) {
                case CustodyContants.R_PT_S_CUSTODY_3_1_8_PATCH01:
                    //19 募集户流水表（MJAccount_seq_info）托管户流水表（TGAccount_seq_info）
                    processAccountSeqInfoData(tenant, trustNo, loopNum);//end20211001-20211029
                    List<String> bankAccoList = accountInfoService.getBankAcco(trustNo, tenant.getTenantName());
                    if (!CollectionUtils.isEmpty(bankAccoList)) {
                        for (String bankAcco : bankAccoList) {
                            if (StringUtils.isEmpty(bankAcco)) {
                                continue;
                            }
                            if (!bankAccoTaskQueue.contains(bankAcco)) {
                                bankAccoTaskQueue.put(bankAcco);
                            }
                        }

                        List<String> mgBankAccoList = mjAccountSeqInfoService.getBankAccoList(trustNo, tenant.getTenantName());
                        if (!CollectionUtils.isEmpty(mgBankAccoList)) {
                            for (String mgBankAcco : mgBankAccoList) {
                                if (StringUtils.isEmpty(mgBankAcco)) {
                                    continue;
                                }
                                if (!mgAccountTaskQueue.contains(mgBankAcco)) {
                                    mgAccountTaskQueue.put(mgBankAcco);
                                }
                            }
                        }
                        List<String> tgBankAccoList = tgAccountSeqInfoService.getBankAccoList(trustNo, tenant.getTenantName());
                        if (!CollectionUtils.isEmpty(tgBankAccoList)) {
                            for (String tgBankAcco : tgBankAccoList) {
                                if (StringUtils.isEmpty(tgBankAcco)) {
                                    continue;
                                }
                                if (!mgAccountTaskQueue.contains(tgBankAcco)) {
                                    mgAccountTaskQueue.put(tgBankAcco);
                                }
                            }
                        }
                        log.info("申万募集户/托管户流水数据结束~");
                        break;
                    }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (Exception e){
            log.error("申万更新流水表失败!", e);
        }
        return null;
    }

    private void initTenantDataBy308(TenantEscrowAuthorizationInfoDto tenant, String trustNo, Integer loopTime) {
        log.info("sw:initTenantDataBy318patch01 is run...");
        try {
            processFundOpenInfoData(tenant, trustNo, loopTime);//endSA0121
            log.info("sw:initTenantDataBy318patch01 is end...");
        } catch (Exception e) {
            log.error("sw:initTenantDataBy318patch01 is error:", e);
        }
    }

    @Override
    public R initByAppointedTrustNoAndMouth(TenantEscrowAuthorizationInfoDto tenant, int mouth) {
        log.info("initByAppointedTrustNoAndMouth_tenant={},mouth={}", JSON.toJSONString(tenant), mouth);
        getDataFromSW(tenant, mouth);
        return R.ok();
    }

    @Override
    public R updateData20min(List<TenantEscrowAuthorizationInfoDto> data) {
        return null;
    }

    @Override
    public R updateSingleData20min(TenantEscrowAuthorizationInfoDto tenant) {

        if (!bankAccoTaskQueue.isEmpty()) {
            String bankAcco = bankAccoTaskQueue.getFirst();
            if (!StringUtils.isEmpty(bankAcco)) {
                log.info("申万没30min更新bankAcco:" + bankAcco);
                getAccountInfoData(tenant, bankAcco);
                bankAccoTaskQueue.remove(bankAcco);
            }
        }
        return null;
    }

    @Override
    public R updateData1h(List<TenantEscrowAuthorizationInfoDto> data) {
        return null;
    }

    @Override
    public R updateSingleData1h(TenantEscrowAuthorizationInfoDto tenant) {
        return null;
    }

    @Override
    public R updateDataCJ(String date, String flag, TenantEscrowAuthorizationInfoDto tenant) {
        return null;
    }

    @Override
    public R updateNetValueData(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R updateSingleNetValueData(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("申万每8点、12点、20点更新数据开始~");
        String trustNo = "45";
        int loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
        try {
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, trustNo, loopTime);
            log.info("申万每8点、12点、20点更新数据结束~");
        }catch (Exception e){
            log.error("申万每8点、12点、20点更新数据异常！");
        }
        return R.ok("申万每8点、12点、20点更新数据完成！");
    }

    @Override
    public DubboResult updateMJBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            // 资金账户基本信息表 account_info 托管户银行账户余额信息表（TGAccount_balance_info,MJAccount_balance_info）
            processAccountInfoData(tenant, tenant.getTrustNo());
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募集户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateMJSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            // 募集户流水表（MJAccount_seq_info）托管户流水表（TGAccount_seq_info）
            processAccountSeqInfoData(tenant, tenant.getTrustNo(), 1);//end20211001-20211029
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新募集户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户流水失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            // 资金账户基本信息表 account_info 托管户银行账户余额信息表（TGAccount_balance_info,MJAccount_balance_info）
            processAccountInfoData(tenant, tenant.getTrustNo());
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新托管户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {
            // 募集户流水表（MJAccount_seq_info）托管户流水表（TGAccount_seq_info）
            processAccountSeqInfoData(tenant, tenant.getTrustNo(), 1);
            return DubboResult.newSuccess();
        } catch (Exception e) {
            log.error("手动更新托管户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户流水失败" + e.getMessage());
        }
    }

    private void getMGAccountInfoData(TenantEscrowAuthorizationInfoDto tenant, String bankAcco) {
        try {
            String url = swUrl + SWConstants.ACCOUNT_SEQ_INFO_API_ONLINE;
            String params;
            int page = 1;
            int pageSize = 10000;
            List<JSONObject> resultDataSet;
            while (true) {
                //一分钟调一次
                if (page != 1) {
                    TimeUnit.MINUTES.sleep(30);
                }
                params = "{'bankAcco':'" + bankAcco + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                log.info("params:" + params);
                Map<String, Object> map = swhyUtils.call(url, params, tenant);
                if (!(Boolean) map.get("result")) {
                    break;
                }
                Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                //封装成标准表的对象
                if (!CollectionUtils.isEmpty(resultDataSet)) {
                    List<MjAccountSeqInfoEntity> entities = getMJAccountSeqInfo(tenant, resultDataSet, tenant.getTrustNo());
                    if (!CollectionUtils.isEmpty(entities)) {
                        mjAccountSeqInfoService.saveData(null, entities);
                    }
                    List<TgAccountSeqInfoEntity> tgAccountSeqInfoEntities = getTGAccountSeqInfo(tenant, resultDataSet, tenant.getTrustNo());
                    if (!CollectionUtils.isEmpty(tgAccountSeqInfoEntities)) {
                        tgAccountSeqInfoService.saveData(null, tgAccountSeqInfoEntities);
                    }
                }
                if (page * pageSize > totalCount) {
                    break;
                }
                page++;
            }
        } catch (Exception e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }

    private void getAccountInfoData(TenantEscrowAuthorizationInfoDto tenant, String bankAcco) {
        try {
            String url = swUrl + SWConstants.ACCOUNT_INFO_API_ONLINE;
            String params;
            int page = 1;
            int pageSize = 10000;
            List<JSONObject> resultDataSet;
            while (true) {
                //一分钟调一次
                if (page != 1) {
                    TimeUnit.MINUTES.sleep(30);
                }
                params = "{'bankAcco':'" + bankAcco + "','reqNum':'" + pageSize + "','reqPageno':'" + page + "'}";
                log.info("params:" + params);
                Map<String, Object> map = swhyUtils.call(url, params, tenant);
                if (!(Boolean) map.get("result")) {
                    break;
                }
                Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(map.get("data")), Map.class);
                Integer totalCount = Integer.valueOf(String.valueOf(dataMap.get("totalCount")));
                resultDataSet = JSONArray.parseArray(JSONObject.toJSONString(dataMap.get("result")), JSONObject.class);
                //封装成标准表的对象
                if (!CollectionUtils.isEmpty(resultDataSet)) {
                    List<AccountInfoEntity> accountEntities = getAccountInfo(tenant, resultDataSet, tenant.getTrustNo());
                    accountInfoService.saveData(null, accountEntities);
                    List<MjAccountBalanceInfoEntity> entities = getMJAccountBanlance(tenant, resultDataSet, tenant.getTrustNo());
                    mjAccountBalanceInfoService.saveData(null, entities);
                    List<TgAccountBalanceInfoEntity> tgAccountEntities = getTGAccountBanlance(tenant, resultDataSet, tenant.getTrustNo());
                    tgAccountBalanceInfoService.saveData(null, tgAccountEntities);
                }
                if (page * pageSize > totalCount) {
                    break;
                }
                page++;
            }
        } catch (Exception e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }

    public R updateSingleMgData(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("申万每10、16点更新募集户/托管户余额、流水数据开始~");
        String trustNo = "45";
        int loopTime = CustodyContants.UPDATE_BY_MONTH_DAILY_LOOP_TIME;
        try {
            //15 资金账户基本信息表 account_info，16 托管户银行账户余额信息表（TGAccount_balance_info,MJAccount_balance_info）
            processAccountInfoData(tenant, trustNo);//end
            //19 募集户流水表（MJAccount_seq_info）托管户流水表（TGAccount_seq_info）
            processAccountSeqInfoData(tenant, trustNo, loopTime);//end20211001-20211029
            List<String> bankAccoList = accountInfoService.getBankAcco(trustNo,tenant.getTenantName());
            if (!CollectionUtils.isEmpty(bankAccoList)) {
                for (String bankAcco : bankAccoList) {
                    if (StringUtils.isEmpty(bankAcco)) {
                        continue;
                    }
                    if (!bankAccoTaskQueue.contains(bankAcco)) {
                        bankAccoTaskQueue.put(bankAcco);
                    }
                }
            }
            List<String> mgBankAccoList = mjAccountSeqInfoService.getBankAccoList(trustNo,tenant.getTenantName());
            if (!CollectionUtils.isEmpty(mgBankAccoList)) {
                for (String mgBankAcco : mgBankAccoList) {
                    if (StringUtils.isEmpty(mgBankAcco)) {
                        continue;
                    }
                    if (!mgAccountTaskQueue.contains(mgBankAcco)) {
                        mgAccountTaskQueue.put(mgBankAcco);
                    }
                }
            }
            List<String> tgBankAccoList = tgAccountSeqInfoService.getBankAccoList(trustNo,tenant.getTenantName());
            if (!CollectionUtils.isEmpty(tgBankAccoList)) {
                for (String tgBankAcco : tgBankAccoList) {
                    if (StringUtils.isEmpty(tgBankAcco)) {
                        continue;
                    }
                    if (!mgAccountTaskQueue.contains(tgBankAcco)) {
                        mgAccountTaskQueue.put(tgBankAcco);
                    }
                }
            }
            log.info("申万每10、16点更新募集户/托管户余额、流水数据结束~");
        }catch (InterruptedException e){
            log.error("申万每10、16点更新募集户/托管户余额、流水数据异常！");
            e.getStackTrace();
            Thread.currentThread().interrupt();
        }
        return R.ok("申万每10、16点更新募集户/托管户余额、流水数据完成！");
    }

    public R updateSingleDataByAppointedScheduled(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("申万每30min更新开始");
        if (!mgAccountTaskQueue.isEmpty()) {
            String mgBankAcco = mgAccountTaskQueue.getFirst();
            if (!StringUtils.isEmpty(mgBankAcco)) {
                log.info("mgBankAcco:" + mgBankAcco);
                getMGAccountInfoData(tenant, mgBankAcco);
                mgAccountTaskQueue.remove(mgBankAcco);
            }
        }
        return null;
    }
}
