package com.jxy.marketall.service.impl;


import com.jxy.common.core.utils.DateUtils;
import com.jxy.common.core.utils.StringUtils;
import com.jxy.common.core.web.Result.AjaxResult;
import com.jxy.common.redis.service.RedisService;
import com.jxy.marketall.dto.*;
import com.jxy.marketall.enums.ETHV2RedisName;
import com.jxy.marketall.mapper.ETHMapper;
import com.jxy.marketall.mapper.ETHRTMapper;
import com.jxy.marketall.mapper.ETHV2Mapper;
import com.jxy.marketall.mapper.EthBigTxMapper;
import com.jxy.marketall.service.ETHV2Service;
import com.jxy.marketall.vo.EBalanceVo;
import com.jxy.marketall.vo.QueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Date 2023/3/3 11:53
 * @Author 杜懿
 */
@Service
public class ETHV2ServiceImpl implements ETHV2Service {

    @Autowired
    private RedisService redisService;

    @Autowired
    private ETHMapper ethMapper;

    @Override
    public AjaxResult getPiCycleTIList(QueryVo vo) {

        List<PiCycleTIDto> list = redisService.getCacheList("ETHPiCTIList");

        if(list.size() < 1){
            return AjaxResult.success(list);
        }

        if(StringUtils.isNotBlank(vo.getStart())){
            Date start = DateUtils.parseDate(vo.getStart());
            list = list.stream().filter(dto -> (dto.getDate().after(start) || dto.getDate().equals(start))).collect(Collectors.toList());
        }

        if(StringUtils.isNotBlank(vo.getEnd())){
            Date end = DateUtils.parseDate(vo.getEnd());
            list = list.stream().filter(dto -> (dto.getDate().before(end) || dto.getDate().equals(end))).collect(Collectors.toList());
        }

        if(vo.getSma() > 0){
            // TODO:
        }

        if(list.size() < 1){
            return AjaxResult.success("当前搜索时间段无数据",list);
        }

        return  AjaxResult.success(list);
    }

    @Override
    public AjaxResult getGoldenRatioMultList(int sma) {

        List<GoldenRatioMultiplierDto> list = redisService.getCacheList("ETHGoldenRatioMultiplierList");

        if(list.size() < 1){
            return AjaxResult.success(list);
        }

        if(sma > 0){
            //todo sma处理
            //返回处理过的数据
            //return AjaxResult.success(list);
        }

        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult getCDDList(int sma) {

        List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_CDD.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getAverageCoinDormancyList(int sma) {
        List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_DORMANCY.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getASOLList(QueryVo vo) {

        List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_ASOL.getKey(), vo.getSma());

        list = filterByTime(list,vo);

        if(list.size() < 1){
            return AjaxResult.success("当前搜索时间段无数据",list);
        }
        return CheckData(list);
    }

    @Override
    public AjaxResult getCDDWaveList(int sma) {

        List<ETHCoinDaysDescDto> list = redisService.getCacheList(ETHV2RedisName.ETH_CDDWAVE.getKey());
        if(sma > 0){
            //todo sma处理
            //返回处理过的数据
            //return AjaxResult.success(list);
        }


        return CheckData(list);
    }

    @Override
    public AjaxResult getAddressBalanceList(int sma) {

        List<ETHAddressBalanceDto> list = redisService.getCacheList(ETHV2RedisName.ETH_ADDRESS_BALANCE.getKey());

        return CheckData(list);
    }

    @Override
    public AjaxResult getAddressSupplyList(int sma) {

        List<ETHAddressBalanceDto> list = redisService.getCacheList(ETHV2RedisName.ETH_BALANCE.getKey());

        return CheckData(list);
    }

    @Override
    public AjaxResult getAddressProfitPercentList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_ADDRESS_PROFIT_RATIO.getKey(), sma);
       //todo sma
        return CheckData(list);
    }

    @Override
    public AjaxResult getAddressProfitList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_ADDRESS_PROFIT.getKey(), sma);
        //todo sma

        return CheckData(list);
    }

    @Override
    public AjaxResult getAddressLossList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_ADDRESS_LOSS.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getInflationRateList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_INFLATION_RATE.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getIssuanceList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_ISSUANCE.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getSOPRList(QueryVo vo) {

       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_SOPR.getKey(), vo.getSma());
       list = filterByTime(list,vo);

        if(list.size() < 1){
            return AjaxResult.success("当前搜索时间段无数据",list);
        }
       return CheckData(list);

    }

    @Override
    public AjaxResult getVelocityList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_VELOCITY.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getNVTRatioList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_NVT_RATIO.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getNVTSignList(int sma) {
        List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_NVT_RATIO.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getLiveLinessList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_LIVELINESS.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getFRMList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_FRM.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getSupplyProfitPercentList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_SUPPLY_PROFIT_RATIO.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getTotalSupplyProfitList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_SUPPLY_PROFIT.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getTotalSupplyLossList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_SUPPLY_LOSS.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getNUPLList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_NUPL.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getRelativeUProfitList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_RELATIVE_UNREALIZED_PROFIT.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getRelativeULossList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_RELATIVE_UNREALIZED_LOSS.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getLTHNUPLList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_LTH_NUPL.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getSTHNUPLList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_STH_NUPL.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getMarketCapList(QueryVo vo) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_MARKETCAP.getKey(), vo.getSma());
       list = filterByTime(list,vo);
       if(list.size() < 1){
            return AjaxResult.success("当前搜索时间段无数据",list);
       }
       return AjaxResult.success(list);
    }

    @Override
    public AjaxResult getRealizedCapList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_REALIZED_CAP.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getRealizedPriceList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_REALIZED_RRICE.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getMVRVRatioList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_MVRV_RATIO.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getBurnedSupplyList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_BURNED_SUPPLY.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getMintedSupplyList(int sma) {
       List<DateBigDecimalDto> list = getList(ETHV2RedisName.ETH_MINTED_SUPPLY.getKey(), sma);
        return CheckData(list);
    }

    @Override
    public AjaxResult getExchanges() {
        Set<String> exchanges = redisService.getCacheSet("ETHExchanges");
        if(exchanges.size() < 1){
            return AjaxResult.success("后台暂无数据,请稍后再试");
        }
        return AjaxResult.success(exchanges);
    }

    @Override
    public AjaxResult getExchangeBalance(EBalanceVo vo) {
        Map<String,List<DateBigDecimalDto>> map = redisService.getCacheMap("ETHExchangeBalanceMap");
        if (map.size() < 1){
            return AjaxResult.error("后台暂无数据,请稍后再试");
        }

        List<DateBigDecimalDto> list = map.get(vo.getExchange());

        if(list.size() < 1){
            return AjaxResult.error("后台暂无数据,请稍后再试");
        }

        if(vo.getSma() > 0){
            list = getSMA(list, vo.getSma());
        }
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult getPrice(QueryVo vo) {
        List<PriceDataDto> list = ethMapper.getPriceList(vo);
        return CheckData(list);
    }


    /**
     * 通过缓存获取所有数据 如果传递了sma则做sma处理
     * @param key
     * @param sma
     * @return
     */
    public List<DateBigDecimalDto> getList(String key,int sma){

        List<DateBigDecimalDto> list = new ArrayList<>();

        if(redisService.hasKey(key)){
            list = redisService.getCacheList(key);
        }

        if(sma > 0){
            //todo sma处理
            list = getSMA(list,sma);
            //返回处理过的数据
            //return AjaxResult.success(list);
        }

        return list;
    }

    /**
     * 验证list是否为空
     * @param list
     * @return
     */
    public AjaxResult CheckData(List list) {

        if(list.size() < 1){
            return AjaxResult.error(508,"后台数据获取失败，请稍后再试");
        }
        return AjaxResult.success(list);
    }

    /**
     * 通过时间筛选list
     * @param list
     * @param vo
     * @return
     */
    public List<DateBigDecimalDto> filterByTime(List<DateBigDecimalDto> list,QueryVo vo){

        if(StringUtils.isNull(vo)){
            return list;
        }

        if(StringUtils.isNotBlank(vo.getStart())){
            Date start = DateUtils.parseDate(vo.getStart());
            list = list.stream().filter(dto -> (dto.getDate().after(start) || dto.getDate().equals(start))).collect(Collectors.toList());
        }

        if(StringUtils.isNotBlank(vo.getEnd())){
            Date end = DateUtils.parseDate(vo.getEnd());
            list = list.stream().filter(dto -> (dto.getDate().before(end) || dto.getDate().equals(end))).collect(Collectors.toList());
        }

        return list;
    }

    /**
     * sma处理
     * @param list
     * @return
     */
    public List<DateBigDecimalDto> getSMA(List<DateBigDecimalDto> list,int day) {

        if (list.size()< day){
            return new ArrayList<>();
        }

        if(list.size() < 1){
            return list;
        }

        BigDecimal total = BigDecimal.ZERO;
        BigDecimal divideNumber = new BigDecimal(day);
        for(int i = 0 ; i < day ;i++){
            total =  list.get(i).getValue().add(total);
        }
        BigDecimal startY = total.divide(divideNumber, 8, BigDecimal.ROUND_HALF_UP);
        DateBigDecimalDto startDto = new DateBigDecimalDto();
        startDto.setDate(list.get(day-1).getDate());
        startDto.setValue(startY.stripTrailingZeros());

        List<DateBigDecimalDto> returnList = new ArrayList<>();
        returnList.add(startDto);
        for (int i = day; i < list.size(); i++) {

            total = total.add(list.get(i).getValue()).subtract(list.get(i-day).getValue());

            startY = total.divide(divideNumber,8,BigDecimal.ROUND_HALF_UP);

            DateBigDecimalDto dto = new DateBigDecimalDto();
            dto.setDate(list.get(i).getDate());
            //返回给前端的参数需要删除多余的0
            dto.setValue(startY.stripTrailingZeros());

            returnList.add(dto);
        }
        return returnList;
    }

}
