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

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Segment;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
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.modules.basedata.entity.TbVehicle;
import com.gci.boot.modules.basedata.service.ITbVehicleService;
import com.gci.boot.modules.gis.entity.RefuelAlarm;
import com.gci.boot.modules.gis.mapper.RefuelAlarmMapper;
import com.gci.boot.modules.gis.service.IRefuelAlarmService;
import com.gci.boot.modules.projects.service.IProjectsService;
import com.gci.boot.modules.vehicles.entity.TbRefuelChargeRecord;
import com.gci.boot.modules.vehicles.service.ITbRefuelChargeRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @author 24642
 */
@Service
public class RefuelAlarmServiceImpl extends ServiceImpl<RefuelAlarmMapper, RefuelAlarm> implements IRefuelAlarmService {

    @Autowired
    private IProjectsService projectsService;
    @Autowired
    private ITbRefuelChargeRecordService recordService;
    @Autowired
    private ITbVehicleService vehicleService;

    @Override
    public IPage<RefuelAlarm> pageBuild(Page<RefuelAlarm> page,RefuelAlarm query) {
        List<RefuelAlarm> recordList = new ArrayList<>();
        List<String> allProjectListOfUser = projectsService.queryAllProjectListOfUser();
        if (allProjectListOfUser.isEmpty()) {
            return page;
        }
        if (StrUtil.isNotBlank(query.getProjectId())) {
            if (!allProjectListOfUser.contains(query.getProjectId())) {
                return page;
            } else {
                allProjectListOfUser.clear();
                allProjectListOfUser.add(query.getProjectId());
            }
        }

        List<TbVehicle> vehicles = vehicleService.list(new LambdaQueryWrapper<TbVehicle>()
        .like(StrUtil.isNotBlank(query.getPlateNumber()),TbVehicle::getPlateNumber,query.getPlateNumber())
        .eq(StrUtil.isNotBlank(query.getVehicleType()),TbVehicle::getVehicleType,query.getVehicleType())
        .like(StrUtil.isNotBlank(query.getFrameNumber()),TbVehicle::getFrameNumber,query.getFrameNumber()));
        if (vehicles.isEmpty()) {
            return page;
        }
        List<String> plateNumbers = vehicles.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList());
        List<TbRefuelChargeRecord> list = recordService.list(new LambdaQueryWrapper<TbRefuelChargeRecord>()
                .eq(TbRefuelChargeRecord::getRefuelType, '1')
                .in(TbRefuelChargeRecord::getProjectId,allProjectListOfUser)
                .in(TbRefuelChargeRecord::getPlateNumber,plateNumbers)
                .ge(ObjectUtil.isNotNull(query.getStartTime()),TbRefuelChargeRecord::getStartTime,query.getStartTime())
                .le(ObjectUtil.isNotNull(query.getEndTime()),TbRefuelChargeRecord::getEndTime,query.getEndTime())
                .isNotNull(TbRefuelChargeRecord::getStartTime)
                .isNotNull(TbRefuelChargeRecord::getEndTime)
                .orderByAsc(TbRefuelChargeRecord::getPlateNumber)
                .orderByAsc(TbRefuelChargeRecord::getRecordDate)
                .orderByAsc(TbRefuelChargeRecord::getStartTime)
                );
        if (list.isEmpty()) {
            return page;
        }
        Map<String, Map<Date, List<TbRefuelChargeRecord>>> stringMapMap = CollStreamUtil.groupBy2Key(list, TbRefuelChargeRecord::getPlateNumber, TbRefuelChargeRecord::getRecordDate);
        Set<Map.Entry<String, Map<Date, List<TbRefuelChargeRecord>>>> entries = stringMapMap.entrySet();
        for (Map.Entry<String, Map<Date, List<TbRefuelChargeRecord>>> entry : entries) {
            Map<Date, List<TbRefuelChargeRecord>> value = entry.getValue();
            Set<Map.Entry<Date, List<TbRefuelChargeRecord>>> entries1 = value.entrySet();
            for (Map.Entry<Date, List<TbRefuelChargeRecord>> dateListEntry : entries1) {
                List<TbRefuelChargeRecord> value1 = dateListEntry.getValue();
                if (value1.size() > 1) {
                    for (int i = 0; i < value1.size() -1; i++) {
                        TbRefuelChargeRecord cur = value1.get(i);
                        TbRefuelChargeRecord next = value1.get(i + 1);

                        TbVehicle vehicle = vehicles.stream().filter(v -> v.getPlateNumber().equals(entry.getKey())).findFirst().orElse(null);
                        if (vehicle == null) {
                            continue;
                        }

                        RefuelAlarm refuelAlarm = new RefuelAlarm();
                        refuelAlarm.setStartTime(cur.getStartTime());
                        refuelAlarm.setEndTime(next.getEndTime());
                        refuelAlarm.setPlateNumber(vehicle.getPlateNumber());
                        refuelAlarm.setVehicleType(vehicle.getVehicleType());
                        refuelAlarm.setFrameNumber(vehicle.getFrameNumber());
                        refuelAlarm.setVehicleModel(vehicle.getVehicleModel());
                        refuelAlarm.setProjectId(cur.getProjectId());
                        refuelAlarm.setAlarm(0);
                        recordList.add(refuelAlarm);
                    }
                }
            }
        }
        if (query.getAlarm() != null) {
            recordList = recordList.stream().filter(r->r.getAlarm()!=null&&r.getAlarm().equals(query.getAlarm())).collect(Collectors.toList());
        }
        recordList.sort(Comparator.comparing(RefuelAlarm::getStartTime).thenComparing(RefuelAlarm::getPlateNumber));
        PageUtil.setOneAsFirstPageNo();
        int totalPage = PageUtil.totalPage(recordList.size(), Convert.toInt(page.getSize()));
        if (page.getCurrent() > totalPage) {
            page.setCurrent(totalPage);
        }
        page.setTotal(recordList.size());
        page.setPages(totalPage);
        if (page.getSize() == -1) {
            page.setRecords(recordList);
            return page;
        }
        Segment<Integer> integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize()));
        Integer endIndex = integerSegment.getEndIndex();
        if (endIndex > recordList.size()) {
            endIndex = recordList.size();
        }
        page.setRecords(recordList.subList(integerSegment.getStartIndex(), endIndex));
        return page;
    }
}
