package com.jxy.marketall.service.impl;

import com.jxy.common.core.text.Convert;
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.marketall.dto.*;
import com.jxy.marketall.entity.KeyValue;
import com.jxy.marketall.mapper.ExchangeMapper;
import com.jxy.marketall.mapper.ExchangeV2Mapper;
import com.jxy.marketall.service.ExchangeService;
import com.jxy.marketall.vo.BourseVo;
import com.jxy.marketall.vo.QueryVo;
import com.jxy.marketall.vo.TimeZoneVo;
import com.jxy.marketall.vo.VolumeProfileVo;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.apache.bcel.generic.RET;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.swing.border.Border;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Description 日交易数查询业务处理
 * @Date 2022/5/19 17:51
 * @Author 杜懿
 */
@Service
public class ExchangeServiceImpl implements ExchangeService {

    @Autowired
    private ExchangeMapper exchangeMapper;

    @Autowired
    private ExchangeV2Mapper exchangeV2Mapper;

    /**
     * 使用https访问接口,并忽略ssl证书验证
     */
    @Resource(name = "restTemplateIgnoreSSL")
    private RestTemplate restTemplateIgnoreSSL;


    private static String TAKERLONGSHORTRATIO_PRE="longshortratio";

    private static String TIMEZONE_PRE="change_";

    @Override
    public AjaxResult getFundingRateByTime(BourseVo vo) {

        List<ExchangeTempDto> list = exchangeMapper.getFundingRateByTime(vo);
        List<DateBigDecimalDto> returnList =
                list.stream().map(
                        e -> {
                            DateBigDecimalDto dto = new DateBigDecimalDto();
                            dto.setDate(new Date(e.getTs()));
                            dto.setValue(e.getValueA().stripTrailingZeros());
                            return dto;
                        }).collect(Collectors.toList());

        //做sma处理 如果sma为0则原数据不变
        returnList = getSMA(returnList, vo.getSma());

        if(StringUtils.isNotBlank(vo.getStart())){
            Date start = DateUtils.parseDate(vo.getStart());
            returnList = returnList.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());
            returnList = returnList.stream().filter(dto -> (dto.getDate().before(end) || dto.getDate().equals(end))).collect(Collectors.toList());
        }

        return AjaxResult.success(returnList);
    }

    @Override
    public AjaxResult getOpenInterestByTime(BourseVo vo) {
        BourseVo queryDBVo = new BourseVo();
        BeanUtils.copyProperties(vo,queryDBVo);

        if(StringUtils.isNotBlank(vo.getStart())){
            Date start = DateUtils.parseDate(vo.getStart());
            queryDBVo.setStart(Convert.toStr(start.getTime()));
        }

        if(StringUtils.isNotBlank(vo.getEnd())){
            Date end = DateUtils.parseDate(vo.getEnd());
            queryDBVo.setEnd(Convert.toStr(end.getTime()));
        }

        List<ExchangeTempDto> list = exchangeMapper.getOpenInterestByTime(queryDBVo);
        List<DateBigDecimalDto> returnList =
                list.stream().map(
                        e -> {
                            DateBigDecimalDto dto = new DateBigDecimalDto();
                            dto.setDate(new Date(e.getTs()));
                            dto.setValue(e.getValueA().stripTrailingZeros());
                            return dto;
                        }).collect(Collectors.toList());

        //做sma处理 如果sma为0则原数据不变
        returnList = getSMA(returnList, vo.getSma());

        //if(returnList.size() < 1){
        //
        //}

        if(StringUtils.isNotBlank(vo.getStart())){
            Date start = DateUtils.parseDate(vo.getStart());
            returnList = returnList.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());
            returnList = returnList.stream().filter(dto -> (dto.getDate().before(end) || dto.getDate().equals(end))).collect(Collectors.toList());
        }

        Collections.reverse(returnList);

        return AjaxResult.success(returnList);
    }

    @Override
    public AjaxResult getTakerlongshortRatioByTime(BourseVo vo) {

        List<ExchangeTempDto> list = exchangeMapper.getTakerLongShortRatioByTime(vo);
        List<TakerLongShortRatioDto> returnList =
                list.stream().map(
                        e -> {
                            TakerLongShortRatioDto dto = new TakerLongShortRatioDto();
                            dto.setDate(new Date(e.getTs()));
                            dto.setBuyVol(e.getValueA().stripTrailingZeros());
                            dto.setSellVol(e.getValueB().stripTrailingZeros());
                            dto.setBuySellRatio(e.getValueC().stripTrailingZeros());
                            return dto;}
                            ).collect(Collectors.toList());



        if(StringUtils.isNotBlank(vo.getStart())){
            Date start = DateUtils.parseDate(vo.getStart());
            returnList = returnList.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());
            returnList = returnList.stream().filter(dto -> (dto.getDate().before(end) || dto.getDate().equals(end))).collect(Collectors.toList());
        }

        //interval范围 默认5分钟"5m","15m","30m","1h","2h","4h","6h","12h","1d"
        //按时间间隔处理数据
        switch (vo.getInterval()){
            case "5m":
                //数据默认就是5分钟 interval为5m时不对数据筛选
                break;
            case "15m":
                returnList = returnList.stream().filter(e -> (e.getDate().getMinutes() % 15 == 0)).collect(Collectors.toList());break;
            case "30m":
                returnList = returnList.stream().filter(e -> (e.getDate().getMinutes() % 30 == 0)).collect(Collectors.toList());break;
            case "1h":
                returnList = returnList.stream().filter(e -> (e.getDate().getMinutes() == 0)).collect(Collectors.toList());break;
            case "2h":
                returnList = returnList.stream().filter(e -> ((e.getDate().getHours() % 2 == 0) && (e.getDate().getMinutes() == 0))).collect(Collectors.toList());break;
            case "4h":
                returnList = returnList.stream().filter(e -> ((e.getDate().getHours() % 4 == 0) && (e.getDate().getMinutes() == 0))).collect(Collectors.toList());break;
            case "6h":
                returnList = returnList.stream().filter(e -> ((e.getDate().getHours() % 6 == 0) && (e.getDate().getMinutes() == 0))).collect(Collectors.toList());break;
            case "12h":
                returnList = returnList.stream().filter(e -> ((e.getDate().getHours() % 12 == 0) && (e.getDate().getMinutes() == 0))).collect(Collectors.toList());break;
            case "1d":
                returnList = returnList.stream().filter(e -> ((e.getDate().getHours() == 0) && (e.getDate().getMinutes() == 0))).collect(Collectors.toList());break;
        }

        return AjaxResult.success(returnList);
    }

    @Override
    public AjaxResult getVolumeProfile(VolumeProfileVo vo) {

        if(StringUtils.isNull(vo.getStart()) || StringUtils.isNull(vo.getEnd())){
            return AjaxResult.error("时间传参缺失");
        }
        System.out.println("参数验证完毕，开始请求第三方接口");
        long t1 = System.currentTimeMillis();
        String url = "https://54.254.93.204:11446/binance/vpvr?startTime="+vo.getStart()+"&endTime="+vo.getEnd()+"&count="+vo.getCount();

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(HttpHeaders.AUTHORIZATION,"Basic bGl6aXh1YW46THp4MjAyMUA=");
        HttpEntity<String> httpEntity = new HttpEntity(null, httpHeaders);

        ResponseEntity<ArrayList> exchange = restTemplateIgnoreSSL.exchange(url, HttpMethod.GET, httpEntity, ArrayList.class);
        long t2 = System.currentTimeMillis();
        System.out.println("调用接口耗时"+(t2-t1)+"ms,响应结果为"+exchange);
        List<VolumeProfileDto> list = new ArrayList<>();
        if (HttpStatus.OK == exchange.getStatusCode()){
            ArrayList dataList = exchange.getBody();
            for(int i=0; i< dataList.size();i++){
                ArrayList dataArray = (ArrayList) dataList.get(i);
                VolumeProfileDto dto = new VolumeProfileDto();
                dto.setPrice(Convert.toDouble(dataArray.get(0)));
                dto.setVolume(Convert.toInt(dataArray.get(1)));
                list.add(dto);
            }
        }else{
            return AjaxResult.error("后台请求异常，请联系后台管理员");
        }
        long t3 = System.currentTimeMillis();
        System.out.println("数量数据耗时"+(t3-t2)+"ms,处理结果"+list);
        return AjaxResult.success(list);

    }

    @Override
    public AjaxResult getTimeZoneBuyPowerList(TimeZoneVo vo) {
        if(StringUtils.isNull(vo.getZone())){
            return AjaxResult.error("时区传参不能为空");
        }
        if(StringUtils.isNull(vo.getCoin())){
            return AjaxResult.error("货币类型不能为空");
        }
        String[] tz={"us","asia","eu"};
        if(!ArrayUtils.contains(tz,vo.getZone().toLowerCase())){
            return AjaxResult.error("时区传参异常");
        }
        String[] coins={"BTC","ETH"};
        if(!ArrayUtils.contains(coins,vo.getCoin().toUpperCase())){
            return AjaxResult.error("币种传参异常");
        }

        List<DateBigDecimalDto> list = new ArrayList<>();
        if("BTC".equals(vo.getCoin().toUpperCase())){
            list = exchangeV2Mapper.getBTCBuyPowerByTimeZone(TIMEZONE_PRE.concat(vo.getZone().toLowerCase()));
        }else if("ETH".equals(vo.getCoin().toUpperCase())){
            list = exchangeV2Mapper.getETHBuyPowerByTimeZone(TIMEZONE_PRE.concat(vo.getZone().toLowerCase()));
        }

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

        return AjaxResult.success(list);

    }

    @Override
    public AjaxResult getBTCBalanceList(QueryVo vo) {
        return null;
    }

    @Override
    public AjaxResult getETHBalanceList(QueryVo vo) {
        return null;
    }


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

        if(day <=0 ){
            return list;
        }

        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-7).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;
    }
}
