package com.ningdatech.carapi.safe.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ningdatech.carapi.car.vehicle.mapper.VehicleBaseInfoMapper;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.common.aop.BuildChildrenRegionEntity;
import com.ningdatech.carapi.common.constant.VehicleTypeEnum;
import com.ningdatech.carapi.common.util.CodeUtil;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.aop.XmlDataScope;
import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo;
import com.ningdatech.carapi.safe.mapper.VehicleOverspeedInfoMapper;
import com.ningdatech.carapi.safe.model.dto.OverspeedPageQuery;
import com.ningdatech.carapi.safe.model.po.NdVehicleOverspeedWaysectionPO;
import com.ningdatech.carapi.safe.model.po.VehicleOverspeedCompanyPO;
import com.ningdatech.carapi.safe.model.po.VehicleOverspeedVehiclePO;
import com.ningdatech.carapi.safe.service.IVehicleOverspeedInfoService;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;

/**
 * <p>
 * 车辆超速信息表 服务实现类
 * </p>
 *
 * @author PoffyZhang
 * @since 2022-11-17
 */
@Service
@RequiredArgsConstructor
public class VehicleOverspeedInfoServiceImpl extends ServiceImpl<VehicleOverspeedInfoMapper, VehicleOverspeedInfo> implements IVehicleOverspeedInfoService {

    private final VehicleOverspeedInfoMapper vehicleOverspeedInfoMapper;
    private final VehicleBaseInfoMapper vehicleBaseInfoMapper;
    

    @Override
    public Long countStatistics(List<Long> regionIds,LocalDateTime todayStart, LocalDateTime todayEnd) {
        LambdaQueryWrapper<VehicleOverspeedInfo> wrapper = Wrappers.lambdaQuery(VehicleOverspeedInfo.class);
        VehicleOverspeedInfoServiceImpl contex = (VehicleOverspeedInfoServiceImpl)AopContext.currentProxy();
        contex.dataScopeCount(wrapper,regionIds,todayStart,todayEnd);
        // 根据车辆类型，过滤出真实超速的
        Map<String, NdVehicleBaseInfo> baseInfoMap = vehicleBaseInfoMapper.selectList(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)).stream()
                .collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v));
        List<VehicleOverspeedInfo> overspeedInfos = vehicleOverspeedInfoMapper.selectList(wrapper);
        List<VehicleOverspeedInfo> list = overspeedInfos.stream().filter(v -> {
            NdVehicleBaseInfo baseInfo = baseInfoMap.get(v.getCarPlate());
            if (Objects.nonNull(baseInfo)) {
                if (Boolean.TRUE.equals(checkIsOverSpeed(v, baseInfo))){
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return (long) list.size();
    }

    @LambdaDataScope
    public void dataScopeCount(LambdaQueryWrapper<VehicleOverspeedInfo> wrapper, List<Long> regionIds, LocalDateTime todayStart, LocalDateTime todayEnd) {
        wrapper.in(CollUtil.isNotEmpty(regionIds),VehicleOverspeedInfo::getRegionId, regionIds)
                .ge(VehicleOverspeedInfo::getOverspeedDate, todayStart)
                .le(VehicleOverspeedInfo::getOverspeedDate, todayEnd);
    }

    @Override
    @XmlDataScope(entityIndex = 1)
    @BuildChildrenRegionEntity(entityIndex = 1)
    public Page<VehicleOverspeedCompanyPO> pageGroupCompany(Page<VehicleOverspeedCompanyPO> page, OverspeedPageQuery overspeedPageQuery) {
        vehicleOverspeedInfoMapper.pageGroupCompany(page, overspeedPageQuery);
        CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords());
        return page;
    }

    @Override
    @XmlDataScope(entityIndex = 1)
    @BuildChildrenRegionEntity(entityIndex = 1)
    public Page<VehicleOverspeedVehiclePO> pageGroupVehicle(Page<VehicleOverspeedVehiclePO> page, OverspeedPageQuery overspeedPageQuery) {
        vehicleOverspeedInfoMapper.pageGroupVehicle(page, overspeedPageQuery);
        CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords());
        return page;
    }

    @Override
    @XmlDataScope(entityIndex = 1)
    @BuildChildrenRegionEntity(entityIndex = 1)
    public Page<NdVehicleOverspeedWaysectionPO> pageGroupWaysection(Page<NdVehicleOverspeedWaysectionPO> page, OverspeedPageQuery overspeedPageQuery) {
        vehicleOverspeedInfoMapper.pageGroupWaysection(page, overspeedPageQuery);
        CodeUtil.searchCompanyNamesAndRegionNames(page.getRecords());
        return page;
    }

    private Boolean checkIsOverSpeed(VehicleOverspeedInfo overspeedInfo, NdVehicleBaseInfo baseInfo) {
        // 混凝土和移动泵车 是50
        Integer vehicleType = baseInfo.getVehicleType();
        VehicleTypeEnum enumByValue = VehicleTypeEnum.getEnumByValue(vehicleType);
        if (VehicleTypeEnum.OTHER.equals(enumByValue)) {
            if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0) {
                return Boolean.TRUE;
            }
        } else if (VehicleTypeEnum.KRHP.equals(enumByValue)) {
            if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(50)) > 0) {
                return Boolean.TRUE;
            }
        } else if (VehicleTypeEnum.MIXER.equals(enumByValue)) {
            if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(50)) > 0) {
                return Boolean.TRUE;
            }
        } else if (VehicleTypeEnum.BULK_CEMENT_TRUCK.equals(enumByValue)) {
            if (overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0) {
                return Boolean.TRUE;
            }
        } else if (VehicleTypeEnum.READY_MIXED_MORTAR_TRUC.equals(enumByValue)) {
            return overspeedInfo.getMaxSpeed().compareTo(BigDecimal.valueOf(80)) > 0;
        }
        return Boolean.FALSE;
    }
}
