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


import com.alibaba.fastjson.JSONObject;
import com.friday.base.common.response.DubboResult;
import com.friday.custody.dto.InterProviderResponseDto;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.entity.DataDictionaryZxFndBasicInfoCyEntity;
import com.friday.custody.entity.FundIndexDailyQuoteInfoEntity;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.service.basicService.impl.DataDictionaryZxFndBasicInfoCyServiceImpl;
import com.friday.custody.service.basicService.impl.FundIndexDailyQuoteInfoServiceImpl;
import com.friday.custody.service.logicService.impl.DataDictionaryBasicServiceImpl;
import com.friday.custody.service.trustService.OutsourceService;
import com.friday.custody.service.trustService.zx.utils.SearchReturnClass;
import com.friday.custody.utils.BigDecimalUtil;
import com.friday.custody.utils.MatchDataDictionaryKeyUtil;
import com.friday.custody.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;


@Slf4j
@Service
public class OutSourceZxServiceImpl  implements OutsourceService {

    @Autowired
    private SearchReturnClass searchReturnClass;

    @Autowired
    private FundIndexDailyQuoteInfoServiceImpl fundIndexDailyQuoteInfoService;

    @Autowired
    private DataDictionaryBasicServiceImpl dataDictionaryBasicService;

    @Autowired
    private DataDictionaryZxFndBasicInfoCyServiceImpl dataDictionaryZxFndBasicInfoCyService;

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

    @Override
    public R initTenantDataSingle(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("资讯平台数据初始化开始！！！！");
        String trustNo = "99";
        int loopTime = CustodyContants.INIT_BY_MONTH_LOOP_TIME;
        getDataFromZx(tenant, trustNo, loopTime);
        log.info("资讯平台数据初始化成功！");
        return R.ok("资讯平台数据初始化成功！");
    }

    private void getDataFromZx(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        processIndexDailyQuoteInfoData(tenant, trustNo, loopTime);
        processInxDailyQuoteWindData(tenant, trustNo, loopTime);
    }
    public void processInxDailyQuoteWindData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        String tradingDay;
        LocalDate localDate = LocalDate.now();
        LocalDate lastDay;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        loopTime = loopTime == 12 ? 1 : 15;
        for (int i = 0; i < loopTime; i++) {
            tradingDay = dateTimeFormatter.format(localDate).concat(" 00:00:00");
            lastDay = localDate.minusDays(1);
            int startrow = 0;
            int pageSize = 1000;
            int pageNo = 0;
            for (; ; ) {
                pageNo++;
                //封装请求参数
                List<String> selectedFields = Lists.newArrayList();
                //交易代码
                Map<String, List<String>> paramMap = new HashMap<>();
                paramMap.put("TRADINGCODE", Lists.newArrayList("H11001"));
                //如果是更新，需要传时间
                if ("15".equals(String.valueOf(loopTime))){
                    paramMap.put("TRADINGDAY", Lists.newArrayList(tradingDay));
                }
                //调用资讯平台接口获取数据
                InterProviderResponseDto resultData = InterProviderResponseDto.builder().build();
                try {
                    resultData = searchReturnClass.sendMessage(tenant, trustNo, "ZX_INXDAILYQUOTEWIND", paramMap, startrow, pageSize, "TRADINGDAY", selectedFields);
                } catch (Exception e) {
                    log.error("调用资讯平台获取行情指数Wind数据失败！", e);
                }
                int totalCount = 0;
                //封装数据
                if (resultData.isSuccess()) {
                    List<Map<String, Object>> dataList = resultData.getDataList();
                    totalCount = dataList.size();
                    log.info("获取资讯平台行情指数Wind数据{}条", dataList.size());
                    if (!ObjectUtils.isEmpty(dataList)) {
                        List<FundIndexDailyQuoteInfoEntity> inxDailyQuoteWindData = getInxDailyQuoteWindData(tenant, trustNo, dataList);
                        log.info("封装行情指数Wind数据{}条", inxDailyQuoteWindData.size());
                        //保存数据
                        fundIndexDailyQuoteInfoService.saveData(null, inxDailyQuoteWindData);
                    }
                }
                if (pageNo * pageSize > totalCount) {
                    break;
                }
                startrow += pageSize;
            }
            localDate = lastDay;
        }
    }

    private List<FundIndexDailyQuoteInfoEntity> getInxDailyQuoteWindData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<Map<String, Object>> dataList) {
        //获取字典
        //todo 交易所
//        dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.EXCHANGE_CODE_SERVICE, trustNo);
        Map<String, String> currencyDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, trustNo);
        //todo 市场标识
        //封装数据
        List<FundIndexDailyQuoteInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        for (Map data : dataList){
            dataMap = data;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            entityList.add(FundIndexDailyQuoteInfoEntity.builder()
                    .windCode(dataMap.get("WINDCODE"))
                    .secuCode(String.valueOf(dataMap.get("SECUCODE")).replace(".0", ""))
                    .tradingCode(dataMap.get("TRADINGCODE"))
                    .exchangeCode(String.valueOf(dataMap.get("EXCHANGECODE")).replaceAll(".0",""))
                    .tradingDay(sdf.format(dataMap.get("TRADINGDAY")))
                    .currency(MatchDataDictionaryKeyUtil.getKey(currencyDic, String.valueOf(dataMap.get("CURRENCYCODE")).replaceAll(".0","")))
                    .prevClosingPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("PREVCLOSINGPRICE"), 4))
                    .openingPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("OPENINGPRICE"), 4))
                    .highestPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("HIGHESTPRICE"), 4))
                    .lowestPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("LOWESTPRICE"), 4))
                    .closingPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("CLOSINGPRICE"), 4))
                    .turnoverVol(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("TURNOVERVOL"), 4))
                    .turnoverVal(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("TURNOVERVAL"), 4))
                    .dayChange(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("DAYCHANGE"), 4))
                    .dayChangeRate(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("DAYCHANGERATE"), 4))
                    .pe(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("PE"), 4))
                    .pb(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("PB"), 4))
                    .afMarketVal(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("AFMARKETVAL"), 4))
                    .tMarketVal(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("TMARKETVAL")))
                    .marketFlag(String.valueOf(dataMap.get(("MARKETFLAG"))).replace(".0", ""))
                    .secuAbbr("中证全债指数")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }

    public R processDataDicZxFndBasicInfo(TenantEscrowAuthorizationInfoDto tenant) {
        //从咨询获取数据
        try {
            int startrow = 0;
            int pageSize = 5000;
            int totalCount = 0;
            int pageNo = 0;
            for (; ; ) {
                pageNo++;
                Map<String, Object> result = searchReturnClass.getFundInfoFromZx(tenant,startrow, pageSize);
                if (!ObjectUtils.isEmpty(result)) {
                    List<JSONObject> fundInfoList = JSONObject.parseArray(JSONObject.toJSONString(result.get("dataList")), JSONObject.class);
                    totalCount = Integer.parseInt(result.get("totalCount").toString());
                    log.info("从咨询平台查询dataDictionaryZxFndBasicInfoCy数据{}条:{}", fundInfoList.size(), JSONObject.toJSONString(fundInfoList));
                    //封装数据
                    List<DataDictionaryZxFndBasicInfoCyEntity> entityList = new ArrayList<>();
                    if (!ObjectUtils.isEmpty(fundInfoList)) {
                        for (Map<String, Object> map : fundInfoList) {
                            if ("0.0".equals(String.valueOf(map.get("ISLIQUIDATION")))) {
                                if (!ObjectUtils.isEmpty(map.get("REGCODE"))) {
                                    entityList.add(DataDictionaryZxFndBasicInfoCyEntity.builder()
                                            .keyStr(String.valueOf(map.get("REGCODE")))
                                            .value(String.valueOf(map.get("FUNDFULLNAME")))
                                            .remark(String.valueOf(map.get("FUNDNAME")))
                                            .createTime(new Date())
                                            .updateTime(new Date())
                                            .build());
                                }
                            }
                        }
                        log.info("封装dataDictionaryZxFndBasicInfoCy数据{}条", entityList.size());
                        //保存数据
                        if (!ObjectUtils.isEmpty(entityList)) {
                            dataDictionaryZxFndBasicInfoCyService.saveData(null, entityList);
                        }
                        if (pageNo * pageSize > totalCount) {
                            break;
                        }
                        startrow += pageSize;
                    }
                }
            }
            return R.ok("保存dataDictionaryZxFndBasicInfoCy数据成功！");
        } catch (InterruptedException e) {
            log.info("获取私募基金基本信息失败！", e);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.info("保存dataDictionaryZxFndBasicInfoCy数据失败！", e);
        }
        return R.error("保存dataDictionaryZxFndBasicInfoCy数据失败！");
    }

    public void processIndexDailyQuoteInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopTime) {
        loopTime = loopTime == 12 ? 1 : 15;
        List<String> tradingCodeList = Arrays.asList("000300", "000905", "000852", "000016", "000906", "000832", "HSI001", "CI0077");
        for (String tradingCode : tradingCodeList) {
            String tradingDay;
            LocalDate localDate = LocalDate.now();
            LocalDate lastDay;
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
            for (int i = 0; i < loopTime; i++) {
                tradingDay = dateTimeFormatter.format(localDate).concat(" 00:00:00");
                lastDay = localDate.minusDays(1);
                int startrow = 0;
                int pageSize = 1000;
                int pageNo = 0;
                for (; ; ) {
                    pageNo++;
                    List<String> selectedFields = Lists.newArrayList();
                    //交易代码
                    Map<String, List<String>> paramMap = new HashMap<>();
                    paramMap.put("TRADINGCODE", Lists.newArrayList(tradingCode));
                    //如果是更新，需要传时间
                    if ("15".equals(String.valueOf(loopTime))) {
                        paramMap.put("TRADINGDAY", Lists.newArrayList(tradingDay));
                    }
                    //调用资讯平台接口获取数据
                    InterProviderResponseDto resultData = InterProviderResponseDto.builder().build();
                    try {
                        resultData = searchReturnClass.sendMessage(tenant, trustNo, "ZX_INXDAILYQUOTE", paramMap, startrow, pageSize, "TRADINGDAY", selectedFields);
                    } catch (Exception e) {
                        log.error("调用资讯平台获取行情指数数据失败！", e);
                    }
                    int totalCount = 0;
                    //封装数据
                    if (resultData.isSuccess()) {
                        List<Map<String, Object>> dataList = resultData.getDataList();
                        totalCount = resultData.getTotalCount();
                        log.info("获取资讯平台行情指数数据{}条", dataList.size());
                        if (!ObjectUtils.isEmpty(dataList)) {
                            List<FundIndexDailyQuoteInfoEntity> fundIndexDailyQuoteInfo = getFundIndexDailyQuoteInfo(tenant, trustNo, dataList);
                            log.info("封装行情指数数据{}条", fundIndexDailyQuoteInfo.size());
                            //保存数据
                            fundIndexDailyQuoteInfoService.saveData(null, fundIndexDailyQuoteInfo);
                        }
                    }
                    if (pageNo * pageSize > totalCount) {
                        break;
                    }
                     startrow += pageSize;
                }
                localDate = lastDay;
            }
        }
    }

    private List<FundIndexDailyQuoteInfoEntity> getFundIndexDailyQuoteInfo(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<Map<String, Object>> dataList) {
        //获取数据字典
        //封装数据
        List<FundIndexDailyQuoteInfoEntity> entityList = new ArrayList<>();
        Map<String, String> dataMap;
        for (Map data : dataList){
            dataMap = data;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            entityList.add(FundIndexDailyQuoteInfoEntity.builder()
                    .secuCode(String.valueOf(dataMap.get("SECUCODE")).replace(".0", ""))
                    .tradingCode(dataMap.get("TRADINGCODE"))
                    .secuAbbr(dataMap.get("SECUABBR"))
                    .tradingDay(sdf.format(dataMap.get("TRADINGDAY")))
                    .prevClosingPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("PREVCLOSINGPRICE"), 4))
                    .openingPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("OPENINGPRICE"), 4))
                    .highestPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("HIGHESTPRICE"), 4))
                    .lowestPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("LOWESTPRICE"), 4))
                    .closingPrice(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("CLOSINGPRICE"), 4))
                    .turnoverVol(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("TURNOVERVOL"), 4))
                    .turnoverVal(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("TURNOVERVAL"), 4))
                    .dayChange(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("DAYCHANGE"), 4))
                    .dayChangeRate(BigDecimalUtil.obj2BigDecimalTrunToZero(dataMap.get("DAYCHANGERATE"), 4))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build());
        }
        return entityList;
    }
    @Override
    public R updateDataDaily(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R updateSingleDataDaily(TenantEscrowAuthorizationInfoDto tenant) {
        log.info("资讯平台数据更新开始！！！！");
        String trustNo = "99";
        int loopTime = CustodyContants.UPDATE_BY_DAY_DAILY_LOOP_TIME;
        getDataFromZx(tenant, trustNo, loopTime);
        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 mouth) {
        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) {
        return null;
    }

    @Override
    public DubboResult updateMJBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }

    @Override
    public DubboResult updateMJSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }

    @Override
    public DubboResult updateTGBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }

    @Override
    public DubboResult updateTGSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }
}
