package com.njcn.device.pq.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.njcn.device.pq.mapper.RStatIntegrityDMapper;
import com.njcn.device.pq.mapper.RStatOnlinerateDMapper;
import com.njcn.device.pq.pojo.param.OnlineRateParam;
import com.njcn.device.pq.pojo.param.PulicTimeParam;
import com.njcn.device.pq.pojo.param.PulicTimeStatisParam;
import com.njcn.device.pq.pojo.vo.*;
import com.njcn.device.pq.service.CommunicateService;
import com.njcn.device.pq.service.LineService;
import com.njcn.device.pq.utils.PublicDateUtil;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * @author denghuajun
 * @date 2022/2/28
 */
@Service
@AllArgsConstructor
public class CommunicateServiceImpl implements CommunicateService {

    private final LineService lineService;

    private final RStatOnlinerateDMapper onlinerateDMapper;

    private final RStatIntegrityDMapper integrityDMapper;

    @Override
    public CommunicateVO getComFlagInfoData(PulicTimeParam pulicTimeParam) {
        //根据监测点id获取终端状态信息
        return lineService.getComFlagInfoData(pulicTimeParam.getId(), pulicTimeParam.getSearchBeginTime(), pulicTimeParam.getSearchEndTime());
    }

    @Override
    public CommunicateStatisticsVO getRunInfoData(PulicTimeStatisParam pulicTimeStatisParam) {
        CommunicateStatisticsVO communicateStatisticsVO = new CommunicateStatisticsVO();
        //根据监测点id获取终端id
        String devId = lineService.getLineIdByDevId(pulicTimeStatisParam.getId());
        List<Float> floatList = new ArrayList<>();
        List<Float> floats = new ArrayList<>();
        floatList.add( getCondition(pulicTimeStatisParam.getId(), pulicTimeStatisParam.getSearchBeginTime(), pulicTimeStatisParam.getSearchEndTime(), 0) );
        floats.add( getCondition(devId, pulicTimeStatisParam.getSearchBeginTime(), pulicTimeStatisParam.getSearchEndTime(), 1) );
        if (StringUtils.isNotBlank(pulicTimeStatisParam.getPeriodBeginTime()) && StringUtils.isNotBlank(pulicTimeStatisParam.getPeriodEndTime())) {
            floatList.add( getCondition(pulicTimeStatisParam.getId(), pulicTimeStatisParam.getPeriodBeginTime(), pulicTimeStatisParam.getPeriodEndTime(), 0) );
            floats.add( getCondition(devId, pulicTimeStatisParam.getPeriodBeginTime(), pulicTimeStatisParam.getPeriodEndTime(), 1) );
        }
        communicateStatisticsVO.setOnlineRateData(floats);
        communicateStatisticsVO.setIntegrityData(floatList);
        return communicateStatisticsVO;
    }

    @SneakyThrows
    @Override
    public List<DeviceOnlineDataVO> getRunOnlineRateData(PulicTimeParam pulicTimeParam) {
        List<DeviceOnlineDataVO> deviceOnlineDataList = new ArrayList<>();
        //根据监测点id获取终端id
        String devId = lineService.getLineIdByDevId(pulicTimeParam.getId());
        DecimalFormat decimalFormat = new DecimalFormat(".00");
        Float floatList;
        if (pulicTimeParam.getTimeFlag() == 0) {
            // 获取两个时间的之间的月份
            List<String> intervalTime = this.getIntervalTime(pulicTimeParam.getSearchBeginTime(), pulicTimeParam.getSearchEndTime());
            for (String interTime : intervalTime) {
                DeviceOnlineDataVO inter = new DeviceOnlineDataVO();
                String startTime, endTime;
                inter.setMonth(interTime.substring(5));
                inter.setYear(interTime.substring(0, 4));
                inter.setDay("/");
                startTime = PublicDateUtil.getFisrtDayOfMonth(Integer.parseInt(interTime.substring(0, 4)), Integer.parseInt(interTime.substring(5)));
                endTime = PublicDateUtil.getLastDayOfMonth(Integer.parseInt(interTime.substring(0, 4)), Integer.parseInt(interTime.substring(5)));
                floatList = getCondition(devId, startTime, endTime, 1);
                if (floatList == 0) {
                    inter.setOnlineRate(3.14159f);
                } else {
                    inter.setOnlineRate(Float.parseFloat(decimalFormat.format(floatList)));
                }
                deviceOnlineDataList.add(inter);
            }
        } else {
            List<String> intervalTime = this.getIntervalTime(pulicTimeParam.getSearchBeginTime(),pulicTimeParam.getSearchEndTime());
            for (int j = 0; j < intervalTime.size(); j++) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                Date dt ;
                Date dtDate;
                if(j==0){
                    dt= simpleDateFormat.parse(pulicTimeParam.getSearchBeginTime());
                }else{
                    String startTime = PublicDateUtil.getFisrtDayOfMonth(Integer.parseInt(intervalTime.get(j).substring(0, 4)), Integer.parseInt(intervalTime.get(j).substring(5)));
                    dt= simpleDateFormat.parse(startTime);

                }
                int beginDay = Integer.valueOf(String.format("%td", dt));
                if(j==intervalTime.size()-1){
                    dtDate= simpleDateFormat.parse(pulicTimeParam.getSearchEndTime());
                }else{
                    String startTime = PublicDateUtil.getLastDayOfMonth(Integer.parseInt(intervalTime.get(j).substring(0, 4)), Integer.parseInt(intervalTime.get(j).substring(5)));
                    dtDate= simpleDateFormat.parse(startTime);
                }
                Integer year = Integer.valueOf(String.format("%tY", dt));
                Integer mon = Integer.valueOf(String.format("%tm", dt));

                Integer day = Integer.valueOf(String.format("%td", dtDate));
                List<String> dayTime = this.getIntervalDateTime(year,beginDay, mon, day);
                for (String interTime : dayTime) {
                    DeviceOnlineDataVO inter = new DeviceOnlineDataVO();
                    String startTime, endTime;
                    inter.setMonth(interTime.substring(5, 7));
                    inter.setYear(interTime.substring(0, 4));
                    inter.setDay(interTime.substring(8));
                    startTime =simpleDateFormat.format(DateUtil.beginOfDay(DateUtil.parse(interTime)));
                    endTime = simpleDateFormat.format(DateUtil.endOfDay(DateUtil.parse(interTime)));
                    floatList = getCondition(devId, startTime, endTime, 1);
                    if (floatList == 0) {
                        inter.setOnlineRate(3.14159f);
                    } else {
                        inter.setOnlineRate(Float.parseFloat(decimalFormat.format(floatList)));
                    }
                    deviceOnlineDataList.add(inter);
                }
            }

        }
        return deviceOnlineDataList;
    }

    /**
     * influxDB相关操作
     * 查询监测点的数据完整性
     */
    private Float getCondition(String lineList, String startTime, String endTime, Integer state) {
        final Float[] resultList = {0.0f};
        OnlineRateParam param=new OnlineRateParam();
        param.setIds(Arrays.asList(lineList));
        param.setStartTime( DateUtil.beginOfDay(DateUtil.parse(startTime)).toString());
        param.setEndTime( DateUtil.endOfDay(DateUtil.parse(endTime)).toString());
        if (state == 1) {
            //在线率
            List<RStatOnlinerateVO> onlineRateByDevIds = onlinerateDMapper.getOnlineRateByDevIds(param);
            if (CollUtil.isNotEmpty(onlineRateByDevIds)) {
                onlineRateByDevIds.forEach(po -> {
                    //数据完整性 保留四位小数
                    resultList[0] = po.getOnlineRate() == null ? null : BigDecimal.valueOf(Float.parseFloat(po.getOnlineRate().toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
                });
            }
        } else {
            //数据完整率
            List<RStatIntegrityVO> onIntegrityByIds = integrityDMapper.getOnIntegrityByIds(param);
            if (CollUtil.isNotEmpty(onIntegrityByIds)) {
                onIntegrityByIds.forEach(po -> {
                    //数据完整性 保留四位小数
                    resultList[0] = po.getIntegrityRate() == null ? null : BigDecimal.valueOf(Float.parseFloat(po.getIntegrityRate().toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
                });
            }
        }
        return resultList[0];
    }

    /**
     * 根据用户选择的时间区间返回月份日期
     */
    @SneakyThrows
    private List<String> getIntervalTime(String startTime, String endTime) {
        List<String> times = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Date start = sdf.parse(startTime);
        Date end = sdf.parse(endTime);
        // 同月
        if (start.getTime() == end.getTime()) {
            String time = startTime.substring(0, 7);
            times.add(time);
        } else if (start.getYear() == end.getYear()) {
            // 同年
            int startM = start.getMonth() + 1;
            int endM = end.getMonth() + 1;
            int temp = endM - startM;
            for (int i = 0; i <= temp; i++) {
                String time = start.getYear() + 1900 + "";
                int month = startM + i;
                if (month < 10) {
                    time = time + "-0" + month;
                } else {
                    time = time + "-" + month;
                }
                times.add(time);
            }
        } else {
            // 不同年!!!!这里忽略了年份之间跨年的情况
            int startY = start.getYear() + 1900;
            int startM = start.getMonth() + 1;
            int endY = end.getYear() + 1900;
            int endM = end.getMonth() + 1;
            int tempS = 12 - startM;
            // 连续的年份
            if (endY - startY == 1) {
                // 第一年的时间获取
                for (int i = 0; i <= tempS; i++) {
                    int month = startM + i;
                    String time = startY + "-";
                    if (month < 10) {
                        time = time + "0" + month;
                    } else {
                        time = time + month;
                    }
                    times.add(time);
                }
                // 第二年的时间获取

                for (int i = 1; i <= endM; i++) {
                    String time = endY + "-";
                    if (i < 10) {
                        time = time + "0" + i;
                    } else {
                        time = time + i;
                    }
                    times.add(time);
                }
            } else {
                // 不连续的年份
                // 第一年的时间获取
                for (int i = 0; i <= tempS; i++) {
                    int month = startM + i;
                    String time = startY + "-";
                    if (month < 10) {
                        time = time + "0" + month;
                    } else {
                        time = time + month;
                    }
                    times.add(time);
                }
                int tempY = endY - startY;
                // 中间年份的时间
                for (int i = 1; i < tempY; i++) {
                    for (int j = 1; j <= 12; j++) {
                        String time = startY + i + "-";
                        if (j < 10) {
                            time = time + "0" + j;
                        } else {
                            time = time + j;
                        }
                        times.add(time);
                    }
                }
                // 最后一年的时间获取
                for (int i = 1; i <= endM; i++) {
                    String time = endY + "-";
                    if (i < 10) {
                        time = time + "0" + i;
                    } else {
                        time = time + i;
                    }
                    times.add(time);
                }
            }

        }
        return times;
    }

    @SneakyThrows
    private List<String> getIntervalDateTime(Integer startTime, int beginDay,Integer endTime,Integer dd) {
        List<String> list = new ArrayList<>();
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.set(startTime, endTime - 1, 1);
        int year = calendar.get(Calendar.YEAR);//年份
        int month = calendar.get(Calendar.MONTH) + 1;//月份
        for (int i = beginDay; i <= dd; i++) {
            String date = null;
            if (month < 10 && i < 10) {
                date = year + "-0" + month + "-0" + i;
            }
            if (month < 10 && i >= 10) {
                date = year + "-0" + month + "-" + i;
            }
            if (month >= 10 && i < 10) {
                date = year + "-" + month + "-0" + i;
            }
            if (month >= 10 && i >= 10) {
                date = year + "-" + month + "-" + i;
            }

            list.add(date);
        }
        return list;
    }
}
