package com.ningdatech.carapi.safe.manage;

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

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.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService;
import com.ningdatech.carapi.common.constant.UserRoleTypeEnum;
import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedVehicle;
import com.ningdatech.carapi.safe.entity.NdVehicleOverspeedWaysection;
import com.ningdatech.carapi.safe.entity.VehicleOverspeedInfo;
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.model.vo.NdVehicleOverspeedCompanyVO;
import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedVehicleVO;
import com.ningdatech.carapi.safe.model.vo.NdVehicleOverspeedWaysectionVO;
import com.ningdatech.carapi.safe.service.INdVehicleOverspeedCompanyService;
import com.ningdatech.carapi.safe.service.INdVehicleOverspeedVehicleService;
import com.ningdatech.carapi.safe.service.INdVehicleOverspeedWaysectionService;
import com.ningdatech.carapi.safe.service.IVehicleOverspeedInfoService;
import com.ningdatech.carapi.sys.entity.dto.CompanyDTO;
import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO;
import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper;
import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.carapi.user.util.LoginUserUtil;

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

/**
 * @author PoffyZhang
 * @date 2022/10/19 上午11:18
 */
@Component
@RequiredArgsConstructor
public class VehicleOverspeedManage {

    private final INdVehicleOverspeedCompanyService overspeedCompanyService;
    private final INdVehicleOverspeedVehicleService overspeedVehicleService;
    private final INdVehicleOverspeedWaysectionService overspeedWaysectionService;
    private final RegionsCacheHelper regionsCacheHelper;
    private final IVehicleOverspeedInfoService vehicleOverspeedInfoService;
    private final OperatorsCacheHelper operatorsCacheHelper;
    private final IVehicleBaseInfoService vehicleBaseInfoService;
    private final CompaniesCacheHelper companiesCacheHelper;

    public PageVo<NdVehicleOverspeedCompanyVO> queryCompanyOverspeed(OverspeedPageQuery overspeedPageQuery) {

        //以企业为维度
        Page<VehicleOverspeedCompanyPO> page = overspeedPageQuery.page();

        // 按照登录用户，如果是运营商账号登录，删选出该运营商关联的车辆信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long roleId = userDetail.getRoleId();
        if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) {
            String companyName = userDetail.getCompanyName();
            // 暂时控制运营商名称和运营商所在企业名称相同
            OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName);
            // 获取运营商ID
            Long operatorId = operatorQueryDTO.getId();
            // 查询出该运营商下所有车辆所在的所有企业
            List<Long> companyIds = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                            .eq(NdVehicleBaseInfo::getOperatorId, operatorId))
                    .stream().map(NdVehicleBaseInfo::getCompanyId).collect(Collectors.toList());
            HashSet<Long> set = new HashSet<>();
            List<Long> companyIdList = companyIds.stream().filter(c -> set.add(c)).collect(Collectors.toList());
            // 过滤掉不在这些企业下的数据
            overspeedPageQuery.setCompanyIds(companyIdList);
        }
        vehicleOverspeedInfoService.pageGroupCompany(page, overspeedPageQuery);
        Map<Long, List<VehicleOverspeedInfo>> listMap = vehicleOverspeedInfoService.list(Wrappers.lambdaQuery(VehicleOverspeedInfo.class)
                .isNotNull(VehicleOverspeedInfo::getCompanyName).isNotNull(VehicleOverspeedInfo::getOverspeedDate)
                .select(VehicleOverspeedInfo::getOverspeedDate,VehicleOverspeedInfo::getCompanyId))
                .stream().collect(Collectors.groupingBy(VehicleOverspeedInfo::getCompanyId));
        List<NdVehicleOverspeedCompanyVO> data = page.getRecords().stream().map(e -> {
            NdVehicleOverspeedCompanyVO vo = new NdVehicleOverspeedCompanyVO();
            BeanUtil.copyProperties(e, vo);
            CompanyDTO companyDto = companiesCacheHelper.getById(vo.getCompanyId());
            Long regionId = companyDto.getRegionId();
            String displayName = regionsCacheHelper.getDisplayName(regionId);
            vo.setRegionId(regionId);
            vo.setRegionName(displayName);
            List<VehicleOverspeedInfo> infoList = listMap.get(e.getCompanyId());
            if (CollUtil.isNotEmpty(infoList)) {
                Optional<LocalDateTime> time = infoList.stream().map(VehicleOverspeedInfo::getOverspeedDate).max(LocalDateTime::compareTo);
                if (time.isPresent()) {
                    LocalDateTime maxTime = time.get();
                    Date date = NdDateUtils.localDateTime2Date(maxTime);
                    vo.setOverspeedDate(date);
                }
            }
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(data, page.getTotal());
    }

    public PageVo<NdVehicleOverspeedVehicleVO> queryVihicleOverspeed(OverspeedPageQuery overspeedPageQuery) {
        //以车辆为维度
        Page<VehicleOverspeedVehiclePO> page = overspeedPageQuery.page();

        // 按照登录用户，如果是运营商账号登录，删选出该运营商关联的车辆信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long roleId = userDetail.getRoleId();
        if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) {
            String companyName = userDetail.getCompanyName();
            // 暂时控制运营商名称和运营商所在企业名称相同
            OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName);
            // 获取运营商ID
            Long operatorId = operatorQueryDTO.getId();
            // 获取运营商下的所有与车辆
            List<NdVehicleBaseInfo> vehicleBaseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                    .eq(NdVehicleBaseInfo::getOperatorId, operatorId));
            List<String> carPlateList = vehicleBaseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList());
            // 过滤掉不在登录运营商下的车辆
            overspeedPageQuery.setCarPlateList(carPlateList);
        }
        vehicleOverspeedInfoService.pageGroupVehicle(page, overspeedPageQuery);
        List<NdVehicleOverspeedVehicleVO> data = CollUtils.convert(page.getRecords(),
                e -> BeanUtil.copyProperties(e, NdVehicleOverspeedVehicleVO.class));
        return PageVo.of(data, page.getTotal());
    }

    public PageVo<NdVehicleOverspeedWaysectionVO> queryWaySectionOverspeed(OverspeedPageQuery overspeedPageQuery) {
        //以路段分析为维度
        Page<NdVehicleOverspeedWaysectionPO> page = overspeedPageQuery.page();

        // 按照登录用户，如果是运营商账号登录，删选出该运营商关联的车辆信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long roleId = userDetail.getRoleId();
        if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) {
            String companyName = userDetail.getCompanyName();
            // 暂时控制运营商名称和运营商所在企业名称相同
            OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName);
            // 获取运营商ID
            Long operatorId = operatorQueryDTO.getId();
            // 获取运营商下的所有与车辆
            List<NdVehicleBaseInfo> vehicleBaseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                    .eq(NdVehicleBaseInfo::getOperatorId, operatorId));
            List<String> carPlateList = vehicleBaseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList());
            // 过滤掉不在登录运营商下的车辆
            overspeedPageQuery.setCarPlateList(carPlateList);
        }

        vehicleOverspeedInfoService.pageGroupWaysection(page, overspeedPageQuery);
        List<NdVehicleOverspeedWaysectionVO> data = CollUtils.convert(page.getRecords(),
                e -> BeanUtil.copyProperties(e, NdVehicleOverspeedWaysectionVO.class));
        return PageVo.of(data, page.getTotal());
    }

    public void vehicleOverspeed(Page<NdVehicleOverspeedVehicle> page, OverspeedPageQuery overspeedPageQuery) {
        LambdaQueryWrapper<NdVehicleOverspeedVehicle> wrapper = Wrappers.lambdaQuery(NdVehicleOverspeedVehicle.class);
        wrapper.ge(Objects.nonNull(overspeedPageQuery.getStartTime()), NdVehicleOverspeedVehicle::getOverspeedDate, overspeedPageQuery.getStartTime())
                .le(Objects.nonNull(overspeedPageQuery.getEndTime()), NdVehicleOverspeedVehicle::getOverspeedDate, overspeedPageQuery.getEndTime())
                .le(Objects.nonNull(overspeedPageQuery.getRank()), NdVehicleOverspeedVehicle::getRank, overspeedPageQuery.getRank());
        wrapper.orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleOverspeedVehicle::getRank);
        overspeedVehicleService.page(page, wrapper);
    }

    public void waysectionOverspeedSearch(Page<NdVehicleOverspeedWaysection> page, OverspeedPageQuery overspeedPageQuery) {
        LambdaQueryWrapper<NdVehicleOverspeedWaysection> wrapper = Wrappers.lambdaQuery(NdVehicleOverspeedWaysection.class);
        if (Objects.nonNull(overspeedPageQuery.getRegionId())) {
            List<Long> regionIds = regionsCacheHelper.listChildRegionId(overspeedPageQuery.getRegionId());
            wrapper.in(CollUtil.isNotEmpty(regionIds), NdVehicleOverspeedWaysection::getRegionId, regionIds);
        }
        wrapper.ge(Objects.nonNull(overspeedPageQuery.getStartTime()), NdVehicleOverspeedWaysection::getOverspeedDate, overspeedPageQuery.getStartTime())
                .le(Objects.nonNull(overspeedPageQuery.getEndTime()), NdVehicleOverspeedWaysection::getOverspeedDate, overspeedPageQuery.getEndTime())
                .le(Objects.nonNull(overspeedPageQuery.getRank()), NdVehicleOverspeedWaysection::getRank, overspeedPageQuery.getRank())
                .like(StringUtils.isNotBlank(overspeedPageQuery.getWaySection()), NdVehicleOverspeedWaysection::getWaySection, overspeedPageQuery.getWaySection())
                .like(StringUtils.isNotBlank(overspeedPageQuery.getCarPlate()), NdVehicleOverspeedWaysection::getCarPlate, overspeedPageQuery.getCarPlate())
                .like(StringUtils.isNotBlank(overspeedPageQuery.getCompanyName()), NdVehicleOverspeedWaysection::getCompanyName, overspeedPageQuery.getCompanyName());
        wrapper.orderBy(Boolean.TRUE, Boolean.TRUE, NdVehicleOverspeedWaysection::getRank);
        overspeedWaysectionService.page(page, wrapper);
    }
}
