package com.gci.boot.modules.gis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gci.boot.annotation.Query.handle.QueryGenerator;
import com.gci.boot.common.util.CoordinateConverterUtil;
import com.gci.boot.common.util.JsonUtil;
import com.gci.boot.common.util.LatLonPoint;
import com.gci.boot.modules.basedata.entity.TbVehicle;
import com.gci.boot.modules.basedata.service.ITbVehicleService;
import com.gci.boot.modules.dataview.vo.GisRoadMileVo;
import com.gci.boot.modules.gis.entity.GisRoadMileLog;
import com.gci.boot.modules.gis.entity.TbGisChargeLog;
import com.gci.boot.modules.gis.entity.TbGisGps;
import com.gci.boot.modules.gis.mapper.GisRoadMileLogMapper;
import com.gci.boot.modules.gis.mapper.TbGisChargeLogMapper;
import com.gci.boot.modules.gis.service.GisRoadMileLogService;
import com.gci.boot.modules.gis.service.ITbGisChargeLogService;
import com.gci.boot.modules.gis.service.ITbGisGpsService;
import com.gci.boot.modules.gis.vo.GisHistoryVo;
import com.gci.boot.modules.gis.vo.PointListDTO;
import com.gci.boot.modules.gis.vo.TimeSlotDTO;
import com.gci.boot.modules.system.service.ISysDictService;
import com.gci.boot.modules.system.vo.DictModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 行驶里程能耗记录表 服务实现类
 * </p>
 *
 * @author 2464
 * @since 2023-09-01
 */
@Service
public class GisRoadMileLogServiceImpl extends ServiceImpl<GisRoadMileLogMapper, GisRoadMileLog> implements GisRoadMileLogService {

    @Autowired
    private ISysDictService sysDictService;

    @Autowired
    private GisRoadMileLogMapper gisRoadMileLogMapper;

    @Autowired
    private ITbGisGpsService tbGisGpsService;

    @Autowired
    private ITbVehicleService vehicleService;
    @Value("${gps.timeCut}")
    private Long timeCut;

    @Override
    public List<GisRoadMileVo> countByTime(Date startTime, Date endTime) {
        List<DictModel> modelList = sysDictService.queryDictItemsByCode("vehicle_type");
        List<GisRoadMileVo> dbList = gisRoadMileLogMapper.countByTime(startTime, endTime);
        List<GisRoadMileVo> resultList = modelList.stream().map(a -> {
            GisRoadMileVo vo = new GisRoadMileVo();
            vo.setVehicleType(a.getValue());
            vo.setVehicleTypeName(a.getText());
            BigDecimal averageEnergy = dbList.stream().filter(db -> {
                return db.getVehicleType().equals(a.getValue());
            }).map(db -> {
                return db.getAverageEnergy();
            }).findFirst().orElse(new BigDecimal(0));
            vo.setAverageEnergy(averageEnergy.setScale(4, BigDecimal.ROUND_HALF_UP));
            return vo;
        }).collect(Collectors.toList());
        resultList.sort(Comparator.comparing(GisRoadMileVo::getAverageEnergy).reversed());
        return resultList;
    }

    @Override
    public void coverGpsToRoadMile(TbVehicle vehicle, Date startTime, Date endTime) {
        Integer batteryCapacity = ObjectUtil.isEmpty(vehicle.getBatteryCapacity()) ? 0 : vehicle.getBatteryCapacity();
        //构建gps数据记录查询
        LambdaQueryWrapper<TbGisGps> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TbGisGps::getPlateNumber, vehicle.getPlateNumber());
        queryWrapper.between(TbGisGps::getGpsTime, startTime, endTime);
        queryWrapper.eq(TbGisGps::getIsValid, 1);
        queryWrapper.orderByAsc(TbGisGps::getGpsTime);
        List<TbGisGps> gpsList = tbGisGpsService.list(queryWrapper);
        //只取三电记录的gps数据
        List<TbGisGps> list = gpsList.stream().filter(g -> g.getRecordSource().equals(2)).collect(Collectors.toList());
        if(list.isEmpty()){
            return;
        }
        List<List<TbGisGps>> lists =groupByStatusAndTime(list);
        List<GisRoadMileLog> logs = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(lists)) {
            for (List<TbGisGps> tbGisGps : lists) {
                if (ObjectUtil.isEmpty(tbGisGps)) {
                    continue;
                }


                TbGisGps startGisGps = tbGisGps.get(0);
                TbGisGps endGisGps = tbGisGps.get(tbGisGps.size() - 1);

                Date startGisGpsGpsTime = startGisGps.getGpsTime();
                Date endGisGpsGpsTime = endGisGps.getGpsTime();
                BigDecimal startGisGpsTotalMileage = startGisGps.getTotalMileage();
                BigDecimal endGisGpsTotalMileage = endGisGps.getTotalMileage();


                if (startGisGpsTotalMileage.compareTo(endGisGpsTotalMileage) == 0) {
                    continue;
                }

                Integer startGisGpsStateOfCharge = startGisGps.getStateOfCharge();
                Integer endGisGpsStateOfCharge = endGisGps.getStateOfCharge();

                String day = DateUtil.format(startGisGpsGpsTime, "yyyy-MM-dd");

                GisRoadMileLog log = new GisRoadMileLog();
                log.setNumberPlate(vehicle.getPlateNumber());
                log.setProjectId(vehicle.getProjectId());
                log.setProjectName("");
                log.setVehicleBrand(vehicle.getVehicleBrand());
                log.setVehicleModel(vehicle.getVehicleModel());
                log.setVehicleType(vehicle.getVehicleType());
                log.setVinCode(vehicle.getVinCode());
                log.setStartTime(startGisGpsGpsTime);
                log.setEndTime(endGisGpsGpsTime);
                log.setOwnDate(day);
                log.setCreateTime(new Date());

                if (ObjectUtil.isAllNotEmpty(startGisGpsTotalMileage, endGisGpsTotalMileage)) {
                    log.setRoadMile((NumberUtil.sub(endGisGpsTotalMileage, startGisGpsTotalMileage)));
                }
                if (ObjectUtil.isAllNotEmpty(startGisGpsStateOfCharge,endGisGpsStateOfCharge, batteryCapacity)) {
//                    double hour = betweenHour(startGisGpsGpsTime, endGisGpsGpsTime);
                    BigDecimal sub = NumberUtil.sub(startGisGpsStateOfCharge, endGisGpsStateOfCharge);
                    BigDecimal div = NumberUtil.div(sub, 100);
                    BigDecimal mul = NumberUtil.mul(div, batteryCapacity);
                    log.setPowerConsume(mul);
                    // TODO: 2023/11/22 不需要处理小时。记录这段时间总的耗电量即可
//                    if (hour > 0) {
//                        log.setPowerConsume(NumberUtil.div(mul,hour,2));
//                    }
                }
                logs.add(log);
            }
        }
        if(!logs.isEmpty()){
            this.saveBatch(logs);
        }
    }

    private List<List<TbGisGps>> groupByStatusAndTime(List<TbGisGps> list) {
        // 创建一个空的结果列表
        List<List<TbGisGps>> result = new ArrayList<>();
        // 创建一个临时的子列表，用于存放符合条件的元素
        List<TbGisGps> subList = new ArrayList<>();
        // 创建速度缓存的
        ArrayList<TbGisGps> timeList = new ArrayList<>();
        // 遍历输入列表中的每个元素
        for (int i = 0; i < list.size(); i++) {
            // 获取当前元素
            TbGisGps current = list.get(i);
            // 获取当前状态 1-点火 0-熄火
            int currentStatus = current.getCurrentStatus();
            current.setCerStatus(currentStatus);
            if(current.getChargeStatus() != 3){
                continue;
            }
            // 点火状态时
            if (currentStatus == 1) {
                //临时列表为空或者上一个也是点火状态
                if (subList.isEmpty() || subList.get(subList.size() - 1).getCerStatus() == currentStatus) {
                    if (!subList.isEmpty()) {
                        TbGisGps tbGisGps = subList.get(subList.size() - 1);
                        //如果超过了间隔就截断
                        long between = DateUtil.between(tbGisGps.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false);
                        if (between > timeCut) {
                            timeList = new ArrayList<>();
                            if (!subList.isEmpty()) {
                                result.add(subList);
                                subList = new ArrayList<>();
                            }
                        }
                    }
                    //没速度先缓存到时间缓存列表里面
                    if (ObjectUtil.isEmpty(current.getSpeed()) || current.getSpeed().compareTo(BigDecimal.ZERO) == 0) {
                        timeList.add(current);
                    } else {
                        //有速度判断一下是否抛弃数据
                        if (!timeList.isEmpty()) {
                            TbGisGps last = timeList.get(0);
                            //当前的速度不为零时 超过了设置时间
                            long between = DateUtil.between(last.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false);
                            if (between > timeCut) {
                                //清空速度缓存
                                timeList = new ArrayList<>();
                                //结束临时列表
                                if (!subList.isEmpty()) {
                                    result.add(subList);
                                    subList = new ArrayList<>();
                                }
                            } else {
                                //新数据上来了 并且没有超过设置时间
                                //将时间缓存加入临时列表
                                subList.addAll(timeList);
                                //清空时间缓存
                                timeList = new ArrayList<>();
                            }
                        }
                        subList.add(current);
                    }
                }
            } else if (currentStatus == 0) {
                //熄火状态时
                //临时列表不为空
                if (!subList.isEmpty()&&current.getTotalMileage().compareTo(subList.get(subList.size()-1).getTotalMileage())==1) {
                    //时间缓存不为空
                    if (!timeList.isEmpty()) {
                        timeList = new ArrayList<>();
                    }
                    //加入结束点
//                    subList.add(current);
                    result.add(subList);
                    //新建临时列表
                    subList = new ArrayList<>();
                }
            }
        }
        // 遍历结束后，判断临时列表是否为空
        if (!subList.isEmpty()) {
            result.add(subList);
        }
        // 返回结果列表
        return result;
    }

    private double betweenHour(Date startTime,Date endTime) {
        return Convert.toDouble(DateUtil.betweenMs(startTime, endTime)) / 3600000;
    }

}
