package com.jxy.marketall.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jxy.common.core.text.DoubleCalculate;
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.entity.BiAn;
import com.jxy.marketall.entity.NDAQ;
import com.jxy.marketall.mapper.BiAnMapper2;
import com.jxy.marketall.mapper.NDAQMapper;
import com.jxy.marketall.service.NDAQService;
import com.jxy.marketall.service.NodeJsMarketFeign;
import com.jxy.marketall.vo.BiAnVo;
import com.jxy.marketall.vo.QueryVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * @Description NDAQ查询业务处理
 * @Date 2022/5/19 17:51
 * @Author 杜懿
 */
@Service
public class NDAQServiceImpl implements NDAQService {

    @Autowired
    private NodeJsMarketFeign nodeJsMarketFeign;

    @Autowired
    private NDAQMapper ndaqMapper;

    @Autowired
    private BiAnMapper2 biAnMapper;

    @Autowired
    private RedisService redisService;

    @Override
    public AjaxResult findNDAQByTime(QueryVo queryVo) {

        HashMap<String,String> map = new HashMap<>();

        /** 判断起止时间是否为空 */
        if(!StringUtils.isEmpty(queryVo.getStart()) && !StringUtils.isEmpty(queryVo.getEnd())){

            map.put("start",queryVo.getStart());
            map.put("end",queryVo.getEnd());

        }

        JSONObject returnDto = nodeJsMarketFeign.NDAQ(map);

        JSONArray data = JSON.parseArray(JSONObject.toJSONString(returnDto.get("data")));

        List<NDAQ> list = JSONObject.parseArray(data.toJSONString(),NDAQ.class);

        List<NDAQDto> dataList = new ArrayList<>();

        for (int i = 0; i < list.size(); i++) {

            NDAQDto dataDto = new NDAQDto();
            NDAQ entry = list.get(i);
            BeanUtils.copyProperties(entry,dataDto);
            dataDto.setTime(entry.getDate());
            dataDto.setOpenPrice(entry.getOpen_price());
            dataDto.setHighestPrice(entry.getHigh_price());
            dataDto.setLowestPrice(entry.getLow_price());
            dataDto.setClosePrice(entry.getClose_price());
            dataList.add(i,dataDto);

        }

        return AjaxResult.success(dataList);
    }

    @Override
    public AjaxResult findOHLCByTime(QueryVo vo) {
        //默认查询最后六个月数据
        if(StringUtils.isEmpty(vo.getStart()) && StringUtils.isEmpty(vo.getEnd())){
            NDAQOHLCDto lastOHLC = ndaqMapper.findLastOHLC();
            if(StringUtils.isNull(lastOHLC)){
                return AjaxResult.error("数据库没数据，请通知管理员");
            }
            vo.setEnd(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,lastOHLC.getDate()));
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(lastOHLC.getDate());
            calendar.add(calendar.MONTH,-6);
            vo.setStart(DateUtils.dateTime(calendar.getTime()));
        }
        List<NDAQOHLCDto> list = ndaqMapper.getOHLCList(vo);

        //倒序
        Collections.reverse(list);
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult findMaByTime(QueryVo vo) {
        //默认查询最后六个月数据
        if(StringUtils.isEmpty(vo.getStart()) && StringUtils.isEmpty(vo.getEnd())){
            NDAQMaDto lastMa = ndaqMapper.findLastMa();
            if(StringUtils.isNull(lastMa)){
                return AjaxResult.error("数据库没数据，请通知管理员");
            }
            vo.setEnd(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,lastMa.getDate()));
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(lastMa.getDate());
            calendar.add(calendar.MONTH,-6);
            vo.setStart(DateUtils.dateTime(calendar.getTime()));
        }
        List<NDAQMaDto> list = ndaqMapper.getMaList(vo);
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult getNBPriceByNDAQTime(QueryVo vo) {

        //查询纳斯达克K线 获得时间线
        //返回降序排序结果
        List<NDAQOHLCDto> ohlcList = ndaqMapper.getOHLCList(vo);
        if(ohlcList.size() < 1){
            return AjaxResult.success(new ArrayList<>());
        }

        BiAnVo biAnVo = new BiAnVo();
        biAnVo.setSymbol("1dBTCUSDT");
        biAnVo.setStart(DateUtils.dateTime(ohlcList.get(ohlcList.size()-1).getDate()));
        /** BTC price数据库时间是北京时间 */
        Calendar cal = new GregorianCalendar();
        cal.setTime(ohlcList.get(0).getDate());
        cal.add(cal.DATE,1);
        biAnVo.setEnd(DateUtils.dateTime(cal.getTime()));

        //查询BTC price
        List<BiAn> biAnList = biAnMapper.selectLongTimeDataByCondition(biAnVo);

        if(ohlcList.size() < 1){
            return AjaxResult.success(new ArrayList<>());
        }

        //整合数据
        List<NBohlcDto> nbohlcList = new ArrayList<>();
        for (int i = 0; i < ohlcList.size();i++){
            NBohlcDto dto = new NBohlcDto();
            dto.setNdaqOpenPrice(ohlcList.get(i).getOpenPrice());
            dto.setNdaqHighPrice(ohlcList.get(i).getHighestPrice());
            dto.setNdaqLowPrice(ohlcList.get(i).getLowestPrice());
            dto.setNdaqClosePrice(ohlcList.get(i).getClosePrice());
            dto.setVolume(ohlcList.get(i).getAmount());
            dto.setDate(ohlcList.get(i).getDate());
            nbohlcList.add(dto);
        }

        nbohlcList.stream().forEach(n -> biAnList.stream().anyMatch(b -> {
            if(DateUtils.isSameDay(n.getDate(),b.getOpenTime())){
                n.setBtcOpenPrice(b.getOpenPrice());
                n.setBtcHighPrice(b.getHighPrice());
                n.setBtcLowPrice(b.getLowPrice());
                n.setBtcClosePrice(b.getClosePrice());
            }
            return false;
        }));

        Collections.reverse(nbohlcList);
        return AjaxResult.success(nbohlcList);
    }

    @Override
    public AjaxResult getNBPriceByBTCTime(QueryVo vo) {

        List<NBohlcDto> list = redisService.getCacheList("NBPriceByBTCTimeList");

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

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

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

        return AjaxResult.success(list);
        ////构造BTCprice查询条件
        //BiAnVo biAnVo = new BiAnVo();
        //biAnVo.setSymbol("1dBTCUSDT");
        //biAnVo.setStart(vo.getStart());
        //biAnVo.setEnd(vo.getEnd());
        //
        ////根据查询BTC priceK线 获取时间线
        //List<BiAn> biAnList = biAnMapper.selectLongTimeDataByCondition(biAnVo);
        //System.out.println("btc价格K线"+biAnList);
        //
        //if(biAnList.size() < 1){
        //    return AjaxResult.success("根据BTC币价时间线没有找到纳斯达克K线数据！",biAnList);
        //}
        //
        //Calendar cal = new GregorianCalendar();
        //cal.setTime(biAnList.get(biAnList.size()-1).getOpenTime());
        //cal.add(cal.DATE,1);
        //vo.setEnd(DateUtils.dateTime(cal.getTime()));
        //vo.setStart(DateUtils.dateTime(biAnList.get(0).getOpenTime()));
        //
        //System.out.println("NDAQ查询条件:"+vo);
        ////返回降序排序结果
        //List<NDAQOHLCDto> ohlcList = ndaqMapper.getOHLCList(vo);
        //System.out.println("NDAQ查询结果:"+ohlcList);
        //if(ohlcList.size() < 1){
        //    return AjaxResult.success("该时间段内没有查询到币价数据，没有与之匹配的纳斯达克数据返回！",ohlcList);
        //}
        //
        ////整合数据
        //List<NBohlcDto> nbohlcList = new ArrayList<>();
        ////第一步 根据时间线构造返回结果list 并填充btc币价相关数据
        //for(int i = 0; i < biAnList.size(); i++){
        //    NBohlcDto dto = new NBohlcDto();
        //    dto.setBtcOpenPrice(biAnList.get(i).getOpenPrice());
        //    dto.setBtcHighPrice(biAnList.get(i).getHighPrice());
        //    dto.setBtcLowPrice(biAnList.get(i).getLowPrice());
        //    dto.setBtcClosePrice(biAnList.get(i).getClosePrice());
        //    dto.setVolume(biAnList.get(i).getVolume());
        //    dto.setDate(biAnList.get(i).getOpenTime());
        //    nbohlcList.add(dto);
        //}
        //
        //
        ////第二步 把纳斯达克数据赋值到返回队列nbohlcList
        //nbohlcList.stream().forEach(n -> ohlcList.stream().anyMatch(o -> {
        //    if(DateUtils.isSameDay(n.getDate(),o.getDate())){
        //        n.setNdaqOpenPrice(o.getOpenPrice());
        //        n.setNdaqHighPrice(o.getHighestPrice());
        //        n.setNdaqLowPrice(o.getLowestPrice());
        //        n.setNdaqClosePrice(o.getClosePrice());
        //    }
        //    return false;
        //}));
        //
        ////第三步 根据纳斯达克K线数据ohlcList 构造缺失日期数据
        //List<NDAQOHLCDto> addList = new ArrayList<>();
        //    //遍历查询到的纳斯达克数据(降序) 构造缺失日期数据 注意
        //for(int i = 0 ; i < ohlcList.size() - 1; i++){
        //    NDAQOHLCDto preDto = ohlcList.get(i);
        //    NDAQOHLCDto nextDto = ohlcList.get(i+1);
        //    Date preDate = DateUtils.parseDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, preDto.getDate()));
        //    Date nextDate = DateUtils.parseDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, nextDto.getDate()));
        //    Long diff = DateUtils.getDateDiff(preDate, nextDate);
        //
        //    if(diff > 1){
        //        NDAQOHLCDto dto = new NDAQOHLCDto();
        //        BeanUtils.copyProperties(preDto,dto);
        //
        //        double opDiff = DoubleCalculate.divide(DoubleCalculate.subtract(preDto.getOpenPrice(), nextDto.getOpenPrice()), diff, 2);
        //        double hpDiff = DoubleCalculate.divide(DoubleCalculate.subtract(preDto.getHighestPrice(), nextDto.getHighestPrice()), diff, 2);
        //        double lpDiff = DoubleCalculate.divide(DoubleCalculate.subtract(preDto.getLowestPrice(), nextDto.getLowestPrice()), diff, 2);
        //        double cpDiff = DoubleCalculate.divide(DoubleCalculate.subtract(preDto.getClosePrice(), nextDto.getClosePrice()), diff, 2);
        //
        //        for (int k = 1 ; k < diff ;k++){
        //
        //            dto.setOpenPrice(DoubleCalculate.subtract(dto.getOpenPrice(),opDiff));
        //            dto.setHighestPrice(DoubleCalculate.subtract(dto.getHighestPrice(),hpDiff));
        //            dto.setLowestPrice(DoubleCalculate.subtract(dto.getLowestPrice(),lpDiff));
        //            dto.setClosePrice(DoubleCalculate.subtract(dto.getClosePrice(),cpDiff));
        //
        //            Calendar ca = new GregorianCalendar();
        //            ca.setTime(dto.getDate());
        //            ca.add(ca.DATE,-1);
        //            dto.setDate(ca.getTime());
        //
        //            NDAQOHLCDto addDto = new NDAQOHLCDto();
        //            BeanUtils.copyProperties(dto,addDto);
        //
        //            addList.add(addDto);
        //        }
        //    }
        //}
        //
        ////第四步 把缺失日期数据复制到返回队列nbohlcList
        //for (int i = 0 ; i < addList.size() ; i++){
        //    NDAQOHLCDto enrty = addList.get(i);
        //    NBohlcDto dto = nbohlcList.stream().filter(n -> DateUtils.isSameDay(enrty.getDate(), n.getDate())).findAny().orElse(null);
        //    if(StringUtils.isNotNull(dto)){
        //        nbohlcList.get(nbohlcList.indexOf(dto)).setNdaqOpenPrice(enrty.getOpenPrice());
        //        nbohlcList.get(nbohlcList.indexOf(dto)).setNdaqHighPrice(enrty.getHighestPrice());
        //        nbohlcList.get(nbohlcList.indexOf(dto)).setNdaqLowPrice(enrty.getLowestPrice());
        //        nbohlcList.get(nbohlcList.indexOf(dto)).setNdaqClosePrice(enrty.getClosePrice());
        //    }
        //}
        //
        //
        ////特殊情况处理： 周一数据没之前 第三步会失效导致周六周日数据仍为0 应该改为周五数据
        //for(int i = nbohlcList.size() - 20 ; i < nbohlcList.size() ; i++  ){
        //    NBohlcDto entry = nbohlcList.get(i);
        //    if(entry.getNdaqOpenPrice() == 0){
        //        nbohlcList.get(i).setNdaqOpenPrice(nbohlcList.get(i-1).getNdaqOpenPrice());
        //        nbohlcList.get(i).setNdaqHighPrice(nbohlcList.get(i-1).getNdaqHighPrice());
        //        nbohlcList.get(i).setNdaqLowPrice(nbohlcList.get(i-1).getNdaqLowPrice());
        //        nbohlcList.get(i).setNdaqClosePrice(nbohlcList.get(i-1).getNdaqClosePrice());
        //    }
        //}
        ////Collections.reverse(nbohlcList);
        //return AjaxResult.success(nbohlcList);
    }
}
