package com.ningdatech.carapi.driver.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.carapi.car.datascreen.model.dto.DataScreenParam;
import com.ningdatech.carapi.common.model.DataChartVo;
import com.ningdatech.carapi.common.model.MapDataVO;
import com.ningdatech.carapi.common.model.po.MapDataPO;
import com.ningdatech.carapi.driver.constant.DriverAgeRangeEnum;
import com.ningdatech.carapi.driver.constant.DrivingExperienceRangeEnum;
import com.ningdatech.carapi.driver.service.IDriverInfoService;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * DriverManageDataViewManage
 * </p>
 *
 * @author WendyYang
 * @since 15:31 2022/10/26
 */
@Component
@AllArgsConstructor
public class DriverManageDataViewManage {

    private final RegionsCacheHelper regionsCacheHelper;

    private final IDriverInfoService driverInfoService;

    public List<MapDataVO> driverStatisticsByRegion(Long regionId) {
        DataScreenParam param = new DataScreenParam();
        param.setRegionId(regionId);
        List<MapDataPO> mapDatas = driverInfoService.diverCountByRegion(param);
        if(CollUtil.isEmpty(mapDatas)){
            return Collections.emptyList();
        }
        int sum = mapDatas.stream().mapToInt(MapDataPO::getValue).sum();
        return mapDatas.stream().map(mapData -> {
            MapDataVO vo = BeanUtil.copyProperties(mapData, MapDataVO.class);
            String percent = BigDecimal.valueOf(mapData.getValue() * 100)
                    .divide(BigDecimal.valueOf(sum), BigDecimal.ROUND_CEILING, RoundingMode.HALF_UP)
                    .stripTrailingZeros().toPlainString();
            vo.setPercent(percent);
            return vo;
        }).collect(Collectors.toList());
    }

    public List<DataChartVo> driverAgeStatisticsByRegion(Long regionId) {
        DataScreenParam param = new DataScreenParam();
        param.setRegionId(regionId);
        String caseSql = Arrays.stream(DriverAgeRangeEnum.values()).map(w -> {
                    StringBuilder builder = new StringBuilder(" when @age ");
                    if (w.getStart() == DriverAgeRangeEnum.UNDEFINED) {
                        builder.append(" <= ").append(w.getEnd());
                    } else if (w.getEnd() == DriverAgeRangeEnum.UNDEFINED) {
                        builder.append(" >= ").append(w.getStart());
                    } else {
                        builder.append(" >= ").append(w.getStart()).append(" and @age <= ").append(w.getEnd());
                    }
                    return builder.append(" then ").append(w.getKey());
                }).collect(Collectors.joining())
                .concat(" else " + DriverAgeRangeEnum.UNDEFINED);
        Map<Integer, Integer> ageMap = driverInfoService.driverAgeStatistics(caseSql, DriverAgeRangeEnum.UNDEFINED, param);
        return Arrays.stream(DriverAgeRangeEnum.values())
                .sorted(Comparator.comparing(DriverAgeRangeEnum::getKey).reversed())
                .map(w -> {
                    DataChartVo vo = new DataChartVo();
                    vo.setLabel(w.getLabel());
                    vo.setValue(ageMap.getOrDefault(w.getKey(), 0));
                    return vo;
                }).collect(Collectors.toList());
    }

    public List<DataChartVo> drivingExperienceStatisticsByRegion(Long regionId) {
        DataScreenParam param = new DataScreenParam();
        param.setRegionId(regionId);
        String caseSql = Arrays.stream(DrivingExperienceRangeEnum.values()).map(w -> {
                    StringBuilder builder = new StringBuilder(" when @age ");
                    if (w.getStart() == DrivingExperienceRangeEnum.UNDEFINED) {
                        builder.append(" <= ").append(w.getEnd());
                    } else if (w.getEnd() == DriverAgeRangeEnum.UNDEFINED) {
                        builder.append(" >= ").append(w.getStart());
                    } else {
                        builder.append(" >= ").append(w.getStart()).append(" and @age <= ").append(w.getEnd());
                    }
                    return builder.append(" then ").append(w.getKey());
                }).collect(Collectors.joining())
                .concat(" else " + DrivingExperienceRangeEnum.UNDEFINED);
        Map<Integer, Integer> ageMap = driverInfoService.drivingExperienceStatistics(caseSql, DrivingExperienceRangeEnum.UNDEFINED, param);
        return Arrays.stream(DrivingExperienceRangeEnum.values())
                .sorted(Comparator.comparing(DrivingExperienceRangeEnum::getKey).reversed())
                .map(w -> {
                    DataChartVo vo = new DataChartVo();
                    vo.setLabel(w.getLabel());
                    vo.setValue(ageMap.getOrDefault(w.getKey(), 0));
                    return vo;
                }).collect(Collectors.toList());
    }

    public List<MapDataVO> driverNativePlaceStatisticsByRegion(Long regionId) {
        List<MapDataVO> result = new ArrayList<>();
        DataScreenParam param = new DataScreenParam();
        param.setRegionId(regionId);
        List<Map<String, Object>> maps = driverInfoService.nativePlaceStatisticsByRegion(param);
        Map<String, List<Map<String, Object>>> groupByProvince = maps.stream()
                .collect(Collectors.groupingBy(w -> String.valueOf(w.get("nativePlace"))));
        groupByProvince.forEach((k, v) -> {
            MapDataVO mapData = MapDataVO.builder()
                    .regionCode(MapUtil.getStr(v.get(0), "nativePlaceRegionCode"))
                    .regionName(k)
                    .build();
            result.add(mapData);
        });
        return result;
    }
}
