package com.ningdatech.carapi.driver.manage;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper;
import com.ningdatech.carapi.common.util.CodeUtil;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum;
import com.ningdatech.carapi.driver.constant.StarManageDisplayTypeEnum;
import com.ningdatech.carapi.driver.entity.RegionStarDTO;
import com.ningdatech.carapi.driver.entity.StarManage;
import com.ningdatech.carapi.driver.model.StarManageDisplayInfo;
import com.ningdatech.carapi.driver.model.po.ReqCompanyStarPO;
import com.ningdatech.carapi.driver.model.po.ReqDriverStarListPO;
import com.ningdatech.carapi.driver.model.po.ReqRegionStarPO;
import com.ningdatech.carapi.driver.model.vo.ResCompanyStarListVO;
import com.ningdatech.carapi.driver.model.vo.ResDriverStarListVO;
import com.ningdatech.carapi.driver.model.vo.ResRegionStarVO;
import com.ningdatech.carapi.driver.model.vo.StarManageDisplay;
import com.ningdatech.carapi.driver.service.IStarManageService;
import com.ningdatech.carapi.sys.entity.Company;
import com.ningdatech.carapi.sys.entity.dto.RegionDTO;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import com.ningdatech.carapi.sys.service.CompanyService;

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

/**
 * @author liuxinxin
 * @date 2022/11/15 上午9:45
 */
@Component
@RequiredArgsConstructor
public class DriverStarManage {

    private final IStarManageService iStarManageService;
    private final RegionsCacheHelper regionsCacheHelper;
    private final IStarManageService starManageService;
    private final CompanyService companyService;

    public PageVo<ResDriverStarListVO> driverStarList(ReqDriverStarListPO request) {
        LambdaQueryWrapper<StarManage> wrapper = Wrappers.lambdaQuery(StarManage.class);
        DriverStarManage context = (DriverStarManage) AopContext.currentProxy();
        List<Long> containsRegionIdList = regionsCacheHelper.listChildRegionId(request.getRegionId());
        request.setChildRegionIds(containsRegionIdList);
        context.buildDriverStarQuery(wrapper, request);
        Page<StarManage> page = iStarManageService.page(request.page(),wrapper);
        if (0L == page.getTotal()) {
            return PageVo.empty();
        }
        List<StarManage> records = page.getRecords();
        List<ResDriverStarListVO> resVOList = records.stream().map(r -> {
            ResDriverStarListVO resVO = new ResDriverStarListVO();
            BeanUtils.copyProperties(r,resVO);
            CodeUtil.searchCompanyNameAndRegionName(resVO);
            return resVO;
        }).collect(Collectors.toList());
        return PageVo.of(resVOList,page.getTotal());
    }

    @LambdaDataScope
    public void buildDriverStarQuery(LambdaQueryWrapper<StarManage> wrapper, ReqDriverStarListPO request) {
        wrapper.like(StringUtils.isNotBlank(request.getCompanyName()), StarManage::getCompanyName, request.getCompanyName())
                .like(StringUtils.isNotBlank(request.getDriverName()), StarManage::getDriverName, request.getDriverName())
                .in(Objects.nonNull(request.getChildRegionIds()),StarManage::getRegionId,request.getChildRegionIds());
    }

    public PageVo<ResRegionStarVO> regionStarList(ReqRegionStarPO request) {
        Integer pageNumber = request.getPageNumber();
        Integer pageSize = request.getPageSize();
        Long regionId = request.getRegionId();
        List<Long> regionList = regionsCacheHelper.listChild(regionId);
        List<ResRegionStarVO> regionStars = new ArrayList<>();
        long total = 0;
        // 如果为空最后一级统计公司
        if (CollectionUtil.isEmpty(regionList)) {
            List<Long> regionIdList = CollectionUtil.toList(regionId);
            RegionStarDTO regionStarDTO = new RegionStarDTO();
            regionStarDTO.setRegionIdList(regionIdList);
            Double avgStars = starManageService.getAvgStar(regionStarDTO);
            avgStars = avgStars == null ? 0 : avgStars;
            BigDecimal avgStarTemp = BigDecimal.valueOf(avgStars);
            double avgStar = avgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
            Double totalStar = starManageService.countTotalStar(regionStarDTO);

            LambdaQueryWrapper<Company> query = Wrappers.lambdaQuery(Company.class);
            DriverStarManage context2 = (DriverStarManage) AopContext.currentProxy();
            context2.buildCompanyQuery(query, request);

            Page<Company> page = companyService.page(request.page(),query);

            if (page.getTotal() == 0){
                return PageVo.empty();
            }
            List<Company> companyRecords = page.getRecords();

            for (Company company : companyRecords) {
                ResRegionStarVO resVO = new ResRegionStarVO();
                resVO.setTotalAvgStar(avgStar);
                resVO.setTotalStar(totalStar);
                StarManageDisplayInfo starManageDisplayInfo = new StarManageDisplayInfo();

                StarManageDisplay firstDisplayInfo = new StarManageDisplay();
                firstDisplayInfo.setId(regionId);
                RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId);
                if (Objects.nonNull(regionDTO)) {
                    firstDisplayInfo.setDisplayName(regionDTO.getRegionName());
                }
                firstDisplayInfo.setType(StarManageDisplayTypeEnum.region_id);

                StarManageDisplay secondDisplayInfo = new StarManageDisplay();
                secondDisplayInfo.setId(company.getId());
                secondDisplayInfo.setDisplayName(company.getName());
                secondDisplayInfo.setType(StarManageDisplayTypeEnum.company_id);

                starManageDisplayInfo.setFirstDisplayInfo(firstDisplayInfo);
                starManageDisplayInfo.setSecondDisplayInfo(secondDisplayInfo);
                RegionStarDTO regionStarDto2 = new RegionStarDTO();
                regionStarDto2.setCompanyId(company.getId());
                Double companyAvgStars = starManageService.getCompanyAvgStar(regionStarDto2);
                companyAvgStars = companyAvgStars == null ? 0 : companyAvgStars;
                BigDecimal companyAvgStarTemp = BigDecimal.valueOf(companyAvgStars);
                double companyAvgStar = companyAvgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
                starManageDisplayInfo.setAvgStar(companyAvgStar);
                resVO.setRecord(starManageDisplayInfo);
                regionStars.add(resVO);
            }
            total = page.getTotal();
        } else {
            // 如果不为空下一级则为地区
            List<Long> containsRegionIdList = regionsCacheHelper.listChildRegionId(regionId);
            RegionStarDTO regionStarDTO = new RegionStarDTO();
            regionStarDTO.setRegionIdList(containsRegionIdList);
            Double avgStars = starManageService.getAvgStar(regionStarDTO);
            avgStars = avgStars == null ? 0 : avgStars;
            BigDecimal avgStarTemp = BigDecimal.valueOf(avgStars);
            double avgStar = avgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
            Double totalStar = starManageService.countTotalStar(regionStarDTO);

            if (CollUtil.isEmpty(regionList)){
                return PageVo.empty();
            }

            int currIdx = (pageNumber > 1 ? (pageNumber - 1) * pageSize : 0);
            int endIdx = Math.min(regionList.size(),currIdx + pageSize);
            List<Long> regionSubList;
            regionSubList = regionList.subList(currIdx, endIdx);

            for (Long childrenRegionId : regionSubList) {
                ResRegionStarVO resVO = new ResRegionStarVO();
                resVO.setTotalAvgStar(avgStar);
                resVO.setTotalStar(totalStar);
                List<Long> listChildRegionIdList = regionsCacheHelper.listChildRegionId(childrenRegionId);

                StarManageDisplayInfo starManageDisplayInfo = new StarManageDisplayInfo();
                StarManageDisplay firstDisplayInfo = new StarManageDisplay();
                firstDisplayInfo.setId(regionId);
                RegionDTO regionDTO = regionsCacheHelper.getByRegionId(regionId);
                if (Objects.nonNull(regionDTO)) {
                    firstDisplayInfo.setDisplayName(regionDTO.getRegionName());
                }
                firstDisplayInfo.setType(StarManageDisplayTypeEnum.region_id);

                StarManageDisplay secondDisplayInfo = new StarManageDisplay();
                secondDisplayInfo.setId(childrenRegionId);
                RegionDTO childrenRegionDTO = regionsCacheHelper.getByRegionId(childrenRegionId);
                if (Objects.nonNull(childrenRegionDTO)) {
                    secondDisplayInfo.setDisplayName(childrenRegionDTO.getRegionName());
                }
                secondDisplayInfo.setType(StarManageDisplayTypeEnum.region_id);

                starManageDisplayInfo.setFirstDisplayInfo(firstDisplayInfo);
                starManageDisplayInfo.setSecondDisplayInfo(secondDisplayInfo);
                RegionStarDTO regionStarDto2 = new RegionStarDTO();
                regionStarDto2.setRegionIdList(listChildRegionIdList);
                Double listAvgStars = starManageService.getAvgStar(regionStarDto2);
                listAvgStars = listAvgStars == null ? 0 : listAvgStars;
                BigDecimal listAvgStarTemp = BigDecimal.valueOf(listAvgStars);
                double listAvgStar = listAvgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
                starManageDisplayInfo.setAvgStar(listAvgStar);
                resVO.setRecord(starManageDisplayInfo);
                regionStars.add(resVO);
            }
            total = regionList.size();
        }
        return PageVo.of(regionStars,total);
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.COMPANY_TABLE)
    public void buildCompanyQuery(LambdaQueryWrapper<Company> query, ReqRegionStarPO request) {
        query.eq(Company::getRegionId, request.getRegionId())
             .orderByDesc(Company::getId);
    }

    public PageVo<ResCompanyStarListVO> companyStarList(ReqCompanyStarPO request) {
        List<ResCompanyStarListVO> companyStarLists = new ArrayList<>();

        LambdaQueryWrapper<StarManage> wrapper = Wrappers.lambdaQuery(StarManage.class);
        Long regionId = request.getRegionId();
        DriverStarManage context = (DriverStarManage) AopContext.currentProxy();
        context.buildCompanyStarQuery(wrapper, request);
        Page<StarManage> page = iStarManageService.page(request.page(),wrapper);

        long total = page.getTotal();
        if (0L == total){
            return PageVo.empty();
        }
        List<StarManage> records = page.getRecords();

        List<Long> containsRegionIdList = regionsCacheHelper.listChildRegionId(regionId);
        RegionStarDTO regionStarDTO = new RegionStarDTO();
        regionStarDTO.setRegionIdList(containsRegionIdList);
        Double avgStars = starManageService.getAvgStar(regionStarDTO);
        avgStars = avgStars == null ? 0 : avgStars;
        BigDecimal avgStarTemp = BigDecimal.valueOf(avgStars);
        double avgStar = avgStarTemp.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
        Double totalStar = starManageService.countTotalStar(regionStarDTO);


        for (StarManage starManage : records) {
            ResCompanyStarListVO resCompanyStarListVO = new ResCompanyStarListVO();
            StarManageDisplayInfo starManageDisplayInfo = new StarManageDisplayInfo();
            StarManageDisplay firstDisplayInfo = new StarManageDisplay();
            firstDisplayInfo.setId(starManage.getCompanyId());
            firstDisplayInfo.setDisplayName(starManage.getCompanyName());
            firstDisplayInfo.setType(StarManageDisplayTypeEnum.company_id);

            StarManageDisplay secondDisplayInfo = new StarManageDisplay();
            secondDisplayInfo.setId(starManage.getDriverId());
            secondDisplayInfo.setDisplayName(starManage.getDriverName());
            secondDisplayInfo.setType(StarManageDisplayTypeEnum.driver_id);

            starManageDisplayInfo.setFirstDisplayInfo(firstDisplayInfo);
            starManageDisplayInfo.setSecondDisplayInfo(secondDisplayInfo);

            if (Objects.nonNull(starManage.getCurrentStar())) {
                starManageDisplayInfo.setAvgStar(Double.parseDouble(starManage.getCurrentStar() + ""));
            }
            resCompanyStarListVO.setTotalAvgStar(avgStar);
            resCompanyStarListVO.setTotalStar(totalStar);
            resCompanyStarListVO.setRecord(starManageDisplayInfo);
            companyStarLists.add(resCompanyStarListVO);
        }
        return PageVo.of(companyStarLists,page.getTotal());
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void buildCompanyStarQuery(LambdaQueryWrapper<StarManage> wrapper, ReqCompanyStarPO request) {
        wrapper.like(StringUtils.isNotBlank(request.getCompanyName()), StarManage::getCompanyName, request.getCompanyName())
                .like(StringUtils.isNotBlank(request.getDriverName()), StarManage::getDriverName, request.getDriverName());
                //.eq(Objects.nonNull(request.getRegionId()), StarManage::getRegionId, request.getRegionId());
    }
}
