package org.dromara.elevator.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.elevator.domain.EBehaviorMessage;
import org.dromara.elevator.domain.EElevatorInfo;
import org.dromara.elevator.domain.bo.*;
import org.dromara.elevator.domain.vo.EElevatorInfoVo;
import org.dromara.elevator.domain.vo.ElevatorBehaviorStatisticsVo;
import org.dromara.elevator.service.IEBehaviorMessageService;
import org.dromara.elevator.service.IEElevatorInfoService;
import org.springframework.stereotype.Service;
import org.dromara.elevator.domain.vo.EBehaviorStatisticsVo;
import org.dromara.elevator.domain.EBehaviorStatistics;
import org.dromara.elevator.mapper.EBehaviorStatisticsMapper;
import org.dromara.elevator.service.IEBehaviorStatisticsService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.dromara.elevator.constant.ElevatorConstant.*;

/**
 * 电梯运行统计Service业务层处理
 *
 * @author ym
 * @date 2024-09-06
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class EBehaviorStatisticsServiceImpl implements IEBehaviorStatisticsService {

    private final EBehaviorStatisticsMapper baseMapper;
    private final IEBehaviorMessageService behaviorMessageService;
    private final IEElevatorInfoService elevatorInfoService;

    /**
     * 查询电梯运行统计
     *
     * @param id 主键
     * @return 电梯运行统计
     */
    @Override
    public EBehaviorStatisticsVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询电梯运行统计列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 电梯运行统计分页列表
     */
    @Override
    public TableDataInfo<EBehaviorStatisticsVo> queryPageList(EBehaviorStatisticsBo bo, PageQuery pageQuery) {
        EElevatorInfoBo elevatorInfoBo = new EElevatorInfoBo();
        elevatorInfoBo.setDeptId(bo.getDeptId());
        elevatorInfoBo.setElevatorName(bo.getElevatorName());
        elevatorInfoBo.setElevatorAddress(bo.getElevatorAddress());
        TableDataInfo<EElevatorInfoVo> elePage = elevatorInfoService.queryPageList(elevatorInfoBo, pageQuery);
        TableDataInfo<EBehaviorStatisticsVo> result = new TableDataInfo<>();
        result.setCode(elePage.getCode());
        result.setMsg(elePage.getMsg());
        result.setTotal(elePage.getTotal());
        List<String> elevatorNumList = new ArrayList<>();
        List<EBehaviorStatisticsVo> list = elePage.getRows().stream()
            .peek(item -> elevatorNumList.add(item.getElevatorNum()))
            .map(item -> {
                EBehaviorStatistics statistics = this.buildEBehaviorStatistics(Objects.requireNonNull(MapstructUtils.convert(item, EElevatorInfo.class)));
                return MapstructUtils.convert(statistics, EBehaviorStatisticsVo.class);
            }).collect(Collectors.toList());
        result.setRows(list);

        if (CollectionUtils.isNotEmpty(list)) {
            LambdaQueryWrapper<EBehaviorStatistics> lqw = Wrappers.<EBehaviorStatistics>lambdaQuery()
                .in(EBehaviorStatistics::getElevatorNum, elevatorNumList)
                .ge(Objects.nonNull(bo.getStartDate()), EBehaviorStatistics::getStatisticsTime, bo.getStartDate())
                .le(Objects.nonNull(bo.getEndDate()), EBehaviorStatistics::getStatisticsTime, bo.getEndDate());
            List<EBehaviorStatistics> behaviorStatisticsList = this.baseMapper.selectList(lqw);
            Map<String, List<EBehaviorStatistics>> eleBehaviorStatisticsMap = StreamUtils.groupByKey(behaviorStatisticsList, EBehaviorStatistics::getElevatorNum);
            for (EBehaviorStatisticsVo record : list) {
                List<EBehaviorStatistics> statisticsList = eleBehaviorStatisticsMap.get(record.getElevatorNum());
                if (CollectionUtils.isEmpty(statisticsList)) {
                    continue;
                }
                for (EBehaviorStatistics item : statisticsList) {
                    record.setUpNum(record.getUpNum() +item.getUpNum());
                    record.setDownNum(record.getDownNum() +item.getDownNum());
                    record.setMileage(record.getMileage().add(item.getMileage()));
                    record.setOpenCloseNum(record.getOpenCloseNum() + item.getOpenCloseNum());
                    record.setStopStationNum(record.getStopStationNum() + item.getStopStationNum());
                }

            }
        }
        return result;
    }

    /**
     * 查询符合条件的电梯运行统计列表
     *
     * @param bo 查询条件
     * @return 电梯运行统计列表
     */
    @Override
    public List<EBehaviorStatisticsVo> queryList(EBehaviorStatisticsBo bo) {
        LambdaQueryWrapper<EBehaviorStatistics> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<EBehaviorStatistics> buildQueryWrapper(EBehaviorStatisticsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EBehaviorStatistics> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getRegisterCode()), EBehaviorStatistics::getRegisterCode, bo.getRegisterCode());
        lqw.eq(StringUtils.isNotBlank(bo.getElevatorNum()), EBehaviorStatistics::getElevatorNum, bo.getElevatorNum());
        lqw.like(StringUtils.isNotBlank(bo.getElevatorName()), EBehaviorStatistics::getElevatorName, bo.getElevatorName());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceCode()), EBehaviorStatistics::getDeviceCode, bo.getDeviceCode());
        lqw.eq(StringUtils.isNotBlank(bo.getTenementId()), EBehaviorStatistics::getTenementId, bo.getTenementId());
        lqw.like(StringUtils.isNotBlank(bo.getTenementName()), EBehaviorStatistics::getTenementName, bo.getTenementName());
        lqw.eq(StringUtils.isNotBlank(bo.getMaintenanceId()), EBehaviorStatistics::getMaintenanceId, bo.getMaintenanceId());
        lqw.like(StringUtils.isNotBlank(bo.getMaintenanceName()), EBehaviorStatistics::getMaintenanceName, bo.getMaintenanceName());
        lqw.eq(StringUtils.isNotBlank(bo.getAreaCode()), EBehaviorStatistics::getAreaCode, bo.getAreaCode());
        lqw.eq(StringUtils.isNotBlank(bo.getBrand()), EBehaviorStatistics::getBrand, bo.getBrand());
        lqw.eq(bo.getUseScenario() != null, EBehaviorStatistics::getUseScenario, bo.getUseScenario());
        lqw.eq(bo.getUpNum() != null, EBehaviorStatistics::getUpNum, bo.getUpNum());
        lqw.eq(bo.getDownNum() != null, EBehaviorStatistics::getDownNum, bo.getDownNum());
        lqw.eq(bo.getMileage() != null, EBehaviorStatistics::getMileage, bo.getMileage());
        lqw.eq(StringUtils.isNotBlank(bo.getElevatorAddress()), EBehaviorStatistics::getElevatorAddress, bo.getElevatorAddress());
        lqw.eq(bo.getOpenCloseNum() != null, EBehaviorStatistics::getOpenCloseNum, bo.getOpenCloseNum());
        lqw.eq(bo.getStopStationNum() != null, EBehaviorStatistics::getStopStationNum, bo.getStopStationNum());
        lqw.eq(StringUtils.isNotBlank(bo.getProjectId()), EBehaviorStatistics::getProjectId, bo.getProjectId());
        lqw.eq(bo.getDeptId() != null, EBehaviorStatistics::getDeptId, bo.getDeptId());
        lqw.orderByDesc(EBehaviorStatistics::getStatisticsTime);
        return lqw;
    }

    /**
     * 新增电梯运行统计
     *
     * @param bo 电梯运行统计
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(EBehaviorStatisticsBo bo) {
        EBehaviorStatistics add = MapstructUtils.convert(bo, EBehaviorStatistics.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改电梯运行统计
     *
     * @param bo 电梯运行统计
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(EBehaviorStatisticsBo bo) {
        EBehaviorStatistics update = MapstructUtils.convert(bo, EBehaviorStatistics.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(EBehaviorStatistics entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除电梯运行统计信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<EBehaviorStatistics> selectBehaviorStatisticsList(Collection<String> elevatorNumList) {
        return baseMapper.selectList(Wrappers.<EBehaviorStatistics>lambdaQuery()
            .in(EBehaviorStatistics::getElevatorNum, elevatorNumList));
    }

    @Override
    public Boolean saveOrUpdateBatch(Collection<EBehaviorStatistics> statisticsList) {
        return baseMapper.insertOrUpdateBatch(statisticsList);
    }

    @Override
    public List<EBehaviorStatistics> queryBehaviorStatisticsList(EBehaviorStatisticsBo bo) {
        return baseMapper.selectList(Wrappers.<EBehaviorStatistics>lambdaQuery()
            .eq(Objects.nonNull(bo.getElevatorNum()), EBehaviorStatistics::getElevatorNum, bo.getElevatorNum())
            .in(CollectionUtils.isNotEmpty(bo.getMaintenanceIds()), EBehaviorStatistics::getMaintenanceId, bo.getMaintenanceIds())
            .in(CollectionUtils.isNotEmpty(bo.getTenementIds()), EBehaviorStatistics::getTenementId, bo.getTenementIds())
            .ge(Objects.nonNull(bo.getStartTime()), EBehaviorStatistics::getStatisticsTime, bo.getStartTime())
            .le(Objects.nonNull(bo.getEndTime()), EBehaviorStatistics::getStatisticsTime, bo.getEndTime()));
    }

    @Override
    public ElevatorBehaviorStatisticsVo queryElevatorStatisticsInfo(EBehaviorStatisticsBo bo) {
        // 楼层停站Map
        EElevatorInfoVo elevator = this.elevatorInfoService.selectByElevatorNum(bo.getElevatorNum());
        if (Objects.isNull(elevator) || StringUtils.isBlank(elevator.getStandNum())) {
            log.warn("电梯信息未查询到或楼层信息为空,{}", JsonUtils.toJsonString(elevator));
            return new ElevatorBehaviorStatisticsVo();
        }

        if (ELE_BEHAVIOR_STATISTICS_DAY_TYPE.equals(bo.getStatisticsType())) {
            return elevatorDayStatistics(bo, elevator);
        }
        // 周月统计
        return elevatorWeekMonthStatistics(bo, elevator);
    }

    /**
     * 电梯详情周月统计
     *
     * @param bo       查询参数
     * @param elevator 电梯信息
     * @return 统计数据
     */
    private ElevatorBehaviorStatisticsVo elevatorWeekMonthStatistics(EBehaviorStatisticsBo bo, EElevatorInfoVo elevator) {
        List<EBehaviorStatistics> statisticsList = this.baseMapper.selectList(Wrappers.<EBehaviorStatistics>lambdaQuery()
            .eq(EBehaviorStatistics::getElevatorNum, bo.getElevatorNum())
            .between(EBehaviorStatistics::getStatisticsTime, DateUtils.toLocalDate(bo.getStartTime()), DateUtils.toLocalDate(bo.getEndTime())));
        ElevatorBehaviorStatisticsVo result = new ElevatorBehaviorStatisticsVo();
        if (CollectionUtils.isEmpty(statisticsList)) {
            return result;
        }
        result.setTimeLineList(StreamUtils.toList(DateUtils.getDatesBetween(bo.getStartTime(), bo.getEndTime()), LocalDate::getDayOfMonth));
        // 电梯运行日统计Map
        Map<Integer, EBehaviorStatistics> eleDayStatisticsMap = statisticsList.stream()
            .collect(Collectors.toMap(item -> item.getStatisticsTime().getDayOfMonth(), Function.identity()));
        for (Integer day : result.getTimeLineList()) {
            Integer openCloseNum = 0;
            Integer upNum = 0;
            Integer downNum = 0;
            Integer stopStationNum = 0;
            BigDecimal mileage = BigDecimal.ZERO;
            EBehaviorStatistics behaviorStatistics = eleDayStatisticsMap.get(day);
            if (Objects.nonNull(behaviorStatistics)) {
                openCloseNum = behaviorStatistics.getOpenCloseNum();
                upNum = behaviorStatistics.getUpNum();
                downNum = behaviorStatistics .getDownNum();
                stopStationNum = behaviorStatistics.getStopStationNum();
                mileage = behaviorStatistics.getMileage();
            }
            result.getDownNumList().add(downNum);
            result.getUpNumList().add(upNum);
            result.getOpenCloseNumList().add(openCloseNum);
            result.getStopStationNumList().add(stopStationNum);
            result.getRunMileageList().add(mileage);
        }
        // 楼层停梯统计
        Map<Integer, Integer> floorStationMap = statisticsList.stream()
            .peek(item -> {
                ElevatorBehaviorStatisticsVo.FloorStatistics floorStatistics = new ElevatorBehaviorStatisticsVo.FloorStatistics();
                floorStatistics.setTimePoint(item.getStatisticsTime().getDayOfMonth());
                floorStatistics.setStatisticsTime(DateUtils.toDate(item.getStatisticsTime()));
                floorStatistics.setStopStationList(JsonUtils.parseArray(item.getFloorStatisticsData(), ElevatorBehaviorStatisticsVo.FloorStopStation.class));
                result.getFloorStatisticsList().add(floorStatistics);
            })
            .map(item -> JsonUtils.parseArray(item.getFloorStatisticsData(), EBehaviorFloorStatisticsBo.class))
            .filter(CollectionUtils::isNotEmpty)
            .flatMap(Collection::stream)
            .collect(Collectors.groupingBy(EBehaviorFloorStatisticsBo::getFloor, Collectors.summingInt(EBehaviorFloorStatisticsBo::getStopStationNum)));

        Integer floorNum = Integer.valueOf(elevator.getStandNum().trim().split("/")[0]);
        List<Integer> floorList = IntStream.range(1, floorNum + 1).peek(item -> {
            result.getFloorStopStationNumList().add(floorStationMap.getOrDefault(item, 0));
        }).boxed().toList();
        result.setFloorList(floorList);
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void behaviorStatistics(BehaviorMessageStatisticsBo bo) {
        LocalDate statisticsTime = DateUtils.toLocalDate(bo.getStartTime());
        List<EBehaviorMessage> behaviorMessages = behaviorMessageService.queryBehaviorMessageList(bo);
        if (CollectionUtils.isEmpty(behaviorMessages)) {
            return;
        }

        EBehaviorStatistics existStatistics = this.baseMapper.selectOne(Wrappers.<EBehaviorStatistics>lambdaQuery()
            .eq(EBehaviorStatistics::getElevatorNum, bo.getElevatorNum())
            .eq(EBehaviorStatistics::getStatisticsTime, statisticsTime));
        EBehaviorStatistics behaviorStatistics = initBehaviorStatistics(bo);
        behaviorStatistics.setStatisticsTime(statisticsTime);
        if (Objects.nonNull(existStatistics)) {
            // 数据存在
            behaviorStatistics.setId(existStatistics.getId());
        }
        if (StringUtils.isBlank(bo.getElevatorInfo().getStandNum())) {
            return;
        }
        // 总层数
        Integer floorNum = Integer.valueOf(bo.getElevatorInfo().getStandNum().trim().substring(0,1));
        Map<Integer, EBehaviorFloorStatisticsBo> floorStatisticsMap = IntStream.range(1, floorNum + 1)
            .mapToObj(EBehaviorFloorStatisticsBo::new)
            .collect(Collectors.toMap(EBehaviorFloorStatisticsBo::getFloor, Function.identity()));
        behaviorStatistics.setDeviceCode(behaviorMessages.get(0).getDeviceCode());
        BigDecimal kilometerRatio = new BigDecimal("100000");
        for (EBehaviorMessage message : behaviorMessages) {
            if (ELE_BEHAVIOR_OPEN_DOOR_STATUS.equals(message.getDoorStatus())
                || ELE_BEHAVIOR_CLOSE_DOOR_STATUS.equals(message.getDoorStatus())) {
                // 开门 关门
                behaviorStatistics.setOpenCloseNum(behaviorStatistics.getOpenCloseNum() + 1);
            }
            if (ELE_BEHAVIOR_UP_STATUS.equals(message.getRunStatus())) {
                // 上行
                behaviorStatistics.setUpNum(behaviorStatistics.getUpNum() + 1);
            }
            if (ELE_BEHAVIOR_DOWN_STATUS.equals(message.getRunStatus())) {
                // 下行
                behaviorStatistics.setDownNum(behaviorStatistics.getDownNum() + 1);
            }
            if (ELE_BEHAVIOR_DOWN_STOP_STATUS.equals(message.getRunStatus())
                || ELE_BEHAVIOR_UP_STOP_STATUS.equals(message.getRunStatus())) {
                // 上下行停梯
                behaviorStatistics.setStopStationNum(behaviorStatistics.getStopStationNum() + 1);
                // 停站楼层统计
                floorStopStationHandler(floorStatisticsMap, message);
            }
            // 里程数 当次运行距离 cm -> 公里
            BigDecimal currRunDis = message.getCurrRunDis().abs();
            behaviorStatistics.setMileage(behaviorStatistics.getMileage().add(currRunDis.divide(kilometerRatio)));
        }
        List<EBehaviorFloorStatisticsBo> floorStatisticsList = floorStatisticsMap.values().stream()
            .sorted(Comparator.comparing(EBehaviorFloorStatisticsBo::getFloor)).collect(Collectors.toList());
        behaviorStatistics.setFloorStatisticsData(JsonUtils.toJsonString(floorStatisticsList));
        this.baseMapper.insertOrUpdate(behaviorStatistics);
    }

    @Override
    public Boolean historyStatistics(BehaviorMessageStatisticsBo bo) {
        List<EElevatorInfoVo> elevatorList = this.elevatorInfoService.selectByElevatorNumList(bo.getElevatorNumList());

        boolean flag = Objects.isNull(bo.getStartTime()) || Objects.isNull(bo.getEndTime());
        BehaviorMessageStatisticsBo messageStatisticsBo = new BehaviorMessageStatisticsBo();
        for (EElevatorInfoVo elevator : elevatorList) {
            messageStatisticsBo.setElevatorNum(elevator.getElevatorNum());
            messageStatisticsBo.setElevatorInfo(MapstructUtils.convert(elevator, EElevatorInfo.class));

            if (flag) {
                // 时间为空 查询第一条消息记录到当前时间点
                EBehaviorMessage firstMsg = this.behaviorMessageService.queryFirstBehaviorMessage(elevator.getElevatorNum());
                if (Objects.isNull(firstMsg)) {
                    continue;
                }
                bo.setStartTime(firstMsg.getHappenTime());
                bo.setEndTime(DateUtil.endOfDay(new Date()));
            }
            List<LocalDate> statisticsDateList = DateUtils.getDatesBetween(bo.getStartTime(), bo.getEndTime());
            // 遍历日期补充数据
            for (LocalDate statisticsDate : statisticsDateList) {
                Date date = DateUtils.toDate(statisticsDate);
                messageStatisticsBo.setStartTime(DateUtil.beginOfDay(date));
                messageStatisticsBo.setEndTime(DateUtil.endOfDay(date));
                this.behaviorStatistics(messageStatisticsBo);
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 初始化行为统计
     *
     * @param bo 初始化参数
     * @return 行为统计
     */
    private EBehaviorStatistics initBehaviorStatistics(BehaviorMessageStatisticsBo bo) {
        EElevatorInfo elevatorInfo = bo.getElevatorInfo();
        if (Objects.isNull(elevatorInfo)) {
            EElevatorInfoVo elevatorInfoVo = this.elevatorInfoService.selectByElevatorNum(bo.getElevatorNum());
            elevatorInfo = MapstructUtils.convert(elevatorInfoVo, EElevatorInfo.class);
        }
        return buildEBehaviorStatistics(elevatorInfo);
    }

    /**
     * 构建行为统计
     *
     * @param elevatorInfo 电梯信息
     * @return 行为统计
     */
    private EBehaviorStatistics buildEBehaviorStatistics(EElevatorInfo elevatorInfo) {
        EBehaviorStatistics  behaviorStatistics = new EBehaviorStatistics();
        behaviorStatistics.setCreateBy(1L);
        behaviorStatistics.setRegisterCode(elevatorInfo.getRegisterCode());
        behaviorStatistics.setElevatorNum(elevatorInfo.getElevatorNum());
        behaviorStatistics.setElevatorName(elevatorInfo.getElevatorName());
        behaviorStatistics.setTenementId(Long.valueOf(elevatorInfo.getTenementId()));
        behaviorStatistics.setTenementName(elevatorInfo.getTenementName());
        behaviorStatistics.setMaintenanceId(Long.valueOf(elevatorInfo.getMaintenanceId()));
        behaviorStatistics.setMaintenanceName(elevatorInfo.getMaintenanceName());
        behaviorStatistics.setAreaCode(elevatorInfo.getAreaCode());
        behaviorStatistics.setBrand(elevatorInfo.getBrand());
        behaviorStatistics.setUseScenario(elevatorInfo.getUseScenario());
        behaviorStatistics.setElevatorAddress(elevatorInfo.getElevatorAddress());
        behaviorStatistics.setUpNum(0);
        behaviorStatistics.setDownNum(0);
        behaviorStatistics.setMileage(BigDecimal.ZERO);
        behaviorStatistics.setOpenCloseNum(0);
        behaviorStatistics.setStopStationNum(0);
        behaviorStatistics.setProjectId(elevatorInfo.getProjectId());
        behaviorStatistics.setDeptId(elevatorInfo.getDeptId());
        return behaviorStatistics;
    }

    /**
     * 楼层停站处理
     *
     * @param floorStatisticsMap 停站楼层Map
     * @param message            停站消息
     */
    private void floorStopStationHandler(Map<Integer, EBehaviorFloorStatisticsBo> floorStatisticsMap, EBehaviorMessage message) {
        if (StringUtils.isBlank(message.getFloor())) {
            return;
        }
        Integer floor = Integer.valueOf(message.getFloor());
        EBehaviorFloorStatisticsBo floorStatisticsBo = floorStatisticsMap.get(floor);
        if (Objects.nonNull(floorStatisticsBo)) {
            floorStatisticsBo.setStopStationNum(floorStatisticsBo.getStopStationNum() + 1);
        }

    }

    /**
     * 电梯运行日统计
     *
     * @param bo       参数
     * @param elevator 电梯信息
     * @return 统计信息
     */
    private ElevatorBehaviorStatisticsVo elevatorDayStatistics(EBehaviorStatisticsBo bo, EElevatorInfoVo elevator) {
        ElevatorBehaviorStatisticsVo result = new ElevatorBehaviorStatisticsVo();
        // 运行消息
        BehaviorMessageStatisticsBo messageStatisticsBo = new BehaviorMessageStatisticsBo();
        messageStatisticsBo.setElevatorNum(bo.getElevatorNum());
        messageStatisticsBo.setStartTime(bo.getStartTime());
        messageStatisticsBo.setEndTime(bo.getEndTime());
        List<EBehaviorMessage> behaviorMessages = this.behaviorMessageService.queryBehaviorMessageList(messageStatisticsBo);
        // 小时时间段
        List<Integer> hoursList = DateUtils.getHoursBetween(bo.getStartTime(), bo.getEndTime());
        result.setTimeLineList(hoursList);
        // 小时内的消息
        Map<Object, List<EBehaviorMessage>> hourMsgMap = StreamUtils.groupByKey(behaviorMessages,
            item -> Objects.requireNonNull(DateUtils.toLocalDateTime(item.getHappenTime())).getHour());
        BigDecimal kilometerRatio = new BigDecimal("100000");
        // 电梯层数
        Integer floorNum = Integer.valueOf(elevator.getStandNum().trim().split("/")[0]);
        // key1:小时  key2: 楼层
        Map<Integer, Map<Integer, ElevatorBehaviorStatisticsVo.FloorStopStation>> hourFloorStopStationMap =
            hoursList.stream().collect(Collectors.toMap(Function.identity(),
                hour -> IntStream.range(1, floorNum + 1).mapToObj(ElevatorBehaviorStatisticsVo.FloorStopStation::new)
                    .collect(Collectors.toMap(ElevatorBehaviorStatisticsVo.FloorStopStation::getFloor, Function.identity()))));

        for (Integer hour : hoursList) {
            // 小时统计
            Integer openCloseNum = 0;
            Integer upNum = 0;
            Integer downNum = 0;
            Integer stopStationNum = 0;
            BigDecimal mileage = BigDecimal.ZERO;
            Map<Integer, ElevatorBehaviorStatisticsVo.FloorStopStation> floorStopStationMap = hourFloorStopStationMap.get(hour);
            if (hourMsgMap.containsKey(hour)) {
                for (EBehaviorMessage message : hourMsgMap.get(hour)) {
                    if (ELE_BEHAVIOR_OPEN_DOOR_STATUS.equals(message.getDoorStatus())
                        || ELE_BEHAVIOR_CLOSE_DOOR_STATUS.equals(message.getDoorStatus())) {
                        // 开门 关门
                        openCloseNum = openCloseNum + 1;
                    }
                    if (ELE_BEHAVIOR_UP_STATUS.equals(message.getRunStatus())) {
                        // 上行
                        upNum = upNum + 1;
                    }
                    if (ELE_BEHAVIOR_DOWN_STATUS.equals(message.getRunStatus())) {
                        // 下行
                        downNum = downNum + 1;
                    }
                    if (ELE_BEHAVIOR_DOWN_STOP_STATUS.equals(message.getRunStatus())
                        || ELE_BEHAVIOR_UP_STOP_STATUS.equals(message.getRunStatus())) {
                        // 上下行停梯
                        stopStationNum = stopStationNum + 1;
                        // 小时楼层停站统计
                        hourFloorStopStationHandler(floorStopStationMap, message);
                    }
                    // 里程数 当次运行距离 cm -> 公里
                    BigDecimal currRunDis = message.getCurrRunDis().abs();
                    mileage = mileage.add(currRunDis.divide(kilometerRatio));
                }
            }

            if (stopStationNum < 10) {
                // 较闲时段个数
                result.setIdleNum(result.getIdleNum() + 1);
            } else if (stopStationNum < 60) {
                // 适中时段个数
                result.setModerateNum(result.getModerateNum() + 1);
            } else  {
                // 繁忙时段个数
                result.setBusyNum(result.getBusyNum() + 1);
            }
            result.getDownNumList().add(downNum);
            result.getUpNumList().add(upNum);
            result.getOpenCloseNumList().add(openCloseNum);
            result.getStopStationNumList().add(stopStationNum);
            result.getRunMileageList().add(mileage);
        }
        // 电梯日运行楼层停站统计
        eleBehaviorFloorStopStationStatistics(elevator, result, behaviorMessages, hourFloorStopStationMap);
        return result;
    }

    /**
     * 小时楼层处理
     * @param floorStopStationMap 楼层停站map
     * @param message 消息
     */
    private void hourFloorStopStationHandler(Map<Integer, ElevatorBehaviorStatisticsVo.FloorStopStation> floorStopStationMap, EBehaviorMessage message) {
        if (StringUtils.isBlank(message.getFloor())) {
            return;
        }
        Integer floor = Integer.valueOf(message.getFloor());
        ElevatorBehaviorStatisticsVo.FloorStopStation floorStopStation = floorStopStationMap.get(floor);
        if (Objects.nonNull(floorStopStation)) {
            floorStopStation.setStopStationNum(floorStopStation.getStopStationNum() + 1);
        }
    }

    /**
     * 电梯日运行楼层停站统计
     *
     * @param elevator                电梯信息
     * @param result                  统计结果
     * @param behaviorMessages        统计消息
     * @param hourFloorStopStationMap 小时楼层停站
     */
    private void eleBehaviorFloorStopStationStatistics(EElevatorInfoVo elevator, ElevatorBehaviorStatisticsVo result,
                                                       List<EBehaviorMessage> behaviorMessages,
                                                       Map<Integer, Map<Integer, ElevatorBehaviorStatisticsVo.FloorStopStation>> hourFloorStopStationMap) {
        Integer floorNum = Integer.valueOf(elevator.getStandNum().trim().split("/")[0]);
        Map<Integer, Integer> floorStationCountMap = behaviorMessages.stream()
            .filter(item -> StringUtils.isNotBlank(item.getFloor()))
            .filter(item -> ELE_BEHAVIOR_DOWN_STOP_STATUS.equals(item.getRunStatus())
                || ELE_BEHAVIOR_UP_STOP_STATUS.equals(item.getRunStatus()))
            .collect(Collectors.groupingBy(item -> Integer.valueOf(item.getFloor()), Collectors.counting()))
            .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().intValue()));
        List<Integer> floorList = IntStream.range(1, floorNum + 1).peek(item -> {
            result.getFloorStopStationNumList().add(floorStationCountMap.getOrDefault(item, 0));
        }).boxed().collect(Collectors.toList());
        result.setFloorList(floorList);

        // 小时楼层停站
        List<ElevatorBehaviorStatisticsVo.FloorStatistics> floorStatisticsList = hourFloorStopStationMap.entrySet().stream().map(item -> {
            ElevatorBehaviorStatisticsVo.FloorStatistics floorStatistics = new ElevatorBehaviorStatisticsVo.FloorStatistics();
            List<ElevatorBehaviorStatisticsVo.FloorStopStation> stopStationList = item.getValue().values().stream()
                .sorted(Comparator.comparing(ElevatorBehaviorStatisticsVo.FloorStopStation::getFloor))
                .toList();
            floorStatistics.setStopStationList(stopStationList);
            floorStatistics.setTimePoint(item.getKey());
            return floorStatistics;
        }).sorted(Comparator.comparing(ElevatorBehaviorStatisticsVo.FloorStatistics::getTimePoint)).collect(Collectors.toList());
        result.setFloorStatisticsList(floorStatisticsList);
    }

}
