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.utils.DateUtils;
import com.jxy.common.core.utils.StringUtils;
import com.jxy.common.core.web.Result.AjaxResult;
import com.jxy.marketall.dto.OHLCPriceDto;
import com.jxy.marketall.entity.BiAn;
import com.jxy.marketall.entity.OHLCprice;
import com.jxy.marketall.enums.OHLCpriceCoinType;
import com.jxy.marketall.mapper.BiAnMapper2;
import com.jxy.marketall.service.NodeJsMarketFeign;
import com.jxy.marketall.service.OHLCPriceService;
import com.jxy.marketall.utils.EnumUtils;
import com.jxy.marketall.vo.BiAnVo;
import com.jxy.marketall.vo.CoinVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * @Description 每日币价查询业务处理
 * @Date 2022/6/2 9:37
 * @Author 杜懿
 */
@Service
public class OHLCPriceServiceImpl implements OHLCPriceService {

    @Autowired
    private NodeJsMarketFeign nodeJsMarketFeign;

    @Autowired
    private BiAnMapper2 biAnMapper;

    @Override
    public AjaxResult findOHLCPriceByCoin(CoinVo coinVo) {

        HashMap<String,String> map = new HashMap<>();
        String coin = coinVo.getCoin();

        /** 条件范围 */
        if(!EnumUtils.isInclude(OHLCpriceCoinType.class,coin)){
            //todo 自定义异常
            throw new  RuntimeException();
        }

        OHLCpriceCoinType ohlCpriceCoinType = (OHLCpriceCoinType) EnumUtils.get(OHLCpriceCoinType.class,coin);
        map.put("coin",ohlCpriceCoinType.getInfo());

        /** 查询的时间差 默认为0 */
        int monthDiff = 0;
        //时间参数判断标记 默认为空 传值了则为true
        boolean flag = false;

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

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

            flag = true;
        }

        /** 调用查询接口 */
        JSONObject returnDto = nodeJsMarketFeign.OHLCprice(map);

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

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

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

        if(!flag){
            //没传时间 返回所有
            for (int i = 0; i < list.size(); i++) {

                OHLCPriceDto ohlcPriceDto = new OHLCPriceDto();
                OHLCprice entry = list.get(i);
                BeanUtils.copyProperties(entry,ohlcPriceDto);
                ohlcPriceDto.setTime(entry.getDate());

                dataList.add(i,ohlcPriceDto);
            }
            return AjaxResult.success("按日返回数据",dataList);
        }

        monthDiff = DateUtils.getMonthDiff(list.get(0).getDate(),list.get(list.size()-1).getDate());
        /** 根据条件判断处理数据 */
        if(monthDiff <= 6){
                /** 半年 按日返回数据 */

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

                    OHLCPriceDto ohlcPriceDto = new OHLCPriceDto();
                    OHLCprice entry = list.get(i);
                    BeanUtils.copyProperties(entry,ohlcPriceDto);
                    ohlcPriceDto.setTime(entry.getDate());

                    dataList.add(i,ohlcPriceDto);
                }
                return AjaxResult.success("按日返回数据",dataList);

            }
        else if(monthDiff <= 24) {

            /** 两年内 按周返回数据 */
            int startWeek = LocalDate.parse(coinVo.getStart()).getDayOfWeek().getValue();

            //周数
            int week = 1;

            OHLCPriceDto ohlcPriceDto = new OHLCPriceDto();

            Date time = DateUtils.parseDate(coinVo.getStart());

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

                OHLCprice entry = list.get(i - startWeek);

                ohlcPriceDto.setOpenPrice(add(ohlcPriceDto.getOpenPrice(),entry.getOpenPrice()));
                ohlcPriceDto.setHighestPrice(add(ohlcPriceDto.getHighestPrice(),entry.getHighestPrice()));
                ohlcPriceDto.setLowestPrice(add(ohlcPriceDto.getLowestPrice(),entry.getLowestPrice()));
                ohlcPriceDto.setClosePrice(add(ohlcPriceDto.getClosePrice(),entry.getOpenPrice()));;

                if(i%7 == 0 || i== (list.size() + startWeek - 1)){

                    String weekendTime = DateUtils.dateTime(entry.getDate());
                    ohlcPriceDto.setId(week);
                    ohlcPriceDto.setTime(time);
                    //统计一周数据
                    int count = week - 1;
                    //System.out.println(count);
                    dataList.add(count,ohlcPriceDto);

                    week++;
                    //下条数据开始时间+1
                    Date date = entry.getDate();
                    Calendar   calendar = new GregorianCalendar();
                    calendar.setTime(date);
                    calendar.add(calendar.DATE,1);
                    time = calendar.getTime();


                    /** 因为复用ohlcPriceDto 所有添加之后数据要还原为0 */
                    ohlcPriceDto = new OHLCPriceDto();

                }
            }

            return AjaxResult.success("按周返回数据",dataList);

        }
        else {
            /** 两年以上 按月返回数据 */
            //判断开始时间是第几个月
            int startMonth = LocalDate.parse(coinVo.getStart()).getMonthValue();

            /** 返回给前端的数据 key从1开始 value是每个月的数据（Map集合） */

            /** 每日数据 */
            OHLCPriceDto ohlcPriceDto = new OHLCPriceDto();

            int count = 1;

            Date time = DateUtils.parseDate(coinVo.getStart());

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

                OHLCprice entry = list.get(i);

                //数据日期转为localdate
                LocalDate entryDay = entry.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                //当前月数 用于判断
                int entryMonth = entryDay.getMonthValue();

                LocalDate lastDayOfMonth = entryDay.with(TemporalAdjusters.lastDayOfMonth());
                //数据日期和当月最后一天差值 等于0表示最后一天
                int days = Period.between(entryDay, lastDayOfMonth).getDays();

                //判断
                if(entryMonth == startMonth){

                    /** 将数据加到当月数据中 */

                    ohlcPriceDto.setOpenPrice(add(ohlcPriceDto.getOpenPrice(),entry.getOpenPrice()));

                    ohlcPriceDto.setHighestPrice(add(ohlcPriceDto.getHighestPrice(),entry.getHighestPrice()));

                    ohlcPriceDto.setLowestPrice(add(ohlcPriceDto.getLowestPrice(),entry.getLowestPrice()));

                    ohlcPriceDto.setClosePrice(add(ohlcPriceDto.getClosePrice(),entry.getClosePrice()));;

                }

                if(days == 0 || i == (list.size() - 1)){

                    //是当月最后一天 所以下条数据月数需要变为下一个月 且要将当月数据放入返回前端的map集合
                    //数据放入返回队列
                    ohlcPriceDto.setId(count);


                    //设置返回数据日期为每月1号
                    Calendar ca = new GregorianCalendar();
                    ca.setTime(time);
                    ca.add(ca.MONTH,0);
                    ca.set(ca.DAY_OF_MONTH,1);
                    ohlcPriceDto.setTime(ca.getTime());

                    int putId = count - 1;
                    //System.out.println(putId);
                    dataList.add(putId,ohlcPriceDto);

                    //局部数据修正
                    count++;

                    if(startMonth == 12){
                        //如果已是每年最后一月 则从1开始算
                        startMonth = 0;
                    }
                    startMonth++;

                    Date date = entry.getDate();
                    Calendar   calendar = new GregorianCalendar();
                    calendar.setTime(date);
                    calendar.add(calendar.DATE,1);
                    time = calendar.getTime();

                    ohlcPriceDto = new OHLCPriceDto();
                }
            }

            return AjaxResult.success("按月返回数据",dataList);
        }

    }




    public static double add(double v1, double v2)

    {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));

        BigDecimal b2 = new BigDecimal(Double.toString(v2));

        return b1.add(b2).doubleValue();

    }
}
