package com.friday.custody.service.trustService.htsc.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.friday.custody.service.trustService.htsc.common.HtscConstants;
import com.friday.custody.service.trustService.htsc.dto.*;
import com.friday.custody.dto.HtscAppSecretDTO;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.entity.InvokeRecordEntity;
import com.friday.custody.service.basicService.InvokeRecordService;
import com.friday.custody.service.basicService.impl.PullDataFailureLogServiceImpl;
import com.friday.custody.service.trustService.gtja.dto.HTSCCustShareDetailsDto;
import com.friday.custody.service.trustService.gtja.dto.HTSCFundProfitDto;
import com.friday.custody.service.trustService.gtja.dto.HTSCValuationFeeDto;
import com.friday.custody.service.trustService.zx.utils.SearchReturnClass;
import com.friday.custody.utils.PullDataFailureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

@Service("hTSCGetDataUtil")
@Slf4j
public class HTSCGetDataUtil {

    @Autowired
    InvokeRecordService invokeRecordService;
    @Autowired
    SearchReturnClass searchReturnClass;
    @Autowired
    PullDataFailureLogServiceImpl pullDataFailureLogService;
    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 调用及封装华泰2.1.1接口的数据
     *
     * @param tenant
     * @param trustNo
     * @param htscUrlPrefix
     * @param today
     * @return 返回的是以fundcode为key的map
     */
    public Map<String, Object> processPrdtInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today) throws IOException {
        String appSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(appSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(appSecret, HtscAppSecretDTO.class);
        //1 拼接请求数据
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("url", HtscConstants.PRDT_INFO_API);
        headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
        headerParamsMap.put("Timestamp", today);
        String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", today);
        headers.set("Sign", sign);
        //2 调用远端服务并处理远端请求结果
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.PRDT_INFO_API + "?appId=" + htscAppSecretDTO.getAppId(), headers);
        // 2.1 调用失败 将错误记录到错误记录表中
        if ((Integer) remoteResp.get("code") == 200) {
            saveInvokeRecord(tenant, trustNo, HtscConstants.PRDT_INFO_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processPrdtInfoData((List<Object>) remoteData, tenant.getTenantName());
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.PRDT_INFO_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp);
    }

    public void saveInvokeRecord(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String invokeType, HttpHeaders headers, Map<String, String> params, HashMap invokeResult) {
        Date now = new Date();
        InvokeRecordEntity invokeRecordEntity = InvokeRecordEntity.builder()
                .trustNo(trustNo)
                .admin(tenant.getTenantName())
                .invokeType(invokeType)
                .reqHeader(JSON.toJSONString(headers))
                .reqParam(JSON.toJSONString(params))
                .invokeTime(now)
                .invokeResult(JSON.toJSONString(invokeResult))
                .queryKey(tenant.getTenantName() + "::" + trustNo + "::" + invokeType)
                .createTime(now)
                .updateTime(now)
                .build();
        invokeRecordService.save(invokeRecordEntity);
    }

    public void saveInvokeRecord(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String invokeType, String headers, String params, HashMap invokeResult) {
        Date now = new Date();
        InvokeRecordEntity invokeRecordEntity = InvokeRecordEntity.builder()
                .trustNo(trustNo)
                .admin(tenant.getTenantName())
                .invokeType(invokeType)
                .reqHeader(JSON.toJSONString(headers))
                .reqParam(JSON.toJSONString(params))
                .invokeTime(now)
                .invokeResult(JSON.toJSONString(invokeResult))
                .queryKey(tenant.getTenantName() + "::" + trustNo + "::" + invokeType)
                .createTime(now)
                .updateTime(now)
                .build();
        invokeRecordService.save(invokeRecordEntity);
    }


    public void saveInvokeRecord(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String invokeType, String headers, String params, String invokeResult) {
        Date now = new Date();
        InvokeRecordEntity invokeRecordEntity = InvokeRecordEntity.builder()
                .trustNo(trustNo)
                .admin(tenant.getTenantName())
                .invokeType(invokeType)
                .reqHeader(JSON.toJSONString(headers))
                .reqParam(JSON.toJSONString(params))
                .invokeTime(now)
                .invokeResult(JSON.toJSONString(invokeResult))
                .queryKey(tenant.getTenantName() + "::" + trustNo + "::" + invokeType)
                .createTime(now)
                .updateTime(now)
                .build();
        invokeRecordService.save(invokeRecordEntity);
    }

    private Map<String, Object> processPrdtInfoData(List<Object> prdtInfos, String tenantName) {
        ArrayList<PrdtInfoDto> result = new ArrayList<>();
        PrdtInfoDto po;
        List<Map<String, Object>> prtList = searchReturnClass.queryPrtInfo(tenantName);
        for (Object item : prdtInfos) {
            po = JSON.parseObject(JSON.toJSONString(item), PrdtInfoDto.class);
            //获得数据中fundCode(fundRecordCode)为null. 则查询并补全
            if (StringUtils.isBlank(po.getFund_record_code())){
                if (prtList != null) {
                    for (Map<String, Object> prt : prtList) {
                        if ( prt.get("FUNDFULLNAME").equals(po.getFundname())) {
                            po.setFund_record_code(prt.get("REGCODE").toString());
                            break;
                        }
                    }
                }
            }
            result.add(po);
        }
        return result.stream().collect(Collectors.toMap(PrdtInfoDto::getFund_record_code, x -> x, (key1, key2) -> key2));
    }

    public Map<String, Object> processChildPrdtInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today) throws IOException {
        String appSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(appSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(appSecret, HtscAppSecretDTO.class);
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
        headerParamsMap.put("fundLevel", "2");
        headerParamsMap.put("Timestamp", today);
        headerParamsMap.put("url", HtscConstants.CHILD_PRDT_INFO_API);
        String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", today);
        headers.set("Sign", sign);
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.CHILD_PRDT_INFO_API + "?appId=" + htscAppSecretDTO.getAppId()
                + "&fundLevel=2", headers);

        // 2.1 调用失败 将错误记录到错误记录表中
        if ((Integer) remoteResp.get("code") == 200) {
            saveInvokeRecord(tenant, trustNo, HtscConstants.CHILD_PRDT_INFO_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processChildPrdtInfoData((List<Object>) remoteData);
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.CHILD_PRDT_INFO_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp);

    }

    private Map<String, Object> processChildPrdtInfoData(List<Object> childPrdtInfo) {
        ArrayList<ChildPrdtInfoDto> result = new ArrayList<>();
        ChildPrdtInfoDto po;
        for (Object item : childPrdtInfo) {
            if (item == null) continue;
            po = JSON.parseObject(JSON.toJSONString(item), ChildPrdtInfoDto.class);
            result.add(po);
        }
        Map<String, List<ChildPrdtInfoDto>> collect = result.stream().collect(Collectors.groupingBy(ChildPrdtInfoDto::getParentPrdtConvertCode));
        return collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));


    }

    public Map<String, Object> processFundValueData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix,
                                                    String today, String beginDate, String endDate, ReentrantLock lock) throws IOException {
        String appSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(appSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(appSecret, HtscAppSecretDTO.class);
        String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
        headerParamsMap.put("Timestamp", todayNew);
        headerParamsMap.put("beginDate", beginDate);
        headerParamsMap.put("endDate", endDate);
        headerParamsMap.put("url", HtscConstants.FUND_VALUE_API);
        String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", todayNew);
        headers.set("Sign", sign);
        String url = htscUrlPrefix + HtscConstants.FUND_VALUE_API + "?appId=" + htscAppSecretDTO.getAppId() + "&beginDate=" + beginDate + "&endDate=" + endDate;
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(url, headers, lock, 6000L, 60);

        // 2.1 调用失败 将错误记录到错误记录表中
        if (remoteResp != null && (Integer) remoteResp.get("code") == 200) {
            saveInvokeRecord(tenant, trustNo, HtscConstants.FUND_VALUE_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processFundValueData((List<Object>) remoteData);
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.FUND_VALUE_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp);
    }

    private Map<String, Object> processFundValueData(List<Object> fundValue) {
        ArrayList<FundValueDto> result = new ArrayList<>();
        FundValueDto po;
        for (Object item : fundValue) {
            if (item == null) continue;
            po = JSON.parseObject(JSON.toJSONString(item), FundValueDto.class);
            result.add(po);
        }
//        return result.stream().collect(Collectors.groupingBy(FundValueDto::getC_fundcode));
        Map<String, List<FundValueDto>> collect = result.stream().collect(Collectors.groupingBy(FundValueDto::getC_fundcode));
        return collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    public Map<String, Object> processInvestmentSubjects(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today) throws IOException {

        String appSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(appSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(appSecret, HtscAppSecretDTO.class);
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
        headerParamsMap.put("Timestamp", today);
        headerParamsMap.put("url", HtscConstants.INVESTMENT_SUBJECTS_API);
        String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", today);
        headers.set("Sign", sign);
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.INVESTMENT_SUBJECTS_API + "?appId=" + htscAppSecretDTO.getAppId(), headers);
        // 2.1 调用失败 将错误记录到错误记录表中
        if ((Integer) remoteResp.get("code") == 200) {
            saveInvokeRecord(tenant, trustNo, HtscConstants.INVESTMENT_SUBJECTS_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processInvestmentSubjectsData((List<Object>) remoteData);
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.INVESTMENT_SUBJECTS_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp);

    }

    private Map<String, Object> processInvestmentSubjectsData(List<Object> investmentSubjects) {

        ArrayList<InvestmentSubjectsDto> result = new ArrayList<>();
        InvestmentSubjectsDto po;
        for (Object item : investmentSubjects) {
            if (item == null) continue;
            log.info("processInvestmentSubjectsData is {}", JSON.toJSONString(item));
            po = JSON.parseObject(JSON.toJSONString(item), InvestmentSubjectsDto.class);
            result.add(po);
        }
        return result.stream().collect(Collectors.toMap(InvestmentSubjectsDto::getC_fundacco, x -> x));
    }

    public Map<String, Object> processCustSharesData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today) throws IOException {
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appId = htscAppSecretDTO.getAppId();
        String appSecret = htscAppSecretDTO.getAppSecret();
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("appid", appId);
        headerParamsMap.put("Timestamp", today);
        headerParamsMap.put("url", HtscConstants.CUST_SHARES_API);
        String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", today);
        headers.set("Sign", sign);
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.CUST_SHARES_API + "?appId=" + appId, headers);

        // 2.1 调用失败 将错误记录到错误记录表中
        if ((Integer) remoteResp.get("code") == 200) {
            saveInvokeRecord(tenant, trustNo, HtscConstants.CUST_SHARES_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processCustSharesData((List<Object>) remoteData);
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.CUST_SHARES_API, headers, "appId=" + appId, remoteResp);


    }

    private Map<String, Object> processCustSharesData(List<Object> remoteData) {
        ArrayList<CustSharesDto> result = new ArrayList<>();
        CustSharesDto po;
        for (Object item : remoteData) {
            if (item == null) continue;
            po = JSON.parseObject(JSON.toJSONString(item), CustSharesDto.class);
            result.add(po);
        }
        Map<String, List<CustSharesDto>> collect = result.stream().collect(Collectors.groupingBy(CustSharesDto::getC_fundcode));
        return collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    public List<BalanceAccountDto2> processTGAccountBalanceInfoData(TenantEscrowAuthorizationInfoDto tenant, List<BalanceAccountDto2> accounts, String trustNo, String htscUrlPrefix, String today, ReentrantLock lock) throws IOException {
        //1 先按照银行账户查
        //2 再按照页码
        String appSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(appSecret)){
            return new ArrayList<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(appSecret, HtscAppSecretDTO.class);
        List<BalanceAccountDto2> result = new ArrayList<>();
        for (BalanceAccountDto2 account : accounts) {
            int pageNo = 1;
            for (; ; ) {
                String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("account", account.getAccount());
                headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
                headerParamsMap.put("fundCode", account.getFundCode());
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "50");
                headerParamsMap.put("Timestamp", todayNew);
                headerParamsMap.put("url", HtscConstants.TG_BALANCE_ACCOUNT_API);
                String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", todayNew);
                headers.set("Sign", sign);
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.TG_BALANCE_ACCOUNT_API + "?account="
                        + account.getAccount() + "&appId=" + htscAppSecretDTO.getAppId() + "&fundCode=" + account.getFundCode() + "&pageNo=" + pageNo++ + "&pageSize=50", headers, lock, 6000L, 60);

                // 2.1 调用失败 将错误记录到错误记录表中
                if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.TG_BALANCE_ACCOUNT_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp));
                    break;
                }
                saveInvokeRecord(tenant, trustNo, HtscConstants.TG_BALANCE_ACCOUNT_API, headers, headerParamsMap, remoteResp);
                Object remoteData = remoteResp.get("data");
                if (!processTGBalanceAccountData(remoteData, result)) {
                    break;
                }
            }
        }
        return result;
    }

    private boolean processTGBalanceAccountData(Object remoteData, List<BalanceAccountDto2> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        BalanceAccountDto dto = JSON.parseObject(JSON.toJSONString(remoteData), BalanceAccountDto.class);
        List<BalanceAccountDto2> list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (BalanceAccountDto2 item : list) {
            if (item == null) continue;
            result.add(item);
        }
        return true;
    }


    public Map<String, List<BalanceAccountDto2>> processAccountInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today, ReentrantLock lock) throws IOException {
        //这个接口需要传分页参数  则需要进入循环   直到当页无数据
        // key fundcode value 返回值
        Map<String, List<BalanceAccountDto2>> result = new HashMap<>();
        getAccountInfoResult(result, tenant, trustNo, htscUrlPrefix, today, "ZJ001", lock);
        getAccountInfoResult(result, tenant, trustNo, htscUrlPrefix, today, "ZJ002", lock);
        return result;
    }

    private void getAccountInfoResult(Map<String, List<BalanceAccountDto2>> result, TenantEscrowAuthorizationInfoDto tenant,
                                      String trustNo, String htscUrlPrefix, String today, String accountTypeCode, ReentrantLock lock) throws IOException {
        String appSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(appSecret)){
            return;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(appSecret, HtscAppSecretDTO.class);
        int pageNo = 1;
        for (; ; ) {
            String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
            Map<String, String> headerParamsMap = new HashMap<>();
            headerParamsMap.put("accountTypeCode", accountTypeCode);
            headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
            headerParamsMap.put("pageNo", pageNo + "");
            headerParamsMap.put("pageSize", "100");
            headerParamsMap.put("Timestamp", todayNew);
            headerParamsMap.put("url", HtscConstants.BALANCE_ACCOUNT_API);
            String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Timestamp", todayNew);
            headers.set("Sign", sign);
            HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.BALANCE_ACCOUNT_API + "?accountTypeCode="
                    + accountTypeCode + "&appId=" + htscAppSecretDTO.getAppId() + "&pageNo=" + pageNo++ + "&pageSize=100", headers, lock, 6000L, 60);

            // 2.1 调用失败 将错误记录到错误记录表中
            if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.BALANCE_ACCOUNT_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp));
                break;
            }
            saveInvokeRecord(tenant, trustNo, HtscConstants.BALANCE_ACCOUNT_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!processBalanceAccountData(remoteData, result)) {
                break;
            }

        }
    }

    private boolean processBalanceAccountData(Object remoteData, Map<String, List<BalanceAccountDto2>> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        ArrayList<BalanceAccountDto2> singleResult = new ArrayList<>();
        BalanceAccountDto dto = JSON.parseObject(JSON.toJSONString(remoteData), BalanceAccountDto.class);
        List<BalanceAccountDto2> list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (BalanceAccountDto2 item : list) {
            if (item == null) continue;
            singleResult.add(item);
        }
        Map<String, List<BalanceAccountDto2>> collect = singleResult.stream().collect(Collectors.groupingBy(BalanceAccountDto2::getFundName));
//        collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        collect.forEach((key, value) -> {
            List<BalanceAccountDto2> balanceAccountDto2s = result.get(key);
            if (Objects.isNull(balanceAccountDto2s)) {
                balanceAccountDto2s = new ArrayList<>();
                result.put(key, balanceAccountDto2s);
            }
            balanceAccountDto2s.addAll(value);
        });
        return true;
    }

    public List<BalanceAccountDto2> processMJAccountBalanceInfoData(TenantEscrowAuthorizationInfoDto tenant, List<BalanceAccountDto2> accounts, String trustNo, String htscUrlPrefix, String today) throws IOException {
        //1 先按照银行账户查
        //2 再按照页码
        String appSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(appSecret)){
            return new ArrayList<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(appSecret, HtscAppSecretDTO.class);
        ReentrantLock lock = new ReentrantLock();
        List<BalanceAccountDto2> result = new ArrayList<>();
        for (BalanceAccountDto2 account : accounts) {
            int pageNo = 1;
            for (; ; ) {
                String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("account", account.getAccount());
                headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
                //fundCode为空时，传fundName
                if (StringUtils.isNotBlank(account.getFundCode())) {
                    headerParamsMap.put("fundCode", account.getFundCode());
                } else {
                    headerParamsMap.put("fundName", account.getFundName());
                }
                headerParamsMap.put("fundCode", account.getFundCode());
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "50");
                headerParamsMap.put("Timestamp", todayNew);
                headerParamsMap.put("url", HtscConstants.MJ_BALANCE_ACCOUNT_API);
                String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", todayNew);
                headers.set("Sign", sign);
                //fundCode为空时，传fundName
                String codeOrNameParam = "&fundCode=" + account.getFundCode();
                if (StringUtils.isBlank(account.getFundCode())) {
                    codeOrNameParam = "&fundName=" + account.getFundName();
                }
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.MJ_BALANCE_ACCOUNT_API + "?account="
                        + account.getAccount() + "&appId=" + htscAppSecretDTO.getAppId() + codeOrNameParam + "&pageNo=" + pageNo++ + "&pageSize=50", headers, lock, 6000L, 60);

                // 2.1 调用失败 将错误记录到错误记录表中
                if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.MJ_BALANCE_ACCOUNT_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp));
                    break;
                }
                //保存调用成功日志
                saveInvokeRecord(tenant, trustNo, HtscConstants.MJ_BALANCE_ACCOUNT_API, headers, headerParamsMap, remoteResp);
                Object remoteData = remoteResp.get("data");
                if (!processMJBalanceAccountData(remoteData, result)) {
                    break;
                }
            }
        }
        return result;
    }

    private boolean processMJBalanceAccountData(Object remoteData, List<BalanceAccountDto2> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        BalanceAccountDto dto = JSON.parseObject(JSON.toJSONString(remoteData), BalanceAccountDto.class);
        List<BalanceAccountDto2> list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (BalanceAccountDto2 item : list) {
            if (item == null) continue;
            result.add(item);
        }
        return true;
    }

    public List<AccountCurrentDetailDto2> processTGAccountCurrentDetailData(TenantEscrowAuthorizationInfoDto tenant, List<BalanceAccountDto2> accounts, String trustNo, String htscUrlPrefix, String today) {
        List<AccountCurrentDetailDto2> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return new ArrayList<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = new HtscAppSecretDTO();
        try {
             htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        } catch (IOException e) {
            log.error("解析账密失败{}!{}", htscAppSecretDTO, e);
        }
        //1 先按照银行账户查
        ReentrantLock lock = new ReentrantLock();
        for (BalanceAccountDto2 account : accounts) {
            //2 再按照页码
            int pageNo = 1;
            for (; ; ) {
                String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("account", account.getAccount());
                headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
                headerParamsMap.put("fundCode", account.getFundCode());
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "200");
                headerParamsMap.put("Timestamp", todayNew);
                headerParamsMap.put("url", HtscConstants.TG_ACCOUNT_CURRENT_DETAIL_API);
                String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", todayNew);
                headers.set("Sign", sign);
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.TG_ACCOUNT_CURRENT_DETAIL_API + "?account="
                        + account.getAccount() + "&appId=" + htscAppSecretDTO.getAppId() + "&fundCode=" + account.getFundCode() + "&pageNo=" + pageNo++ + "&pageSize=200", headers, lock, 6000L, 60);
                // 2.1 调用失败 将错误记录到错误记录表中
                if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.TG_ACCOUNT_CURRENT_DETAIL_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp));
                    break;
                }
                saveInvokeRecord(tenant, trustNo, HtscConstants.TG_ACCOUNT_CURRENT_DETAIL_API, headers, headerParamsMap, remoteResp);
                Object remoteData = remoteResp.get("data");
                if (!processTGAccountCurrentDetailData(remoteData, result)) {
                    break;
                }
            }
        }
        return result;

    }

    private boolean processTGAccountCurrentDetailData(Object remoteData, List<AccountCurrentDetailDto2> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        AccountCurrentDetailDto dto = JSON.parseObject(JSON.toJSONString(remoteData), AccountCurrentDetailDto.class);
        List<AccountCurrentDetailDto2> list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (AccountCurrentDetailDto2 item : list) {
            if (item == null) continue;
            result.add(item);
        }
        return true;

    }


    public List<AccountCurrentDetailDto2> processHistoryTgAccountBalanceInfoData(TenantEscrowAuthorizationInfoDto tenant,
                                                                                 List<BalanceAccountDto2> accounts, String trustNo,
                                                                                 String htscUrlPrefix, String today, Integer loopNum,
                                                                                 String finalStartDate, String finalEndDate, ReentrantLock lock) {

        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return new ArrayList<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = new HtscAppSecretDTO();
        try {
            htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        } catch (IOException e) {
            log.error("解析账密失败{}!{}", htscAppSecretDTO, e);
        }
        String appId = htscAppSecretDTO.getAppId();
        String appSecret = htscAppSecretDTO.getAppSecret();
        List<AccountCurrentDetailDto2> result = new ArrayList<>();
        //1 先按照银行账户查
        for (BalanceAccountDto2 account : accounts) {
            //2 再按照页码
            int pageNo = 1;
            for (; ; ) {
                String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("account", account.getAccount());
                headerParamsMap.put("appid", appId);
                headerParamsMap.put("beginDate", finalStartDate);
                headerParamsMap.put("endDate", finalEndDate);
                headerParamsMap.put("fundCode", account.getFundCode());
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "200");
                headerParamsMap.put("Timestamp", todayNew);
                headerParamsMap.put("url", HtscConstants.TG_ACCOUNT_HISTORY_DETAIL_API);
                String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", todayNew);
                headers.set("Sign", sign);
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.TG_ACCOUNT_HISTORY_DETAIL_API + "?account="
                        + account.getAccount() + "&appId=" + appId + "&beginDate=" + finalStartDate + "&endDate=" + finalEndDate
                        + "&fundCode=" + account.getFundCode() + "&pageNo=" + pageNo++ + "&pageSize=200", headers, lock, 6000L, 60);

                // 2.1 调用失败 将错误记录到错误记录表中
                if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.TG_ACCOUNT_HISTORY_DETAIL_API, headers, "appId=" + appId, remoteResp));
                    break;
                }
                saveInvokeRecord(tenant, trustNo, HtscConstants.TG_ACCOUNT_HISTORY_DETAIL_API, headers, headerParamsMap, remoteResp);
                Object remoteData = remoteResp.get("data");
                if (!processTGAccountCurrentDetailData(remoteData, result)) {
                    break;
                }
            }
        }
        return result;

    }

    public List<AccountCurrentDetailDto2> processMJAccountCurrentDetailData(TenantEscrowAuthorizationInfoDto tenant,
                                                                            List<BalanceAccountDto2> accounts, String trustNo,
                                                                            String htscUrlPrefix, String today) throws IOException {
        List<AccountCurrentDetailDto2> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        ReentrantLock lock = new ReentrantLock();
        //1 先按照银行账户查
        for (BalanceAccountDto2 account : accounts) {
            //2 再按照页码
            int pageNo = 1;
            for (; ; ) {
                String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("account", account.getAccount());
                headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
                //如果fundCode为空  传fundName
                if (StringUtils.isNotBlank(account.getFundCode())) {
                    headerParamsMap.put("fundCode", account.getFundCode());
                } else {
                    headerParamsMap.put("fundName", account.getFundName());
                }
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "200");
                headerParamsMap.put("Timestamp", todayNew);
                headerParamsMap.put("url", HtscConstants.MJ_ACCOUNT_CURRENT_DETAIL_API);
                String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", todayNew);
                headers.set("Sign", sign);
                //如果fundCode为空  传fundName
                String codeOrNamentParam = "&fundCode=" + account.getFundCode();
                if (StringUtils.isBlank(account.getFundCode())) {
                    codeOrNamentParam = "&fundName=" + account.getFundName();
                }
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.MJ_ACCOUNT_CURRENT_DETAIL_API + "?account="
                        + account.getAccount() + "&appId=" + htscAppSecretDTO.getAppId() + codeOrNamentParam + "&pageNo=" + pageNo++ + "&pageSize=200", headers, lock, 6000L, 60);


                // 2.1 调用失败 将错误记录到错误记录表中
                if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.MJ_ACCOUNT_CURRENT_DETAIL_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp));
                    break;
                }
                saveInvokeRecord(tenant, trustNo, HtscConstants.MJ_ACCOUNT_CURRENT_DETAIL_API, headers, headerParamsMap, remoteResp);
                Object remoteData = remoteResp.get("data");
                if (!processMJAccountCurrentDetailData(remoteData, result)) {
                    break;
                }
            }
        }
        return result;


    }

    private boolean processMJAccountCurrentDetailData(Object remoteData, List<AccountCurrentDetailDto2> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        AccountCurrentDetailDto dto = JSON.parseObject(JSON.toJSONString(remoteData), AccountCurrentDetailDto.class);
        List<AccountCurrentDetailDto2> list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (AccountCurrentDetailDto2 item : list) {
            if (item == null) continue;
            result.add(item);
        }
        return true;
    }

    public List<AccountCurrentDetailDto2> processHistoryMJAccountBalanceInfoData(TenantEscrowAuthorizationInfoDto tenant, List<BalanceAccountDto2> accounts, String trustNo, String htscUrlPrefix, String today, Integer loopNum, String finalStartDate, String finalEndDate, ReentrantLock lock) throws IOException {

        List<AccountCurrentDetailDto2> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        //1 先按照银行账户查
        for (BalanceAccountDto2 account : accounts) {
            //2 再按照页码
            int pageNo = 1;
            for (; ; ) {
                String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("account", account.getAccount());
                headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
                headerParamsMap.put("beginDate", finalStartDate);
                headerParamsMap.put("endDate", finalEndDate);
                //fundCode为空，传fundName
                if (StringUtils.isNotBlank(account.getFundCode())) {
                    headerParamsMap.put("fundCode", account.getFundCode());
                } else {
                    headerParamsMap.put("fundName", account.getFundName());
                }
                headerParamsMap.put("fundCode", account.getFundCode());
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "200");
                headerParamsMap.put("Timestamp", todayNew);
                headerParamsMap.put("url", HtscConstants.MJ_ACCOUNT_HISTORY_DETAIL_API);
                String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", todayNew);
                headers.set("Sign", sign);
                //fundCode 为空 传fundName
                String codeOrNameParam = "&fundCode=" + account.getFundCode();
                if (StringUtils.isBlank(account.getFundCode())) {
                    codeOrNameParam = "&fundName=" + account.getFundName();
                }
                log.info("单个募集户历史流水查询 参数开始时间：{}，结束时间:{}",finalStartDate,finalEndDate);
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.MJ_ACCOUNT_HISTORY_DETAIL_API + "?account="
                        + account.getAccount() + "&appId=" + htscAppSecretDTO.getAppId() + "&beginDate=" + finalStartDate + "&endDate=" + finalEndDate
                        + codeOrNameParam + "&pageNo=" + pageNo++ + "&pageSize=200", headers, lock, 6000L, 60);
                saveInvokeRecord(tenant, trustNo, HtscConstants.MJ_ACCOUNT_HISTORY_DETAIL_API, headers, headerParamsMap, remoteResp);

                // 2.1 调用失败 将错误记录到错误记录表中
                if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.MJ_ACCOUNT_HISTORY_DETAIL_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp));
                    break;
                }
                Object remoteData = remoteResp.get("data");
                if (!processMJAccountCurrentDetailData(remoteData, result)) {
                    break;
                }

            }
        }
        return result;

    }

    public Map<String, Object> processInvestTradeCfmDetailData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today, String finalStartDate, String finalEndDate, ReentrantLock lock) throws IOException {

        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
        headerParamsMap.put("Timestamp", todayNew);
        headerParamsMap.put("beginDate", finalStartDate);
        headerParamsMap.put("endDate", finalEndDate);
        headerParamsMap.put("url", HtscConstants.INVEST_TRADE_CFM_DETAIL_API);
        String sign = HTSCSignGenerator.genSign(htscAppSecretDTO.getAppSecret(), headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", todayNew);
        headers.set("Sign", sign);
        String url = htscUrlPrefix + HtscConstants.INVEST_TRADE_CFM_DETAIL_API + "?appId=" + htscAppSecretDTO.getAppId() + "&beginDate=" + finalStartDate + "&endDate=" + finalEndDate;
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(url, headers, lock, 6000L, 60);

        if (remoteResp != null && (Integer) remoteResp.get("code") == 200) {
            saveInvokeRecord(tenant, trustNo, HtscConstants.INVEST_TRADE_CFM_DETAIL_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processInvestTradeCfmDetailData((List<Object>) remoteData);
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.INVEST_TRADE_CFM_DETAIL_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp);
    }

    private Map<String, Object> processInvestTradeCfmDetailData(List<Object> remoteData) {
        ArrayList<InvestTradeCfmDetailDto> result = new ArrayList<>();
        InvestTradeCfmDetailDto po;
        for (Object item : remoteData) {
            if (item == null) continue;
            po = JSON.parseObject(JSON.toJSONString(item), InvestTradeCfmDetailDto.class);
            result.add(po);
        }
        Map<String, List<InvestTradeCfmDetailDto>> collect = result.stream().collect(Collectors.groupingBy(InvestTradeCfmDetailDto::getC_fundcode));
        return collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    public List<FeePayDetailDto> processFeePayDetailData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today, Integer loopNum, String finalStartDate, String finalEndDate) {
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return new ArrayList<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = new HtscAppSecretDTO();
        String appId = htscAppSecretDTO.getAppId();
        String appSecret = htscAppSecretDTO.getAppSecret();
        List<FeePayDetailDto> result = new ArrayList<>();
        //1 先按照银行账户查
        //2 再按照页码
        int pageNo = 1;
        for (; ; ) {
            Map<String, String> headerParamsMap = new HashMap<>();
            headerParamsMap.put("appid", appId);
            headerParamsMap.put("beginDate", finalStartDate);
            headerParamsMap.put("endDate", finalEndDate);
            headerParamsMap.put("pageNo", pageNo + "");
            headerParamsMap.put("pageSize", "200");
            headerParamsMap.put("Timestamp", today);
            headerParamsMap.put("url", HtscConstants.FEE_PAY_DETAIL_API);
            String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Timestamp", today);
            headers.set("Sign", sign);
            HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.FEE_PAY_DETAIL_API + "?appId=" + appId + "&beginDate=" + finalStartDate + "&endDate=" + finalEndDate + "&pageNo=" + pageNo++ + "&pageSize=200", headers);
            saveInvokeRecord(tenant, trustNo, HtscConstants.FEE_PAY_DETAIL_API, headers, headerParamsMap, remoteResp);

            // 2.1 调用失败 将错误记录到错误记录表中
            if ((Integer) remoteResp.get("code") != 200) {
                break;
            }
            Object remoteData = remoteResp.get("data");
            if (!processFeePayDetailData(remoteData, result)) {
                break;
            }
            try {
                Thread.sleep(60000L);
            } catch (InterruptedException e) {
                log.error("睡眠的线程被打断了");
                Thread.currentThread().interrupt();
            }
        }
        return result;


    }

    private boolean processFeePayDetailData(Object remoteData, List<FeePayDetailDto> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        HTSCQueryPageDto dto = JSON.parseObject(JSON.toJSONString(remoteData), HTSCQueryPageDto.class);
        List list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (Object item : list) {
            if (item == null) continue;
            result.add(JSON.parseObject(JSON.toJSONString(item), FeePayDetailDto.class));
        }
        return true;
    }

    public List<ValuationDetailDto> processFundValueTableDataInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today,
                                                                      String finalCurDay, ReentrantLock lock) throws IOException {
        int pageNo = 1;
        List<ValuationDetailDto> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        for (; ; ) {
            String todayNew = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
            Map<String, String> headerParamsMap = new HashMap<>();
            headerParamsMap.put("appid", htscAppSecretDTO.getAppId());
            headerParamsMap.put("pageNo", pageNo + "");
            headerParamsMap.put("pageSize", "200");
            headerParamsMap.put("Timestamp", todayNew);
            headerParamsMap.put("url", HtscConstants.VALUATION_DETAIL_API);
            headerParamsMap.put("valueDate", finalCurDay);
            String appSecret = htscAppSecretDTO.getAppSecret();
            String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Timestamp", todayNew);
            headers.set("Sign", sign);
            HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.VALUATION_DETAIL_API + "?appId=" + htscAppSecretDTO.getAppId() + "&pageNo=" + pageNo++ + "&pageSize=200"
                    + "&valueDate=" + finalCurDay, headers, lock, 6000L, 60);

            // 2.1 调用失败 将错误记录到错误记录表中
            if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.VALUATION_DETAIL_API, headers, "appId=" + htscAppSecretDTO.getAppId(), remoteResp));
                break;
            }
            saveInvokeRecord(tenant, trustNo, HtscConstants.VALUATION_DETAIL_API, headers, headerParamsMap, remoteResp);
            log.info("VALUATION_DETAIL_API有值了...the finalCurDay is {},the remoteResp is {}", finalCurDay, JSON.toJSONString(remoteResp));
            Object remoteData = remoteResp.get("data");
            if (!processFundValueTableDataInfoData(remoteData, result)) {
                break;
            }
        }
        return result;
    }

    private boolean processFundValueTableDataInfoData(Object remoteData, List<ValuationDetailDto> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        HTSCQueryPageDto dto = JSON.parseObject(JSON.toJSONString(remoteData), HTSCQueryPageDto.class);
        List list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (Object item : list) {
            if (item == null) continue;
            //todo 转换失败
            log.info("VALUATION_DETAIL_API有值了...the item is {}", JSON.toJSONString(item));
            result.add(JSON.parseObject(JSON.toJSONString(item), ValuationDetailDto.class));
        }
        return true;

    }

    public Map<String, Object> processInvestorBankInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String today) throws IOException {
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appSecret = htscAppSecretDTO.getAppSecret();
        String appId = htscAppSecretDTO.getAppId();
        //1 拼接请求数据
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("appid", appId);
        headerParamsMap.put("Timestamp", today);
        headerParamsMap.put("url", HtscConstants.BANK_ACCOUNT_INFO_API);
        String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", today);
        headers.set("Sign", sign);
        //2 调用远端服务并处理远端请求结果
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.BANK_ACCOUNT_INFO_API + "?appId=" + appId, headers);
        saveInvokeRecord(tenant, trustNo, HtscConstants.BANK_ACCOUNT_INFO_API, headers, headerParamsMap, remoteResp);
        // 2.1 调用失败 将错误记录到错误记录表中
        if ((Integer) remoteResp.get("code") == 200) {
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processInvestorBankInfoData((List<Object>) remoteData);
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.BANK_ACCOUNT_INFO_API, headers, "appId=" + appId, remoteResp);
    }

    private Map<String, Object> processInvestorBankInfoData(List<Object> remoteData) {
        ArrayList<InvestorBankInfoDto> result = new ArrayList<>();
        InvestorBankInfoDto po;
        for (Object item : remoteData) {
            po = JSON.parseObject(JSON.toJSONString(item), InvestorBankInfoDto.class);
            result.add(po);
        }
        return result.stream().collect(Collectors.toMap(InvestorBankInfoDto::getC_bankacco, x -> x, (key1, key2) -> key2));

    }

    public List<HTSCFundProfitDto> processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String startDay, String endDay) throws IOException {
        int pageNo = 1;
        List<HTSCFundProfitDto> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appSecret = htscAppSecretDTO.getAppSecret();
        String appId = htscAppSecretDTO.getAppId();
        String today;
        for (; ; ) {
            try {

                TimeUnit.SECONDS.sleep(6L);
            } catch (Exception e) {
                log.error("睡眠的线程被打断了...", e);
                Thread.currentThread().interrupt();
            }
            today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
            Map<String, String> headerParamsMap = new HashMap<>();
            headerParamsMap.put("appid", appId);
            headerParamsMap.put("pageNo", pageNo + "");
            headerParamsMap.put("pageSize", "200");
            headerParamsMap.put("Timestamp", today);
            headerParamsMap.put("url", HtscConstants.FUND_PROFIT_API);
            headerParamsMap.put("confBeginDate", startDay);
            headerParamsMap.put("confEndDate", endDay);
            String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Timestamp", today);
            headers.set("Sign", sign);
            HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.FUND_PROFIT_API + "?appId=" + appId + "&pageNo=" + pageNo++ + "&pageSize=200"
                    + "&confBeginDate=" + startDay + "&confEndDate=" + endDay, headers);

            // 2.1 调用失败 将错误记录到错误记录表中
            if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.FUND_PROFIT_API, headers, "appId=" + appId, remoteResp));
                break;
            }
            log.info("FUND_PROFIT_API有值了...the confBeginDate is {},the confEndDate is {},the remoteResp is {}", startDay, endDay, JSON.toJSONString(remoteResp));
            saveInvokeRecord(tenant, trustNo, HtscConstants.FUND_PROFIT_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!processFundProfitInfoData(remoteData, result)) {
                break;
            }
        }
        return result;

    }

    private boolean processFundProfitInfoData(Object remoteData, List<HTSCFundProfitDto> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        HTSCQueryPageDto dto = JSON.parseObject(JSON.toJSONString(remoteData), HTSCQueryPageDto.class);
        List list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (Object item : list) {
            if (item == null) continue;
            //todo 转换失败
            log.info("FUND_PROFIT_API有值了...the item is {}", JSON.toJSONString(item));
            result.add(JSON.parseObject(JSON.toJSONString(item), HTSCFundProfitDto.class));
        }
        return true;
    }

    public List<HTSCCustShareDetailsDto> processCustShareDetailInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix) throws IOException {

        int pageNo = 1;
        List<HTSCCustShareDetailsDto> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appSecret = htscAppSecretDTO.getAppSecret();
        String appId = htscAppSecretDTO.getAppId();
        String today;
        for (; ; ) {
            try {
                TimeUnit.SECONDS.sleep(6L);
            } catch (Exception e) {
                log.error("睡眠的线程被打断了...", e);
                Thread.currentThread().interrupt();
            }
            today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
            Map<String, String> headerParamsMap = new HashMap<>();
            headerParamsMap.put("appid", appId);
            headerParamsMap.put("pageNo", pageNo + "");
            headerParamsMap.put("pageSize", "200");
            headerParamsMap.put("Timestamp", today);
            headerParamsMap.put("url", HtscConstants.CUST_SHARE_DETAILS_API);
            String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Timestamp", today);
            headers.set("Sign", sign);
            HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.CUST_SHARE_DETAILS_API + "?appId=" + appId + "&pageNo=" + pageNo++ + "&pageSize=200", headers);
            // 2.1 调用失败 将错误记录到错误记录表中
            if (remoteResp == null || (Integer) remoteResp.get("code") != 200) {
                pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.CUST_SHARE_DETAILS_API, headers, "appId=" + appId, remoteResp));
                break;
            }
            saveInvokeRecord(tenant, trustNo, HtscConstants.CUST_SHARE_DETAILS_API, headers, headerParamsMap, remoteResp);
            log.info("CUST_SHARE_DETAILS_API 有值了...the remoteResp is {}", JSON.toJSONString(remoteResp));
            Object remoteData = remoteResp.get("data");
            if (!processCustShareDetailInfoData(remoteData, result)) {
                break;
            }
        }
        return result;
    }

    private boolean processCustShareDetailInfoData(Object remoteData, List<HTSCCustShareDetailsDto> result) {
        //如果没有值 返回false
        if (Objects.isNull(remoteData)) {
            return false;
        }
        HTSCQueryPageDto dto = JSON.parseObject(JSON.toJSONString(remoteData), HTSCQueryPageDto.class);
        List list = dto.getList();
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        for (Object item : list) {
            if (item == null) continue;
            //todo 转换失败
            log.info("CUST_SHARE_DETAILS_API 有值了...the item is {}", JSON.toJSONString(item));
            result.add(JSON.parseObject(JSON.toJSONString(item), HTSCCustShareDetailsDto.class));
        }
        return true;
    }

    public Map<String, Object> processFundTempFareInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String startDay, String endDay) throws IOException {
        String today;
        try {
            TimeUnit.SECONDS.sleep(3L);
        } catch (Exception e) {
            log.error("睡眠的线程被打断了...", e);
            Thread.currentThread().interrupt();
        }
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return new HashMap<>();
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appSecret = htscAppSecretDTO.getAppSecret();
        String appId = htscAppSecretDTO.getAppId();
        today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
        Map<String, String> headerParamsMap = new HashMap<>();
        headerParamsMap.put("appid", appId);
        headerParamsMap.put("Timestamp", today);
        headerParamsMap.put("beginDate", startDay);
        headerParamsMap.put("endDate", endDay);
        headerParamsMap.put("url", HtscConstants.VALUATION_FEE_API);
        String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Timestamp", today);
        headers.set("Sign", sign);
        String url = htscUrlPrefix + HtscConstants.VALUATION_FEE_API + "?appId=" + appId + "&beginDate=" + startDay + "&endDate=" + endDay;
        HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(url, headers);

        if (remoteResp != null && (Integer) remoteResp.get("code") == 200) {
            saveInvokeRecord(tenant, trustNo, HtscConstants.VALUATION_FEE_API, headers, headerParamsMap, remoteResp);
            Object remoteData = remoteResp.get("data");
            if (!Objects.isNull(remoteData) && remoteData instanceof List) {
                return processFundTempFareInfoData((List<Object>) remoteData);
            }
        }
        return PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.VALUATION_FEE_API, headers, "appId=" + appId, remoteResp);

    }

    private Map<String, Object> processFundTempFareInfoData(List<Object> remoteData) {

        ArrayList<HTSCValuationFeeDto> result = new ArrayList<>();
        HTSCValuationFeeDto po;
        for (Object item : remoteData) {
            if (item == null) continue;
            po = JSON.parseObject(JSON.toJSONString(item), HTSCValuationFeeDto.class);
            result.add(po);
        }
        Map<String, List<HTSCValuationFeeDto>> collect = result.stream().collect(Collectors.groupingBy(HTSCValuationFeeDto::getC_fundcode));
        return collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));


    }

    public List<JSONObject> processChargeFeeDetailInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String startDay, String endDay) throws IOException {
        int pageNo = 1;
        String today;
        List<JSONObject> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appSecret = htscAppSecretDTO.getAppSecret();
        String appId = htscAppSecretDTO.getAppId();
        for (; ; ) {
            try {
                TimeUnit.SECONDS.sleep(6L);
            } catch (Exception e) {
                log.error("睡眠的线程被打断了...", e);
                Thread.currentThread().interrupt();
            }
            try {
                today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("appid", appId);
                headerParamsMap.put("beginDate", startDay);
                headerParamsMap.put("endDate", endDay);
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "200");
                headerParamsMap.put("Timestamp", today);
                headerParamsMap.put("url", HtscConstants.CHARGE_FEE_DETAIL_INFO_API);
                String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", today);
                headers.set("Sign", sign);
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.CHARGE_FEE_DETAIL_INFO_API + "?appId=" + appId + "&beginDate=" + startDay + "&endDate=" + endDay + "&pageNo=" + pageNo + "&pageSize=200", headers);


                int totalPages = 0;
                // 调用失败保存错误信息
                if (remoteResp != null && (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.CHARGE_FEE_DETAIL_INFO_API, headers, "appId=" + appId, remoteResp));
                    break;
                }
                saveInvokeRecord(tenant, trustNo, HtscConstants.CHARGE_FEE_DETAIL_INFO_API, headers, headerParamsMap, remoteResp);
                log.info("chargeFeeDetailInfo有值了...the beginDate is {},the endDate is {},the remoteResp is {}", startDay, endDay, JSON.toJSONString(remoteResp));
                if (remoteResp != null && remoteResp.containsKey("data")) {
                    JSONObject remoteData = (JSONObject) remoteResp.get("data");
                    if (!ObjectUtils.isEmpty(remoteData)) {
                        List<JSONObject> remoteDataList = JSONObject.parseArray(remoteData.get("list").toString(), JSONObject.class);
                        result.addAll(remoteDataList);
                        totalPages = Integer.parseInt(remoteData.get("totalPages").toString());
                    }
                }
                pageNo++;
                if (pageNo > totalPages){
                    break;
                }
            } catch (Exception e) {
                log.info("调用华泰接口查询chargeFeeDetailInfo失败！", e);
            }
        }
        return result;
    }

    public List<JSONObject> processPayFeeDetailInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String startDay, String endDay) throws IOException {
        int pageNo = 1;
        String today;
        List<JSONObject> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appSecret = htscAppSecretDTO.getAppSecret();
        String appId = htscAppSecretDTO.getAppId();
        for (; ; ) {
            try {
                TimeUnit.SECONDS.sleep(6L);
            } catch (Exception e) {
                log.error("睡眠的线程被打断了...", e);
                Thread.currentThread().interrupt();
            }
            try {
                today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("appid", appId);
                headerParamsMap.put("beginDate", startDay);
                headerParamsMap.put("endDate", endDay);
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "200");
                headerParamsMap.put("Timestamp", today);
                headerParamsMap.put("url", HtscConstants.PAY_FEE_DETAIL_INFO_API);
                String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", today);
                headers.set("Sign", sign);
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.PAY_FEE_DETAIL_INFO_API + "?appId=" + appId + "&beginDate=" + startDay + "&endDate=" + endDay + "&pageNo=" + pageNo + "&pageSize=200", headers);
                // 2.1 调用失败 将错误记录到错误记录表中
                int totalPages = 0;
                if (remoteResp.containsKey("code")) {
                    if (remoteResp != null && (Integer) remoteResp.get("code") != 200) {
                        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.PAY_FEE_DETAIL_INFO_API, headers, "appId=" + appId, remoteResp));
                        break;
                    }
                }
                saveInvokeRecord(tenant, trustNo, HtscConstants.PAY_FEE_DETAIL_INFO_API, headers, headerParamsMap, remoteResp);
                log.info("payFeeDetailInfo有值了...the beginDate is {},the endDate is {},the remoteResp is {}", startDay, endDay, JSON.toJSONString(remoteResp));
                if (remoteResp.containsKey("data")) {
                    JSONObject remoteData = (JSONObject) remoteResp.get("data");
                    if (!ObjectUtils.isEmpty(remoteData)) {
                        List<JSONObject> remoteDataList = JSONObject.parseArray(remoteData.get("list").toString(), JSONObject.class);
                        result.addAll(remoteDataList);
                        totalPages = Integer.parseInt(remoteData.get("totalPages").toString());
                    }
                }
                pageNo++;
                if (pageNo > totalPages) {
                    break;
                }
            } catch (Exception e) {
                log.info("调用华泰接口查询payFeeDetailInfo失败！", e);
            }
        }
        return result;
    }

    public List<JSONObject> processFundOpenInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, String htscUrlPrefix, String startDay, String endDay) throws IOException {
        int pageNo = 1;
        String today;
        List<JSONObject> result = new ArrayList<>();
        String tenantAppSecret = tenant.getAppSecret();
        if (StringUtils.isEmpty(tenantAppSecret)){
            return result;
        }
        HtscAppSecretDTO htscAppSecretDTO = objectMapper.readValue(tenantAppSecret, HtscAppSecretDTO.class);
        String appSecret = htscAppSecretDTO.getAppSecret();
        String appId = htscAppSecretDTO.getAppId();
        for (; ; ) {
            try {
                TimeUnit.SECONDS.sleep(6L);
            } catch (InterruptedException e) {
                log.error("processFundOpenInfoData睡眠的线程被打断了...", e);
                Thread.currentThread().interrupt();
            }
            try {
                today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "Z";
                Map<String, String> headerParamsMap = new HashMap<>();
                headerParamsMap.put("appid", appId);
                headerParamsMap.put("beginDate", startDay);
                headerParamsMap.put("endDate", endDay);
                headerParamsMap.put("pageNo", pageNo + "");
                headerParamsMap.put("pageSize", "200");
                headerParamsMap.put("Timestamp", today);
                headerParamsMap.put("url", HtscConstants.FUND_OPEN_INFO);
                String sign = HTSCSignGenerator.genSign(appSecret, headerParamsMap);
                HttpHeaders headers = new HttpHeaders();
                headers.set("Timestamp", today);
                 headers.set("Sign", sign);
                HashMap remoteResp = HTSCRemoteUtil.getDataFromRemote(htscUrlPrefix + HtscConstants.FUND_OPEN_INFO + "?appId=" + appId + "&beginDate=" + startDay + "&endDate=" + endDay + "&pageNo=" + pageNo + "&pageSize=200", headers);
                // 2.1 调用失败 将错误记录到错误记录表中
                int totalPages = 0;
                if (remoteResp != null && (Integer) remoteResp.get("code") != 200) {
                    pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, HtscConstants.FUND_OPEN_INFO, headers, "appId=" + appId, remoteResp));
                    break;
                }
                saveInvokeRecord(tenant, trustNo, HtscConstants.FUND_OPEN_INFO, headers, headerParamsMap, remoteResp);
                log.info("fundOpenInfo有值了...the beginDate is {},the endDate is {},the remoteResp is {}", startDay, endDay, JSON.toJSONString(remoteResp));
                if (remoteResp != null && remoteResp.containsKey("data")) {
                    JSONObject remoteData = (JSONObject) remoteResp.get("data");
                    if (!ObjectUtils.isEmpty(remoteData)) {
                        List<JSONObject> remoteDataList = JSONObject.parseArray(remoteData.get("list").toString(), JSONObject.class);
                        result.addAll(remoteDataList);
                        totalPages = Integer.parseInt(remoteData.get("totalPages").toString());
                    }
                }
                pageNo++;
                if (pageNo > totalPages) {
                    break;
                }
            } catch (Exception e) {
                log.info("调用华泰接口查询fundOpenINfo失败！", e);
            }
        }
        return result;
    }
}
