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

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import com.gci.boot.common.util.FormatUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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.gci.boot.common.util.DateUtils;
import com.gci.boot.modules.dataview.service.SafetyDataStatisticsService;
import com.gci.boot.modules.dataview.vo.ProjectSignInVo;
import com.gci.boot.modules.driver.mapper.TbDriverSignInMapper;
import com.gci.boot.modules.gis.entity.GisAlarm;
import com.gci.boot.modules.gis.entity.TbGisActiveSafetyAlarm;
import com.gci.boot.modules.gis.entity.TbGisFenceAlarm;
import com.gci.boot.modules.gis.entity.TbGisSpeedingAlarm;
import com.gci.boot.modules.gis.entity.TbGisVehicleFaultAlarm;
import com.gci.boot.modules.gis.service.ITbGisActiveSafetyAlarmService;
import com.gci.boot.modules.gis.service.ITbGisFenceAlarmService;
import com.gci.boot.modules.gis.service.ITbGisSpeedingAlarmService;
import com.gci.boot.modules.gis.service.ITbGisVehicleFaultAlarmService;
import com.gci.boot.modules.projects.entity.Projects;
import com.gci.boot.modules.projects.service.IProjectsService;
import com.gci.boot.modules.statis.vo.AlarmTrendVO;
import com.gci.boot.modules.statis.vo.SafetyDataVO;

import cn.hutool.core.date.DateUtil;

/**
 * @author lyz
 * @date 2023/9/23 17:43
 */
@Service
public class SafetyDataStatisticsServiceImpl implements SafetyDataStatisticsService {

    @Autowired
    private ITbGisSpeedingAlarmService tbGisSpeedingAlarmService;
    @Autowired
    private ITbGisActiveSafetyAlarmService tbGisActiveSafetyAlarmService;
    @Autowired
    private ITbGisVehicleFaultAlarmService tbGisVehicleFaultAlarmService;
    @Autowired
    private ITbGisFenceAlarmService tbGisFenceAlarmService;

    @Autowired
    private IProjectsService iProjectsService;

    @Autowired
    private TbDriverSignInMapper tbDriverSignInMapper;

    private List<SafetyDataVO> convertToVoList(Map<String, Long> counts) {
        List<SafetyDataVO> result = new ArrayList<>();
        for (Map.Entry<String, Long> entry : counts.entrySet()) {
            SafetyDataVO vo = new SafetyDataVO();
            vo.setName(entry.getKey());
            vo.setCount(entry.getValue());
            result.add(vo);
        }
        return result;
    }

    @Override
    public Map alarmQuantity() {
        Date endTime = DateUtils.convertLocalDateTimeToDate(LocalDateTime.now());
        Date startTime = DateUtils.convertLocalDateTimeToDate(LocalDateTime.now().minusMonths(3));
        HashMap resultMap = new HashMap(3);
        CompletableFuture<List<TbGisActiveSafetyAlarm>> safetyAlarmsFuture = CompletableFuture.supplyAsync(() -> {
            return tbGisActiveSafetyAlarmService.findListByTime(startTime, endTime);
        });
        CompletableFuture<List<TbGisSpeedingAlarm>> speedingAlarmsFuture = CompletableFuture.supplyAsync(() -> {
            return tbGisSpeedingAlarmService.findListByTime(startTime, endTime);
        });
        CompletableFuture<List<TbGisVehicleFaultAlarm>> vehicleFaultAlarmsFuture = CompletableFuture.supplyAsync(() -> {
            return tbGisVehicleFaultAlarmService.findListByTime(startTime, endTime);
        });
        CompletableFuture<List<Projects>> projectsFuture = CompletableFuture.supplyAsync(() -> {
            return iProjectsService.listAll();
        });
        // 使用 CompletableFuture.allOf 等待所有异步查询完成
        CompletableFuture<Void> allOf = CompletableFuture.allOf(
                safetyAlarmsFuture,
                speedingAlarmsFuture,
                vehicleFaultAlarmsFuture,
                projectsFuture
        );
        // 注册回调来处理异步任务的结果
        allOf.thenRun(() -> {
            try {
                List<TbGisActiveSafetyAlarm> safetyAlarms = safetyAlarmsFuture.get();
                List<TbGisSpeedingAlarm> speedingAlarms = speedingAlarmsFuture.get();
                List<TbGisVehicleFaultAlarm> vehicleFaultAlarms = vehicleFaultAlarmsFuture.get();
                List<Projects> projects = projectsFuture.get();

                AtomicReference<Long> adasTotalCount = new AtomicReference<>(0L);
                Map<String, Long> adasResult = safetyAlarms.parallelStream().filter(alarm -> alarm.getPrimaryType() == 1)
                        .collect(Collectors.groupingBy(
                                alarm -> alarm.getEventName() != null ? alarm.getEventName() : "未知",
                                Collectors.collectingAndThen(Collectors.counting(), count -> {
                                    // 在这里更新总的数量
                                    adasTotalCount.updateAndGet(v -> v + count);
                                    return count;
                                })
                        ));
                AtomicReference<Long> dsmTotalCount = new AtomicReference<>(0L);
                Map<String, Long> dsmResult = safetyAlarms.parallelStream().filter(alarm -> alarm.getPrimaryType() == 2)
                        .collect(Collectors.groupingBy(
                                alarm -> alarm.getEventName() != null ? alarm.getEventName() : "未知",
                                Collectors.collectingAndThen(Collectors.counting(), count -> {
                                    // 在这里更新总的数量
                                    dsmTotalCount.updateAndGet(v -> v + count);
                                    return count;
                                })
                        ));

                // 合并三个列表为一个总的告警列表
                List<GisAlarm> allAlarms = new ArrayList<>();
                allAlarms.addAll(safetyAlarms);
                allAlarms.addAll(speedingAlarms);
                allAlarms.addAll(vehicleFaultAlarms);

                Set<String> projectSet = projects.stream().map(a->{return a.getProjectName();}).collect(Collectors.toSet());
                // 使用流进行分组、计数和排序
                Map<String, Long> projectAlarmCounts = allAlarms.stream()
                        .collect(Collectors.groupingBy(
                                GisAlarm::getProjectName,
                                Collectors.counting()
                        ));
                for (String projectName : projectSet) {
                    if (!projectAlarmCounts.containsKey(projectName)) {
                        projectAlarmCounts.put(projectName, 0L);
                    }
                }
                List<SafetyDataVO> rankList = new ArrayList<>();
                rankList = convertToVoList(projectAlarmCounts);
                rankList.removeIf(entry -> !projectSet.contains(entry.getName()));
                rankList.sort(Comparator.comparingLong(SafetyDataVO::getCount).reversed());
//                // 将 Map 按照值（告警数量）倒序排序
//                List<Map.Entry<String, Long>> sortedProjectCounts = projectAlarmCounts.entrySet()
//                        .stream()
//                        .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
//                        .collect(Collectors.toList());
                resultMap.put("adasResult",convertToVoList(adasResult));
                resultMap.put("dsmResult",convertToVoList(dsmResult));
                resultMap.put("rankList",rankList);
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        allOf.join();
        return resultMap;
    }

    @Override
    public Map alarmTrend() {
        Date endTime = DateUtils.convertLocalDateTimeToDate(LocalDateTime.now());
        Date startTime = DateUtils.convertLocalDateTimeToDate(LocalDateTime.now().minusMonths(5));
        HashMap resultMap = new HashMap(2);
        CompletableFuture<List<AlarmTrendVO>> safetyAlarmsFuture = CompletableFuture.supplyAsync(() -> {
            return tbGisActiveSafetyAlarmService.findTrendListByTime(startTime, endTime);
        });
        CompletableFuture<List<AlarmTrendVO>> speedingAlarmsFuture = CompletableFuture.supplyAsync(() -> {
            return tbGisSpeedingAlarmService.findTrendListByTime(startTime, endTime);
        });
        // 使用 CompletableFuture.allOf 等待所有异步查询完成
        CompletableFuture<Void> allOf = CompletableFuture.allOf(
                safetyAlarmsFuture,
                speedingAlarmsFuture
        );
        allOf.thenRun(() -> {
            try {
                List<AlarmTrendVO> safetyAlarms = safetyAlarmsFuture.get();
                List<AlarmTrendVO> speedingAlarms = speedingAlarmsFuture.get();
                resultMap.put("speedingAlarms",speedingAlarms);
                resultMap.put("safetyAlarms",safetyAlarms);
            }catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        allOf.join();
        return resultMap;
    }

    @Override
    public IPage<TbGisFenceAlarm> pageFenceList(List<String> projectIds, String plateNumber, String startTime, String endTime, Integer pageNo, Integer pageSize) {
        Page<TbGisFenceAlarm> page = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<TbGisFenceAlarm> lambdaQueryWrapper = new LambdaQueryWrapper<TbGisFenceAlarm>();
//        if (!projectIds.isEmpty()) {
//            lambdaQueryWrapper.in(TbGisFenceAlarm::getProjectId, projectIds);
//        }
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            // 如果 startTime 和 endTime 都提供了，使用 BETWEEN 条件
            lambdaQueryWrapper.between(TbGisFenceAlarm::getStartTime, DateUtil.parse(startTime), DateUtil.parse(endTime));
        } else if (StringUtils.isNotBlank(startTime)) {
            // 如果只提供了 startTime，使用 大于等于
            lambdaQueryWrapper.ge(TbGisFenceAlarm::getStartTime, DateUtil.parse(startTime));
        } else if (StringUtils.isNotBlank(endTime)) {
            // 如果只提供了 endTime，使用 小于等于
            lambdaQueryWrapper.le(TbGisFenceAlarm::getStartTime, DateUtil.parse(endTime));
        }
        lambdaQueryWrapper.isNull(TbGisFenceAlarm::getEndTime);
        lambdaQueryWrapper.orderByDesc(TbGisFenceAlarm::getStartTime);
        IPage<TbGisFenceAlarm> pageList = tbGisFenceAlarmService.page(page, lambdaQueryWrapper);
        for (TbGisFenceAlarm record : pageList.getRecords()) {
            String duration = FormatUtil.formattedTimeDifference(record.getStartTime(), record.getEndTime());
            record.setDuration(duration);
        }
        return pageList;
    }

    /**
     * 司机考勤情况
     */
    @Override
	public ProjectSignInVo getDriverSignInCount() {
    	ProjectSignInVo vo = new ProjectSignInVo();
    	List<ProjectSignInVo> list = getSignInCount();
    	for (ProjectSignInVo projectSignInVo : list) {
    		vo.setTotal(vo.getTotal()+projectSignInVo.getTotal());
    		vo.setSignIn(vo.getSignIn()+projectSignInVo.getSignIn());
		}
    	return vo;
    }

    /**
     * 项目考勤情况
     */
    @Override
	public List<ProjectSignInVo> getSignInCount() {
    	Date today = DateUtils.getToday();
    	List<ProjectSignInVo> list = tbDriverSignInMapper.getSignInCount(today);
    	return list;
    }

}
