package com.friday.custody.service.trustService.guojindaofu.service.impl;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.friday.base.common.response.DubboResult;
import com.friday.custody.api.constant.GJDFConstant;
import com.friday.custody.api.dto.gjdf.*;
import com.friday.custody.entity.*;
import com.friday.custody.service.basicService.impl.*;
import com.friday.custody.service.trustService.guojindaofu.dto.*;
import com.friday.custody.api.feignclient.GJDFApi;
import com.friday.custody.api.util.GJDFInfoToEntityConvertor;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.service.basicService.InvokeRecordService;
import com.friday.custody.service.basicService.TenantEscrowAuthorizationInfoService;
import com.friday.custody.service.trustService.guojindaofu.service.GuoJinDaoFuService;
import com.friday.custody.service.trustService.guojindaofu.utils.GJDFResult;
import com.friday.custody.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GuoJinDaoFuServiceImpl implements GuoJinDaoFuService {
    @Autowired
    private GJDFApi gjdfApi;
    @Autowired
    GJDFInfoToEntityConvertor gjdfInfoToEntityConvertor;
    @Autowired
    InvokeRecordService invokeRecordService;
    @Autowired
    private InvestorInfoServiceImpl investorInfoService;
    @Autowired
    private CustShareInfoServiceImpl custShareInfoService;
    @Autowired
    private CustShareDetailInfoServiceImpl custShareDetailInfoService;
    @Autowired
    private FundTradeInfoServiceImpl fundTradeInfoService;
    @Autowired
    private FundOpenInfoServiceImpl fundOpenInfoService;
    @Autowired
    private FundProfitInfoServiceImpl fundProfitInfoService;
    @Autowired
    private CustShareSeqInfoServiceImpl custShareSeqInfoService;
    @Autowired
    private FundNetValueInfoServiceImpl fundNetValueInfoService;
    @Autowired
    private FundInfoServiceImpl fundInfoService;
    @Autowired
    private InvestorBankInfoServiceImpl investorBankInfoService;
    @Autowired
    private TenantEscrowAuthorizationInfoService authorizationInfoService;
    @Autowired
    DataDictionarySellerServiceImpl dataDictionarySellerService;
    @Autowired
    DataDictionarySellerDetailsServiceImpl dataDictionarySellerDetailsService;

    private static String token = "15de9f7e-76d2-45df-b01c-bd73442028864";
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 每日 点更新
     *
     * @param dto 管理人
     */
    @Override
    public void updatesEveryDay(TenantEscrowAuthorizationInfoDto dto, Integer dayCount) {
        try {
            // 获取账密
            String admin = dto.getTenantName();
            GjdfAppSecretDto gjdfAppSecretDto;
            gjdfAppSecretDto = objectMapper.readValue(dto.getAppSecret(), GjdfAppSecretDto.class);
            String operateCode = gjdfAppSecretDto.getOperateCode();
            String password = gjdfAppSecretDto.getPassword();
            //获取token
            getToken(admin, operateCode, password);
            //    saveSellerInformation(admin);
            // 1、基金信息 custody_fund_info
            saveFundInfo(admin);
            // 2、开放周期 custody_fund_open_info
            saveFundOpenInfo(admin);
            // 3、客户账户信息数据 custody_investor_info
            saveInvestorInfo(admin);
            // 4、基金账号登记信息 custody_investor_bank_info
            saveInvestorBankInfo(admin);
            // 5、从custody_fund_info表获取fundCode
            List<String> fundCodeList = fundInfoService.getFundCodeList("98", admin);
            for (String fundCode : fundCodeList) {
                // 基金行情信息 custody_fund_net_value_info
                saveFundNetValueInfo(admin, fundCode, dayCount);
            }
            // 6、交易申请信息
            // 7、交易确认结果 custody_fund_trade_info
            saveFundTradeInfo(admin, dayCount);
            // 8、基金确认明细
            // 9、业绩提成流水 custody_fund_profit_info
            saveFundProfitInfo(admin, dayCount);
            // 10、基金静态份额 custody_cust_share_info
            saveCustShareInfo(admin);
            //saveFundProfitInfo落库缺少份额类别在saveCustShareDetailInfo补充
            //saveCustShareDetailInfo需要流水号，但是上游没传来，从saveCustShareSeqInfo接口落库的表获取
            // 12、份额变化流水 custody_cust_share_seq_info
            saveCustShareSeqInfo(admin);
            // 11、基金份额明细 custody_cust_share_detail_info custody_fund_profit_info
            saveCustShareDetailInfo(admin);
            //saveCustShareSeqInfo有流水号
            // 13、分红明细
            // 14、账户确认信息
        } catch (Exception e) {
            log.error("国金道富初始化异常", e);
        }
    }

    /**
     * 基金账号登记信息
     * @param admin
     */
    private void saveInvestorBankInfo(String admin) {
        log.info("国金道富获取基金账号登记信息开始");
        int pageSize = 100;
        int pageNo = 0;
        List<GJDFBankInfoDto> gjdfBankInfoDtoList;
        List<InvestorBankInfoEntity> investorBankInfoEntityList = new ArrayList<>();
        Integer total;
        try {
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                String rawData = gjdfApi.customerBankInfo(token, admin, gjdfRequestParam);
                log.info("国金道富获取基金账号登记信息api:customerBankInfo:admin:{},Param={},response:{}", admin, gjdfRequestParam, rawData);
                ReturnDataDto<GJDFBankInfoDto> returnDataDto = obtainReturnData(rawData, GJDFBankInfoDto.class);
                total = returnDataDto.getTotal();
                gjdfBankInfoDtoList = returnDataDto.getDataList();
                //数据转换bankInfoDtoToEntity
                List<InvestorBankInfoEntity> investorInfoEntities = gjdfInfoToEntityConvertor.bankInfoDtoToEntity(gjdfBankInfoDtoList, admin);
                //将转换数据全部汇总
                investorBankInfoEntityList.addAll(investorInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_ACCOINFO_ACCONET, String.valueOf(gjdfRequestParam), rawData);
            } while (pageNo * pageSize < total);
            if (investorBankInfoEntityList.size() > 0) {
                //将数据落库
                investorBankInfoService.saveData(null, investorBankInfoEntityList);
            }
        } catch (Exception e) {
            log.error("国金道富获取基金账号登记信息异常", e);
        }
        log.info("国金道富获取基金账号登记信息结束");
    }


    /**
     * 客户账户信息数据
     *
     * @param admin 管理人
     */
    @Override
    public void saveInvestorInfo(String admin) {
        log.info("国金道富获取客户账户信息数据开始");
        int pageSize = 100;
        int pageNo = 0;
        try {
            List<GJDFAccoDto> gjdfAccoDtoList;
            List<InvestorInfoEntity> investorInfoEntityList = new ArrayList<>();
            Integer total;
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                String rawData = gjdfApi.customerAccountInfo(token, admin, gjdfRequestParam);
                log.info("国金道富获取客户账户信息数据api:customerAccountInfo:admin:{},Param={},response:{}", admin, gjdfRequestParam, rawData);
                ReturnDataDto<GJDFAccoDto> returnDataDto = obtainReturnData(rawData, GJDFAccoDto.class);
                total = returnDataDto.getTotal();
                gjdfAccoDtoList = returnDataDto.getDataList();
                //数据转换accoDtoToEntity
                List<InvestorInfoEntity> investorInfoEntities = gjdfInfoToEntityConvertor.accoDtoToEntity(gjdfAccoDtoList, admin);
                //将数据落库
                investorInfoEntityList.addAll(investorInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_ACCOINFO_ACCO, String.valueOf(gjdfRequestParam), rawData);
            } while (pageNo * pageSize < total);
            if (investorInfoEntityList.size() > 0) {
                investorInfoService.saveData(null, investorInfoEntityList);
            }
        } catch (Exception e) {
            log.error("国金道富获取客户账户信息数据异常", e);
        }
        log.info("国金道富获取客户账户信息数据结束");
    }

    /**
     * 基金静态份额
     *
     * @param admin 管理人
     */
    @Override
    public void saveCustShareInfo(String admin) {
        log.info("国金道富基金静态份额开始");
        int pageSize = 100;
        int pageNo = 0;
        List<GJDFShareDto> gjdfShareDtoList;
        List<CustShareInfoEntity> shareInfoEntities = new ArrayList<>();
        Integer total;
        try {
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                log.info("gjdfRequestParam={}", gjdfRequestParam);
                String rawData = gjdfApi.fundStaticShares(token, admin, gjdfRequestParam);
                ReturnDataDto<GJDFShareDto> returnDataDto = obtainReturnData(rawData, GJDFShareDto.class);
                total = returnDataDto.getTotal();
                gjdfShareDtoList = returnDataDto.getDataList();
                //数据转换
                List<CustShareInfoEntity> custShareInfoEntities = gjdfInfoToEntityConvertor.shareDtoToCustShareInfoEntity(gjdfShareDtoList, admin);
                //将数据暂存
                shareInfoEntities.addAll(custShareInfoEntities);

                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_SHARE_SHARE, String.valueOf(gjdfRequestParam), rawData);
            } while (pageNo * pageSize < total);
            if (shareInfoEntities.size() > 0) {
                custShareInfoService.saveData(null, shareInfoEntities);
            }
        } catch (Exception e) {
            log.error("国金道富基金静态份额异常", e);
        }
        log.info("国金道富基金静态份额结束");
    }

    /**
     * 基金份额明细
     *
     * @param admin 管理人
     */
    @Override
    public void saveCustShareDetailInfo(String admin) {
        log.info("国金道富基金份额明细开始");
        int pageSize = 100;
        int pageNo = 0;
        List<GJDFSharedetailDto> gjdfSharedetailDtoList;
        List<CustShareDetailInfoEntity> shareDetailInfoEntities = new ArrayList<>();
        ArrayList<FundProfitInfoEntity> profitInfoEntities = new ArrayList<>();
        Integer total;
        try {
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                log.info("国金道富基金份额明细api入参，gjdfRequestParam={}", gjdfRequestParam);
                String rawData = gjdfApi.fundShareDetails(token, admin, gjdfRequestParam);
                log.info("国金道富基金份额明细api响应={}", rawData);
                ReturnDataDto<GJDFSharedetailDto> returnDataDto = obtainReturnData(rawData, GJDFSharedetailDto.class);
                total = returnDataDto.getTotal();
                gjdfSharedetailDtoList = returnDataDto.getDataList();
                //数据转换
                List<CustShareDetailInfoEntity> custShareDetailInfoEntities = gjdfInfoToEntityConvertor.sharedetailDtoToCustShareDetailInfoEntity(gjdfSharedetailDtoList, admin);
                //数据转换-业绩报酬信息表-fund_profit_info
                List<FundProfitInfoEntity> fundProfitInfoEntities = gjdfInfoToEntityConvertor.sharedetailDtoToFundProfitInfoEntity(gjdfSharedetailDtoList, admin);
                //将数据暂存
                shareDetailInfoEntities.addAll(custShareDetailInfoEntities);
                profitInfoEntities.addAll(fundProfitInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_SHARE_SHAREDETAIL, String.valueOf(gjdfRequestParam), rawData);
            } while (pageNo * pageSize < total);
            if (shareDetailInfoEntities.size() > 0) {
                custShareDetailInfoService.saveData(null, shareDetailInfoEntities);
                //去重
                profitInfoEntities = new ArrayList<>(new HashSet<>(profitInfoEntities));
                fundProfitInfoService.saveGjdfShareType(profitInfoEntities);
            }
        } catch (Exception e) {
            log.error("国金道富基金份额明细异常", e);
        }
        log.info("国金道富基金份额明细结束");
    }

    /**
     * 交易确认结果
     *
     * @param admin 管理人
     */
    @Override
    public void saveFundTradeInfo(String admin, Integer dayCount) {
        log.info("国金道富交易确认结果开始");
        List<FundTradeInfoEntity> tradeInfoEntities = new ArrayList<>();
        if (dayCount != null) {
            LocalDate todayDate = LocalDate.now();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyyMMdd");
            for (int i = 0; i < dayCount; i++) {
                this.getFundTradeInfo(admin, todayDate.minusDays(i).format(pattern), tradeInfoEntities);
            }
        } else {
            this.getFundTradeInfo(admin, null, tradeInfoEntities);
        }
        if (tradeInfoEntities.size() > 0) {
            fundTradeInfoService.saveData(null, tradeInfoEntities);
        }
        log.info("国金道富交易确认结果结束");
    }

    /**
     * 单独抽出交易确认结果获取逻辑
     * @param admin
     * @param date
     * @param tradeInfoEntities
     */
    private void getFundTradeInfo(String admin, String date, List<FundTradeInfoEntity> tradeInfoEntities) {
        int pageSize = 100;
        int pageNo = 0;
        List<GJDFConfirmDto> gjdfConfirmDtoList;
        Integer total;
        try {
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                if (StringUtils.isNotBlank(date)){
                    gjdfRequestParam.setCdate(date);
                }
                String rawData = gjdfApi.transactionConfirmationresults(token, admin, gjdfRequestParam);
                log.info("国金道富交易确认结果api:gjdfRequestParam={},rawData={}", gjdfRequestParam, rawData);
                ReturnDataDto<GJDFConfirmDto> returnDataDto = obtainReturnData(rawData, GJDFConfirmDto.class);
                total = returnDataDto.getTotal();
                gjdfConfirmDtoList = returnDataDto.getDataList();
                //数据转换
                List<FundTradeInfoEntity> fundTradeInfoEntities = gjdfInfoToEntityConvertor.fundTradeInfoDtoToEntity(gjdfConfirmDtoList, "98", admin);
                //将数据落库
                tradeInfoEntities.addAll(fundTradeInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_TRADE_CONFIRM, String.valueOf(gjdfRequestParam), rawData);
            } while (pageNo * pageSize < total);
        } catch (Exception e) {
            log.error("国金道富交易确认结果异常", e);
        }
    }

    /**
     * 开放周期
     */
    @Override
    public void saveFundOpenInfo(String admin) {
        log.info("国金道富获取开放周期开始");
        int pageSize = 100;
        int pageNo = 0;
        try {
            List<GJDFFundopendayDto> gjdfFundopendayDtoList;
            List<FundOpenInfoEntity> openInfoEntities = new ArrayList<>();
            Integer total;
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                log.info("gjdfRequestParam={}", gjdfRequestParam);
                String rawData = gjdfApi.openingPeriod(token, admin, gjdfRequestParam);
                log.info("国金道富获取开放周期api响应：" + rawData);
                ReturnDataDto<GJDFFundopendayDto> returnDataDto;
                returnDataDto = obtainReturnData(rawData, GJDFFundopendayDto.class);
                total = returnDataDto.getTotal();
                gjdfFundopendayDtoList = returnDataDto.getDataList();
                //数据转换
                List<FundOpenInfoEntity> fundOpenInfoEntities = gjdfInfoToEntityConvertor.fundOpenInfoDtoToEntity(gjdfFundopendayDtoList, admin);
                //将数据暂存
                openInfoEntities.addAll(fundOpenInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_PARAMINFO_FUNDOPENDAY, String.valueOf(gjdfRequestParam), rawData);

            } while (pageNo * pageSize < total);
            if (openInfoEntities.size() > 0) {
                //将数据落库
                fundOpenInfoService.saveData(null, openInfoEntities);
            }
        } catch (Exception e) {
            log.error("国金道富获取开放周期异常", e);
        }
        log.info("国金道富获取开放周期结束");
    }

    /**
     * 业绩提成流水
     *
     * @param admin 管理人
     */
    @Override
    public void saveFundProfitInfo(String admin, Integer dayCount) {
        log.info("国金道富业绩提成流水开始");
        try {
            List<FundProfitInfoEntity> profitInfoEntities = new ArrayList<>();
            if (dayCount != null) {
                DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyyMMdd");
                LocalDate todayDate = LocalDate.now();
                for (int i = 0; i < dayCount; i++) {
                    this.getFundProfitInfo(admin, todayDate.minusDays(i).format(pattern), profitInfoEntities);
                }
            } else {
                this.getFundProfitInfo(admin, null, profitInfoEntities);
            }

            if (profitInfoEntities.size() > 0) {
                fundProfitInfoService.saveData(null, profitInfoEntities);
            }
        } catch (Exception e) {
            log.error("国金道富业绩提成流水异常", e);
        }
        log.info("国金道富业绩提成流水结束");
    }

    /**
     * 单独抽出业绩提成流水逻辑
     * @param admin
     * @param date
     * @param profitInfoEntities
     */
    private void getFundProfitInfo(String admin, String date, List<FundProfitInfoEntity> profitInfoEntities) {
        int pageSize = 100;
        int pageNo = 0;
        List<GJDFProfitcurrentDto> gjdfProfitcurrentDtoList;
        Integer total;
        do {
            pageNo++;
            GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
            gjdfRequestParam.setNeedCountFlag(1);
            gjdfRequestParam.setCurrentPage(pageNo);
            gjdfRequestParam.setPageRows(pageSize);
            if (StringUtils.isNotBlank(date)) {
                gjdfRequestParam.setDate(date);
            }
            String rawData = gjdfApi.performanceCommissionFlow(token, admin, gjdfRequestParam);
            log.info("国金道富业绩提成流水api:gjdfRequestParam={},rawData={}", gjdfRequestParam, rawData);
            ReturnDataDto<GJDFProfitcurrentDto> returnDataDto = null;
            try {
                returnDataDto = obtainReturnData(rawData, GJDFProfitcurrentDto.class);
            } catch (IOException e) {
                log.error("国金道富业绩提成流水响应转化异常", e);
                throw new RuntimeException(e);
            }
            total = returnDataDto.getTotal();
            gjdfProfitcurrentDtoList = returnDataDto.getDataList();
            //数据转换
            List<FundProfitInfoEntity> fundProfitInfoEntities = gjdfInfoToEntityConvertor.profitcurrentDtoToFundProfitInfoEntity(gjdfProfitcurrentDtoList, admin);
            //将数据落库
            profitInfoEntities.addAll(fundProfitInfoEntities);
            //原始数据添加到日志
            saveInvokeRecord("98", admin, GJDFConstant.TA_KF_TRADE_PROFITCURRENT, String.valueOf(gjdfRequestParam), rawData);
        } while (pageNo * pageSize < total);
    }

    /**
     * 份额变化流水
     *
     * @param admin 管理人
     */
    @Override
    public void saveCustShareSeqInfo(String admin) {
        log.info("国金道富份额变化流水开始");
        int pageSize = 100;
        int pageNo = 0;
        List<GJDFSharecurrentsDto> gjdfSharecurrentsDtoList;
        List<CustShareSeqInfoEntity> shareSeqInfoEntities = new ArrayList<>();
        Integer total;
        try {
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                log.info("国金道富份额变化流水api入参，gjdfRequestParam={}", gjdfRequestParam);
                String rawData = gjdfApi.shareChangeJournal(token, admin, gjdfRequestParam);
                log.info("国金道富份额变化流水api响应={}", rawData);
                ReturnDataDto<GJDFSharecurrentsDto> returnDataDto = obtainReturnData(rawData, GJDFSharecurrentsDto.class);
                total = returnDataDto.getTotal();
                gjdfSharecurrentsDtoList = returnDataDto.getDataList();
                //数据转换
                List<CustShareSeqInfoEntity> custShareSeqInfoEntities = gjdfInfoToEntityConvertor.sharecurrentsDtoToShareSeqInfoEntity(gjdfSharecurrentsDtoList, admin);
                //将数据暂存
                shareSeqInfoEntities.addAll(custShareSeqInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_TRADE_SHARECURRENTS, String.valueOf(gjdfRequestParam), rawData);
            } while (pageNo * pageSize < total);
            if (shareSeqInfoEntities.size() > 0) {
                custShareSeqInfoService.saveData(null, shareSeqInfoEntities);
            }
        } catch (Exception e) {
            log.error("国金道富份额变化流水异常", e);
        }
        log.info("国金道富份额变化流水结束");

    }

    /**
     * 基金行情信息
     *
     * @param admin    管理人
     * @param fundCode 基金代码
     */
    @Override
    public void saveFundNetValueInfo(String admin, String fundCode, Integer dayCount) {
        log.info("国金道富获取基金:{},行情信息开始", fundCode);
        List<FundNetValueInfoEntity> netValueInfoEntities = new ArrayList<>();
        if (dayCount != null) {
            LocalDate todayDate = LocalDate.now();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyyMMdd");
            // 按照时间遍历
            for (int i = 0; i < dayCount; i++) {
                String dateStr = todayDate.minusDays(i).format(pattern);
                this.getFundNetValueInfo(admin, fundCode, dateStr, netValueInfoEntities);
            }
        } else {
            this.getFundNetValueInfo(admin, fundCode, null, netValueInfoEntities);
        }
        if (netValueInfoEntities.size() > 0) {
            fundNetValueInfoService.saveData(null, netValueInfoEntities);
        }
        log.info("国金道富获取基金:{},行情信息结束", fundCode);
    }

    /**
     * 单独抽出来调用获取基金行情信息接口解析
     * @param admin 租户id
     * @param fundCode 基金code
     * @param date 指定查询日期，如果为空，则不传递，默认全查
     * @param netValueInfoEntities 查询结果转换后添加到该集合
     */
    private void getFundNetValueInfo(String admin, String fundCode, String date, List<FundNetValueInfoEntity> netValueInfoEntities) {
        List<GJDFFundvaluationsDto> gjdfFundvaluationsDtoList;
        int pageSize = 100;
        int pageNo = 0;
        Integer total;
        try {
            do {
                pageNo++;
                FundMarketInformationReq fundMarketInformationReq = new FundMarketInformationReq();
                fundMarketInformationReq.setNeedCountFlag(1);
                fundMarketInformationReq.setCurrentPage(pageNo);
                fundMarketInformationReq.setPageRows(pageSize);
                fundMarketInformationReq.setFundCode(fundCode);
                if (StringUtils.isNotBlank(date)) {
                    fundMarketInformationReq.setDate(date);
                }
                String rawData = gjdfApi.fundMarketInformation(token, admin, fundMarketInformationReq);
                log.info("国金道富获取基金行情信息api:fundMarketInformationReq={},rawData:{}", fundMarketInformationReq, rawData);
                ReturnDataDto<GJDFFundvaluationsDto> returnDataDto = null;
                try {
                    returnDataDto = obtainReturnData(rawData, GJDFFundvaluationsDto.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                total = returnDataDto.getTotal();
                gjdfFundvaluationsDtoList = returnDataDto.getDataList();
                //数据转换
                List<FundNetValueInfoEntity> fundNetValueInfoEntities = GJDFInfoToEntityConvertor.fundNetValueInfoDtoToEntity(gjdfFundvaluationsDtoList, admin);
                //将数据暂存
                netValueInfoEntities.addAll(fundNetValueInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_NAVINFO_FUNDVALUATIONS, String.valueOf(fundMarketInformationReq), rawData);
            } while (pageNo * pageSize < total);
        } catch (Exception e) {
            log.error("国金道富获取基金行情信息异常", e);
        }
    }


    public <T> ReturnDataDto<T> obtainReturnData(String rawData, Class<T> type) throws IOException {
        GJDFResult<T> gjdfResult = new GJDFResult();

        gjdfResult = objectMapper.readValue(rawData, GJDFResult.class);
        String data = gjdfResult.getData().toString();
        GuoJinDaoFuProductInfoDto<?> productInfoDto;
        productInfoDto = objectMapper.readValue(data, GuoJinDaoFuProductInfoDto.class);
        //数据总数
        Integer total = productInfoDto.getTotal();
        List<T> typeList = new ArrayList<T>();
        try {
            List rows = productInfoDto.getRows();
            String s = objectMapper.writeValueAsString(rows);
            TypeFactory t = TypeFactory.defaultInstance();
            typeList = objectMapper.readValue(s, t.constructCollectionType(ArrayList.class, type));
            // typeList = objectMapper.readValue(s, new TypeReference<List<T>>() {});
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        ReturnDataDto<T> returnDataDto = new ReturnDataDto<>();
        returnDataDto.setDataList(typeList);
        returnDataDto.setTotal(total);
        return returnDataDto;
    }

    /**
     * 基金信息
     *
     * @param admin 管理人
     */
    @Override
    public void saveFundInfo(String admin) {
        log.info("国金道富获取基金信息开始");
        try {
            int pageSize = 100;
            int pageNo = 0;
            List<GJDFFundInfo> gjdfFundInfoList;
            ArrayList<FundInfoEntity> infoEntities = new ArrayList<>();
            Integer total;
            do {
                pageNo++;
                GJDFRequestParam gjdfRequestParam = new GJDFRequestParam();
                gjdfRequestParam.setNeedCountFlag(1);
                gjdfRequestParam.setCurrentPage(pageNo);
                gjdfRequestParam.setPageRows(pageSize);
                log.info("gjdfRequestParam={}", gjdfRequestParam);
                String rawData = gjdfApi.fundInformation(token, admin, gjdfRequestParam);
                log.info("国金道富基金api响应：" + rawData);
                ReturnDataDto<GJDFFundInfo> returnDataDto;
                returnDataDto = obtainReturnData(rawData, GJDFFundInfo.class);
                total = returnDataDto.getTotal();
                gjdfFundInfoList = returnDataDto.getDataList();
                //数据转换
                List<FundInfoEntity> fundInfoEntities = gjdfInfoToEntityConvertor.fundInfoDtoToEntity(gjdfFundInfoList, admin);
                //将数据暂存
                infoEntities.addAll(fundInfoEntities);
                //原始数据添加到日志
                saveInvokeRecord("98", admin, GJDFConstant.TA_KF_PARAMINFO_FUNDINFO, String.valueOf(gjdfRequestParam), rawData);
            } while (pageNo * pageSize < total);
            if (infoEntities.size() > 0) {
                //将数据落库
                fundInfoService.saveData(null, infoEntities);
            }
        } catch (Exception e) {
            log.error("国金道富获取基金信息异常", e);
        }
        log.info("国金道富获取基金信息结束");
    }


    /**
     * 销售商信息-字典表
     *
     * @param admin
     */
    public void saveSellerInformation(String admin) {
        int pageSize = 100;
        int pageNo = 0;
        int total = 0;
        List<GJDFAgencyinfoDto> gjdfAgencyinfoDtoList;
        do {
            pageNo++;
            GJDFsellerInformationReq gjdFsellerInformationReq = new GJDFsellerInformationReq();
            gjdFsellerInformationReq.setNeedCountFlag(1);
            gjdFsellerInformationReq.setPageRows(100);
            gjdFsellerInformationReq.setCurrentPage(1);
            gjdFsellerInformationReq.setAgencyno(null);
            String rawData = gjdfApi.sellerInformation(token, admin, gjdFsellerInformationReq);
            ReturnDataDto<GJDFAgencyinfoDto> returnDataDto = null;
            try {
                returnDataDto = obtainReturnData(rawData, GJDFAgencyinfoDto.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            total = returnDataDto.getTotal();
            gjdfAgencyinfoDtoList = returnDataDto.getDataList();
            //将数据落库
            for (GJDFAgencyinfoDto gjdfAgencyinfoDto : gjdfAgencyinfoDtoList) {
                String mapValue = gjdfAgencyinfoDto.getAgencyno();
                String value = gjdfAgencyinfoDto.getAgencyname();
                Integer sellerKeyDicId = dataDictionarySellerService.saveSellerKey(value, mapValue, "国金道富");
                if (sellerKeyDicId != 0) {
                    //落映射表
                    Integer sellerDetails = dataDictionarySellerDetailsService.saveSellerDetails(sellerKeyDicId, "98", mapValue);
                }
            }
            //原始数据添加到日志
            System.out.println("=======");
            //saveInvokeRecord("98",admin,GJDFConstant.TA_KF_PARAMINFO_AGENCYINFO,String.valueOf(gjdFsellerInformationReq),rawData);
        } while (pageNo * pageSize < total);
    }

    /**
     * 原始数据添加到日志
     *
     * @param trustNo    托管
     * @param admin      管理人
     * @param invokeType 接口路径
     * @param reqParam   请求参数
     * @param rawData    上游返回原始数据
     */
    public void saveInvokeRecord(String trustNo, String admin, String invokeType, String reqParam, String rawData) {
        //原始数据添加到日志
        InvokeRecordEntity invokeRecordEntity = InvokeRecordEntity.builder()
                .trustNo(trustNo)
                .admin(admin)
                .invokeType(invokeType)
                .reqParam(reqParam)
                .invokeTime(new Date())
                .invokeResult(rawData)
                .queryKey(admin + "::" + trustNo + "::" + invokeType)
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        invokeRecordService.save(invokeRecordEntity);
    }

    /**
     * token是否失效
     *
     * @return
     */


    @Override
    public Boolean doesTheTokenExpire(String token, String admin, String userCode, String password) {
        GJDFResult<?> gjdfResult;
        try {
            DoesTheTokenExpireReq doesTheTokenExpireReq = new DoesTheTokenExpireReq();
            doesTheTokenExpireReq.setUserToken(token);
            String tokenInvalid = gjdfApi.doesTheTokenExpire(admin, doesTheTokenExpireReq);
            gjdfResult = objectMapper.readValue(tokenInvalid, GJDFResult.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Map resultData;
        try {
            resultData = objectMapper.readValue((JsonParser) gjdfResult.getData(), Map.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Object isSessionTimeOut = resultData.get("isSessionTimeOut");
        //true:失效，false 为未失效
        if ("true".equals(isSessionTimeOut)) {
            getToken(admin, userCode, password);
        }

        return true;
    }

    @Override
    public void getToken(String admin, String userCode, String password) {
        try {
            log.info("国金道富获取token开始，参数：admin:{},useCode:{},password:{}", admin, userCode, password);
            TokenReq tokenReq = new TokenReq();
            tokenReq.setOperatorCode(userCode);
            tokenReq.setPassword(password);
            String result = gjdfApi.getToken(admin, tokenReq);
            GJDFResult<?> gjdfResult = objectMapper.readValue(result, GJDFResult.class);
            Map resultData = (Map) gjdfResult.getData();
            token = (String) resultData.get("token");
        } catch (Exception e) {
            log.error("国金道富获取token异常", e);
        }

    }

    /*
        ========================================
        ============以下为框架接口实现==============
     */
    @Override
    public R initTenantData(List<TenantEscrowAuthorizationInfoDto> tenants) {
        log.info("国金道富初始化开始。。。");
        List<TenantEscrowAuthorizationInfoDto> result = tenants.stream().filter(t -> t.getTrustNo().equals("98") && t.getVersion().equals("api")).collect(Collectors.toList());
        for (TenantEscrowAuthorizationInfoDto dto : result) {
            updatesEveryDay(dto, null);
        }
        return R.ok("国金道富初始化结束。。。");
    }

    @Override
    public R initTenantDataSingle(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("国金道富初始化开始...");
        updatesEveryDay(tenant, null);
        log.info("国金道富初始化结束...");
        return R.ok("国金道富初始化结束...");
    }

    @Override
    public R updateDataDaily(List<TenantEscrowAuthorizationInfoDto> tenants) {
        log.info("国金道富初始化开始...");
        List<TenantEscrowAuthorizationInfoDto> result = tenants.stream().filter(t -> t.getTrustNo().equals("98") && t.getVersion().equals("api")).collect(Collectors.toList());
        for (TenantEscrowAuthorizationInfoDto dto : result) {
            updatesEveryDay(dto, 7);
        }
        log.info("国金道富初始化结束...");
        return R.ok("国金道富更新结束...");
    }

    @Override
    public R updateSingleDataDaily(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("国金道富初始化...");
        updatesEveryDay(tenant, 7);
        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) {
        return null;
    }

    @Override
    public R initByAppointedTrustNoAndMouth(TenantEscrowAuthorizationInfoDto tenant, int month) {
        return null;
    }

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

    @Override
    public R updateSingleData20min(TenantEscrowAuthorizationInfoDto tenant) {
        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("国金道富基金行情信息更新开始...");
        try {
            // 获取账密
            String admin = tenant.getTenantName();
            GjdfAppSecretDto gjdfAppSecretDto;
            gjdfAppSecretDto = objectMapper.readValue(tenant.getAppSecret(), GjdfAppSecretDto.class);
            String operateCode = gjdfAppSecretDto.getOperateCode();
            String password = gjdfAppSecretDto.getPassword();
            //获取token
            getToken(admin, operateCode, password);
            // 5、从custody_fund_info表获取fundCode
            List<String> fundCodeList = fundInfoService.getFundCodeList("98", admin);
            for (String fundCode : fundCodeList) {
                // 基金行情信息 custody_fund_net_value_info
                saveFundNetValueInfo(admin, fundCode, 7);
            }
        } catch (Exception e) {
            log.error("国金道富基金行情信息更新异常", e);
        }
        log.info("国金道富基金行情信息更新结束...");
        return R.ok("国金道富基金行情信息更新完毕...");
    }

    @Override
    public DubboResult updateMJBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {

            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
        } catch (Exception e) {
            log.error("手动更新募集户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateMJSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {

            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
        } catch (Exception e) {
            log.error("手动更新募集户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新募集户流水失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        try {

            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
        } catch (Exception e) {
            log.error("手动更新托管户余额失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户余额失败" + e.getMessage());
        }
    }

    @Override
    public DubboResult updateTGSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        try {

            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
        } catch (Exception e) {
            log.error("手动更新托管户流水失败", e);
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "手动更新托管户流水失败" + e.getMessage());
        }
    }
}
