package com.fs.api.controller;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fs.common.core.domain.R;
import com.fs.common.core.domain.entity.SysDept;
import com.fs.common.core.redis.RedisCache;
import com.fs.company.constant.CompanyTrafficConstants;
import com.fs.company.domain.Company;
import com.fs.company.service.ICompanyService;
import com.fs.his.utils.ConfigUtil;
import com.fs.hisStore.config.MedicalMallConfig;
import com.fs.statis.StatisticsRedisConstant;
import com.fs.statis.dto.*;
import com.fs.statis.param.StatisticsDeptCompanyParam;
import com.fs.statis.service.IStatisticsService;
import com.fs.system.domain.SysConfig;
import com.fs.system.service.ISysConfigService;
import com.fs.system.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

import static com.fs.statis.StatisticsRedisConstant.*;

/**
 * 首页-统计
 */
@RestController
@RequestMapping("/index/statistics")
@Slf4j
public class IndexStatisticsController {
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private ConfigUtil configUtil;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ICompanyService companyService;

    @Autowired
    private MedicalMallConfig medicalMallConfig;

    @Autowired
    private IStatisticsService statisticsService;
    /**
     * 分析概览
     */
    @PostMapping("/analysisPreview")
    public R analysisPreview(@RequestBody AnalysisPreviewQueryDTO param){
        AnalysisPreviewDTO analysisPreviewDTO = new AnalysisPreviewDTO();
        Integer type = param.getType();
        Integer userType = param.getUserType();

        if(type == null) {
            type = 0;
        }

        if(userType == null) {
            userType = 0;
        }
        if(medicalMallConfig.isStatics()|| (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            analysisPreviewDTO = redisCache.getCacheObject(String.format("%s:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType));
        }else if(param.getCompanyId() != null){
            analysisPreviewDTO = redisCache.getCacheObject(String.format("%s:%d:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType,param.getCompanyId()));
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            for(Long companyId : companyIds){
                AnalysisPreviewDTO clildDTO = redisCache.getCacheObject(String.format("%s:%d:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType,companyId));
                if (clildDTO != null) {
                    //将除了completedRate、correctRate和watchRate之外的数据相加，并计算completedRate、correctRate和watchRate
                    analysisPreviewDTO.setWatchUserCount(
                            analysisPreviewDTO.getWatchUserCount() == 0 ? 0 : analysisPreviewDTO.getWatchUserCount()
                                +(clildDTO.getWatchUserCount() == 0 ? 0 : clildDTO.getWatchUserCount())
                    );
                    analysisPreviewDTO.setCompletedUserCount(
                            analysisPreviewDTO.getCompletedUserCount() == 0 ? 0 : analysisPreviewDTO.getCompletedUserCount()
                                +(clildDTO.getCompletedUserCount() == 0 ? 0 : clildDTO.getCompletedUserCount())
                    );
                    analysisPreviewDTO.setCompletedCount(
                            analysisPreviewDTO.getCompletedCount() == 0 ? 0 : analysisPreviewDTO.getCompletedCount()
                                +(clildDTO.getCompletedCount() == 0 ? 0 : clildDTO.getCompletedCount())
                    );
                    analysisPreviewDTO.setWatchCount(
                            analysisPreviewDTO.getWatchCount() == 0 ? 0 : analysisPreviewDTO.getWatchCount()
                                +(clildDTO.getWatchCount() == 0 ? 0 : clildDTO.getWatchCount())
                    );
                    analysisPreviewDTO.setAnswerMemberCount(
                            analysisPreviewDTO.getAnswerMemberCount() == 0 ? 0 : analysisPreviewDTO.getAnswerMemberCount()
                                +(clildDTO.getAnswerMemberCount() == 0 ? 0 : clildDTO.getAnswerMemberCount())
                    );
                    analysisPreviewDTO.setCorrectUserCount(
                            analysisPreviewDTO.getCorrectUserCount() == 0 ? 0 : analysisPreviewDTO.getCorrectUserCount()
                                +(clildDTO.getCorrectUserCount() == 0 ? 0 : clildDTO.getCorrectUserCount())
                    );
                    analysisPreviewDTO.setRewardCount(
                            analysisPreviewDTO.getRewardCount() == 0 ? 0 : analysisPreviewDTO.getRewardCount()
                                +(clildDTO.getRewardCount() == 0 ? 0 : clildDTO.getRewardCount())
                    );
                    analysisPreviewDTO.setRewardMoney(
                            analysisPreviewDTO.getRewardMoney() == null ? BigDecimal.ZERO : analysisPreviewDTO.getRewardMoney()
                                .add(clildDTO.getRewardMoney() == null ? BigDecimal.ZERO : clildDTO.getRewardMoney())
                    );
                }
            }
            if(analysisPreviewDTO.getAnswerMemberCount() != 0){
                analysisPreviewDTO.setCorrectRate(
                        analysisPreviewDTO.getCorrectUserCount() == 0 ? "0" : String.format("%.2f", analysisPreviewDTO.getCorrectUserCount() * 100.0 / analysisPreviewDTO.getAnswerMemberCount())
                );
            }
            if(analysisPreviewDTO.getWatchUserCount() != 0){
                analysisPreviewDTO.setCompletedRate(
                        analysisPreviewDTO.getCompletedUserCount() == 0 ? "0" : String.format("%.2f", analysisPreviewDTO.getCompletedUserCount() * 100.0 / analysisPreviewDTO.getWatchUserCount())
                );
            }
            if(analysisPreviewDTO.getWatchCount() != 0){
                analysisPreviewDTO.setWatchRate(
                        analysisPreviewDTO.getCompletedCount() == 0 ? "0" : String.format("%.2f", analysisPreviewDTO.getCompletedCount() * 100.0 / analysisPreviewDTO.getWatchCount())
                );
            }

        }

        return R.ok().put("data",analysisPreviewDTO);
    }


    /**
     * 消费余额
     */
    @GetMapping("/rechargeComsumption")
    public R rechargeComsumption(StatisticsDeptCompanyParam param){
        ConsumptionBalanceDataDTO consumptionBalanceDataDTO = new ConsumptionBalanceDataDTO();
        if(medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)) {
            consumptionBalanceDataDTO = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_BALANCE);
        }else if(param.getCompanyId() != null){
            consumptionBalanceDataDTO = redisCache.getCacheObject(String.format("%s:%d",DATA_OVERVIEW_DEALER_BALANCE,param.getCompanyId()));
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            for(Long companyId : companyIds){
                ConsumptionBalanceDataDTO clildDTO = redisCache.getCacheObject(String.format("%s:%d",DATA_OVERVIEW_DEALER_BALANCE,companyId));
                consumptionBalanceDataDTO.setBalance(
                    (consumptionBalanceDataDTO.getBalance() == null ? BigDecimal.ZERO : consumptionBalanceDataDTO.getBalance())
                    .add(clildDTO.getBalance() == null ? BigDecimal.ZERO : clildDTO.getBalance())
                );
                consumptionBalanceDataDTO.setTodayComsumption(
                    (consumptionBalanceDataDTO.getTodayComsumption() == null ? BigDecimal.ZERO : consumptionBalanceDataDTO.getTodayComsumption())
                    .add(clildDTO.getTodayComsumption() == null ? BigDecimal.ZERO : clildDTO.getTodayComsumption())
                );
                consumptionBalanceDataDTO.setYesterdayComsumption(
                    (consumptionBalanceDataDTO.getYesterdayComsumption() == null ? BigDecimal.ZERO : consumptionBalanceDataDTO.getYesterdayComsumption())
                    .add(clildDTO.getYesterdayComsumption() == null ? BigDecimal.ZERO : clildDTO.getYesterdayComsumption())
                );
            }
        }
        BigDecimal redPacketCompanyMoney = redisCache.getCacheObject("redpacket_money");
        if(ObjectUtils.isNull(redPacketCompanyMoney)){
            redPacketCompanyMoney = BigDecimal.ZERO;
        }
        if (consumptionBalanceDataDTO != null){
            consumptionBalanceDataDTO.setRunTianBalance(redPacketCompanyMoney);

        }
        return R.ok().put("data", consumptionBalanceDataDTO);
    }

    /**
     * 获取统计流量
     * @return
     */
    @GetMapping("/trafficLog")
    public R getTrafficLog(StatisticsDeptCompanyParam  param){
        TrafficLogDTO result = new TrafficLogDTO();
        if(!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)) {
            result = redisCache.getCacheObject(DATA_OVERVIEW_TRAFFIC_LOG);
            if (!medicalMallConfig.isStatics()) {
                SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
                if(result == null || sysConfig == null) {
                    return null;
                }
                String configValue = sysConfig.getConfigValue();
                result.setTraffic(configValue);
            } else {
                //所有部门流量之和
                SysDept dept = new SysDept();
                dept.setParentId(1L);
                Long[] deptIds = deptService.selectDeptList(dept).stream().map(SysDept::getDeptId).toArray(Long[]::new);
                long trafficTemp = 0L;
                for(Long deptId : deptIds){
                    Object clildTraffic = redisCache.getCacheObject(CompanyTrafficConstants.CACHE_KEY+":"+deptId);
                    if(clildTraffic != null){
                        trafficTemp += Long.parseLong(clildTraffic.toString());
                    }
                }
                result.setTraffic(String.format("%.2f",trafficTemp * 1024.0));
            }
        }else if(param.getCompanyId() != null){
            Company company = companyService.selectCompanyById(param.getCompanyId());
            getTrafficLogResult(result,CompanyTrafficConstants.CACHE_KEY+":"+company.getDeptId()+":"+param.getCompanyId());
        }else{
            getTrafficLogResult(result,CompanyTrafficConstants.CACHE_KEY+":"+param.getDeptId());
        }
        return R.ok().put("data",result);
    }

    private void getTrafficLogResult(TrafficLogDTO result, String key){
        //昨天
        LocalDate yesterday = LocalDate.now().minusDays(1);
        Object yesterdayCount = redisCache.getCacheObject(key+":"+yesterday);
        Object todayCount = redisCache.getCacheObject(key+":"+LocalDate.now());
        Object thisMonthCount = redisCache.getCacheObject(key+":"+YearMonth.now());
        Object traffic = redisCache.getCacheObject(key);
        result.setYesterday(parseRedisNumberValueToLong(yesterdayCount));
        //今天
        result.setToday(parseRedisNumberValueToLong(todayCount));
        //本月
        result.setThisMonth(parseRedisNumberValueToLong(thisMonthCount));
        //剩余
        result.setTraffic(traffic == null?"0":traffic.toString());
    }

    private Long parseRedisNumberValueToLong(Object value){
        return value == null ? 0 : Long.parseLong(value.toString());
    }

    /**
     * 观看趋势
     */
    @PostMapping("/watchEndPlayTrend")
    public R watchEndPlayTrend(@RequestBody AnalysisPreviewQueryDTO param){
        Integer type = param.getType();
        Integer userType = param.getUserType();

        if(type == null) {
            type = 0;
        }
        if(userType == null){
            userType = 0;
        }
        List<WatchEndPlayTrendDTO> watchEndPlayTrendDTOS;
        // 参考watchCourseTopTen方法的处理逻辑
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            String key = String.format("%s:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType);
            watchEndPlayTrendDTOS = redisCache.getCacheObject(key);
        }else if(param.getCompanyId() != null){
            String key = String.format("%s:%d:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType,param.getCompanyId());
            watchEndPlayTrendDTOS = redisCache.getCacheObject(key);
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            List<WatchEndPlayTrendDTO> tempDTOS = new ArrayList<>();
            for(Long companyId : companyIds){
                String key = String.format("%s:%d:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType,companyId);
                List<WatchEndPlayTrendDTO> companyData = redisCache.getCacheObject(key);
                if (companyData != null) {
                    tempDTOS.addAll(companyData);
                }
            }
            // 根据startDate 和 x 分组,合并watchUserCount和completedUserCount 限制最多返回10条记录
            watchEndPlayTrendDTOS = tempDTOS.stream()
                    .collect(Collectors.groupingBy(
                            dto -> dto.getStartDate() + ":" + dto.getX(),  // 根据startDate和x分组
                            Collectors.reducing(new WatchEndPlayTrendDTO(), (dto1, dto2) -> {
                                // 合并watchUserCount和completedUserCount
                                WatchEndPlayTrendDTO result = new WatchEndPlayTrendDTO();
                                // 复制分组标识字段
                                if (dto2 != null && dto2.getStartDate() != null) {
                                    result.setStartDate(dto2.getStartDate());
                                } else if (dto1 != null) {
                                    result.setStartDate(dto1.getStartDate());
                                }

                                if (dto2 != null && dto2.getX() != null) {
                                    result.setX(dto2.getX());
                                } else if (dto1 != null) {
                                    result.setX(dto1.getX());
                                }

                                // 合并数值字段
                                result.setWatchUserCount(
                                        (dto1 == null || dto1.getWatchUserCount() == null ? 0 : dto1.getWatchUserCount()) +
                                                (dto2 == null || dto2.getWatchUserCount() == null ? 0 : dto2.getWatchUserCount())
                                );

                                result.setCompletedUserCount(
                                        (dto1 == null || dto1.getCompletedUserCount() == null ? 0 : dto1.getCompletedUserCount()) +
                                                (dto2 == null || dto2.getCompletedUserCount() == null ? 0 : dto2.getCompletedUserCount())
                                );

                                return result;
                            })
                    ))
                    .values()
                    .stream()
                    .filter(Objects::nonNull)  // 过滤掉null值
                    .limit(10)
                    .sorted(Comparator.comparing(WatchEndPlayTrendDTO::getX))
                    .collect(Collectors.toList());
        }

        if(watchEndPlayTrendDTOS == null){
            watchEndPlayTrendDTOS = new ArrayList<>();
        }

        return R.ok().put("data", watchEndPlayTrendDTOS);
    }

    /**
     * 经销商会员观看
     */
    @PostMapping("/deaMemberTopTen")
    public R deaMemberTopTen(@RequestBody AnalysisPreviewQueryDTO param){
        Integer type = param.getType();
        Integer statisticalType = param.getStatisticalType();
        Integer userType = param.getUserType();

        if(type == null) {
            type = 0;
        }
        if(userType == null){
            userType = 0;
        }
        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = new ArrayList<>();
        // 参考deaMemberTopTen方法处理逻辑
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            String key = String.format("%s:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType);
            deaMemberTopTenDTOS =  redisCache.getCacheObject(key);
        }else if(param.getCompanyId() != null){
            String key = String.format("%s:%d:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType,param.getCompanyId());
            deaMemberTopTenDTOS = redisCache.getCacheObject(key);
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            List<DeaMemberTopTenDTO> tempDTOS = new ArrayList<>();
            for(Long companyId : companyIds){
                String key = String.format("%s:%d:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType,companyId);
                List<DeaMemberTopTenDTO> companyData = redisCache.getCacheObject(key);
                if (companyData != null) {
                    tempDTOS.addAll(companyData);
                }
            }
            // companyId 和 companyName 分组,合并watchUserCount 限制最多返回10条记录
            deaMemberTopTenDTOS = tempDTOS.stream()
                    .collect(Collectors.groupingBy(
                            dto -> dto.getCompanyId() + ":" + dto.getCompanyName(),  // 根据companyId和companyName分组
                            Collectors.reducing(new DeaMemberTopTenDTO(), (dto1, dto2) -> {
                                DeaMemberTopTenDTO result = new DeaMemberTopTenDTO();
                                result.setCompanyId(dto1.getCompanyId());
                                result.setCompanyName(dto1.getCompanyName());
                                result.setWatchUserCount(
                                        (dto1.getWatchUserCount() == null ? 0 : dto1.getWatchUserCount()) +
                                                (dto2 == null || dto2.getWatchUserCount() == null ? 0 : dto2.getWatchUserCount())
                                );
                                return result;
                            })
                    ))
                    .values()
                    .stream()
                    .filter(Objects::nonNull)  // 过滤掉null值
                    .limit(10)
                    .sorted(Comparator.comparing(DeaMemberTopTenDTO::getWatchUserCount, Comparator.nullsLast(Comparator.reverseOrder())))
                    .collect(Collectors.toList());
        }

        if(deaMemberTopTenDTOS == null){
            deaMemberTopTenDTOS = new ArrayList<>();
        }
        return R.ok().put("data", deaMemberTopTenDTOS);
    }

    /**
     * 奖励金额top10
     */
    @PostMapping("/rewardMoneyTopTen")
    public R rewardMoneyTopTen(@RequestBody AnalysisPreviewQueryDTO param){
        Integer type = param.getType();
        Integer dataType = param.getDataType();
        Integer userType = param.getUserType();
        List<RewardMoneyTopTenDTO> rewardMoneyTopTenDTOS = new ArrayList<>();
        // 参考rewardMoneyTopTen方法处理逻辑
        if(!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            String key = String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType);
            rewardMoneyTopTenDTOS = redisCache.getCacheObject(key);
        }else if(param.getCompanyId() != null){
            String key = String.format("%s:%d:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType,param.getCompanyId());
            rewardMoneyTopTenDTOS = redisCache.getCacheObject(key);
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            List<RewardMoneyTopTenDTO> tempDTOS = new ArrayList<>();
            for(Long companyId : companyIds){
                String key = String.format("%s:%d:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType,companyId);
                List<RewardMoneyTopTenDTO> companyData = redisCache.getCacheObject(key);
                if (companyData != null) {
                    tempDTOS.addAll(companyData);
                }
            }
            rewardMoneyTopTenDTOS = tempDTOS.stream()
                    .collect(Collectors.groupingBy(
                            dto -> dto.getCompanyId() + ":" + dto.getCompanyName(),  // 根据companyId和companyName分组
                            Collectors.reducing(new RewardMoneyTopTenDTO(), (dto1, dto2) -> {
                                RewardMoneyTopTenDTO result = new RewardMoneyTopTenDTO();
                                result.setCompanyId(dto1.getCompanyId());
                                result.setCompanyName(dto1.getCompanyName());
                                result.setRewardMoney(
                                        (dto1.getRewardMoney() == null ? BigDecimal.ZERO : dto1.getRewardMoney())
                                        .add(
                                                (dto2 == null || dto2.getRewardMoney() == null ? BigDecimal.ZERO : dto2.getRewardMoney())
                                        )
                                );
                                return result;
                            })
                    ))
                    .values()
                    .stream()
                    .filter(Objects::nonNull)  // 过滤掉null值
                    .limit(10)
                    .sorted(Comparator.comparing(RewardMoneyTopTenDTO::getRewardMoney, Comparator.nullsLast(Comparator.reverseOrder())))
                    .collect(Collectors.toList());
        }

        return R.ok().put("data", rewardMoneyTopTenDTOS);
    }

    /**
     * 答题红包金额趋势图
     */
    @PostMapping("/rewardMoneyTrend")
    public R rewardMoneyTrend(@RequestBody AnalysisPreviewQueryDTO param){
        Integer type = param.getType();
        Integer userType = param.getUserType();
        List<RewardMoneyTrendDTO> rewardMoneyTrendDTOS = new ArrayList<>();
        // 参考rewardMoneyTrend方法处理逻辑
        if(!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            String key = String.format("%s:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType);
            rewardMoneyTrendDTOS = redisCache.getCacheObject(key);
        }else if(param.getCompanyId() != null){
            String key = String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType,param.getCompanyId());
            rewardMoneyTrendDTOS = redisCache.getCacheObject(key);
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            List<RewardMoneyTrendDTO> tempDTOS = new ArrayList<>();
            for(Long companyId : companyIds){
                String key = String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType,companyId);
                List<RewardMoneyTrendDTO> companyData = redisCache.getCacheObject(key);
                if (companyData != null) {
                    tempDTOS.addAll(companyData);
                }
            }
            //根据startDate和x分组，合并rewardMoney,根据x排序，限制10
            rewardMoneyTrendDTOS = tempDTOS.stream()
                    .collect(Collectors.groupingBy(dto -> dto.getStartDate() + ":" + dto.getX(),
                            Collectors.reducing(new RewardMoneyTrendDTO(), (dto1, dto2) -> {
                        RewardMoneyTrendDTO result = new RewardMoneyTrendDTO();
                        result.setStartDate(dto1.getStartDate());
                        result.setX(dto1.getX());
                        result.setRewardMoney(
                                (dto1.getRewardMoney() == null ? BigDecimal.ZERO : dto1.getRewardMoney())
                                .add(
                                        (dto2 == null || dto2.getRewardMoney() == null ? BigDecimal.ZERO : dto2.getRewardMoney())
                                )
                        );
                        return result;
                    })))
                    .values()
                    .stream()
                    .sorted(Comparator.comparing(RewardMoneyTrendDTO::getX))
                    .limit(10)
                    .collect(Collectors.toList());
        }
        return R.ok().put("data", rewardMoneyTrendDTOS);
    }

    /**
     * 课程观看top10
     */
    @PostMapping("/watchCourseTopTen")
    public R watchCourseTopTen(@RequestBody AnalysisPreviewQueryDTO param){
        Integer type = param.getType();
        String sort = param.getSort();
        Integer statisticalType = param.getStatisticalType();
        Integer userType = param.getUserType();
        List<CourseStatsDTO> courseStatsDTOS;
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            courseStatsDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort));
        }else if(param.getCompanyId() != null){
            courseStatsDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s:%d", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort,param.getCompanyId()));
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            List<CourseStatsDTO> tempDTOS = new ArrayList<>();
            for(Long companyId : companyIds){
                List<CourseStatsDTO> companyDTO = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s:%d", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort,companyId));
                if (companyDTO != null) {
                    tempDTOS.addAll(companyDTO);
                }
            }
            // courseId和courseName分组,合并watchUserCount、completedUserCount、answerUserCount、correctUserCount 限制最多返回10条记录
            courseStatsDTOS = tempDTOS.stream()
                    .collect(Collectors.groupingBy(dto -> dto.getCourseId() + ":" + dto.getCourseName()))
                    .values()
                    .stream()
                    .map(group -> {
                        if (group.isEmpty()) {
                            return null;
                        }

                        // 取第一个作为基础对象
                        CourseStatsDTO result = new CourseStatsDTO();
                        CourseStatsDTO first = group.get(0);
                        result.setCourseId(first.getCourseId());
                        result.setCourseName(first.getCourseName());

                        // 合并所有数值字段
                        int watchUserCount = 0;
                        int completedUserCount = 0;
                        int answerUserCount = 0;
                        int correctUserCount = 0;

                        for (CourseStatsDTO dto : group) {
                            watchUserCount += (dto.getWatchUserCount() == null ? 0 : dto.getWatchUserCount());
                            completedUserCount += (dto.getCompletedUserCount() == null ? 0 : dto.getCompletedUserCount());
                            answerUserCount += (dto.getAnswerUserCount() == null ? 0 : dto.getAnswerUserCount());
                            correctUserCount += (dto.getCorrectUserCount() == null ? 0 : dto.getCorrectUserCount());
                        }

                        result.setWatchUserCount(watchUserCount);
                        result.setCompletedUserCount(completedUserCount);
                        result.setAnswerUserCount(answerUserCount);
                        result.setCorrectUserCount(correctUserCount);

                        return result;
                    })
                    .filter(Objects::nonNull)
                    .sorted(Comparator.comparing(CourseStatsDTO::getWatchUserCount, Comparator.nullsLast(Comparator.reverseOrder())))
                    .limit(10)
                    .collect(Collectors.toList());

        }

        return R.ok().put("data", courseStatsDTOS);
    }

    private List<CourseStatsDTO> groupAndSumCourseStatsWithStream(List<CourseStatsDTO> courseStatsList) {
        // 定义合并逻辑
        BinaryOperator<CourseStatsDTO> mergeFunction = (s1, s2) -> {
            s1.setWatchUserCount(
                    (s1.getWatchUserCount() == null ? 0 : s1.getWatchUserCount()) +
                            (s2.getWatchUserCount() == null ? 0 : s2.getWatchUserCount())
            );

            s1.setCompletedUserCount(
                    (s1.getCompletedUserCount() == null ? 0 : s1.getCompletedUserCount()) +
                            (s2.getCompletedUserCount() == null ? 0 : s2.getCompletedUserCount())
            );

            s1.setAnswerUserCount(
                    (s1.getAnswerUserCount() == null ? 0 : s1.getAnswerUserCount()) +
                            (s2.getAnswerUserCount() == null ? 0 : s2.getAnswerUserCount())
            );

            s1.setCorrectUserCount(
                    (s1.getCorrectUserCount() == null ? 0 : s1.getCorrectUserCount()) +
                            (s2.getCorrectUserCount() == null ? 0 : s2.getCorrectUserCount())
            );

            return s1;
        };

        // 分组、合并并排序、限制10条
        return courseStatsList.stream()
                .collect(Collectors.toMap(
                        CourseStatsDTO::getCourseId,
                        dto -> {
                            CourseStatsDTO copy = new CourseStatsDTO();
                            copy.setCourseId(dto.getCourseId());
                            copy.setCourseName(dto.getCourseName());
                            copy.setWatchUserCount(dto.getWatchUserCount() == null ? 0 : dto.getWatchUserCount());
                            copy.setCompletedUserCount(dto.getCompletedUserCount() == null ? 0 : dto.getCompletedUserCount());
                            copy.setAnswerUserCount(dto.getAnswerUserCount() == null ? 0 : dto.getAnswerUserCount());
                            copy.setCorrectUserCount(dto.getCorrectUserCount() == null ? 0 : dto.getCorrectUserCount());
                            return copy;
                        },
                        mergeFunction,
                        LinkedHashMap::new
                ))
                .values()
                .stream()
                .sorted(Comparator.comparing(CourseStatsDTO::getWatchUserCount, Comparator.nullsLast(Comparator.reverseOrder())))
                .limit(10)
                .collect(Collectors.toList());
    }

    /**
     * 数据概览
     */
    @GetMapping("/dealerAggregated")
    public R dealerAggregated(StatisticsDeptCompanyParam param){
        DealerAggregatedDTO result = new DealerAggregatedDTO();
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)) {
            result = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AGGREGATED);
        }else if (param.getCompanyId() != null) {
            result = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AGGREGATED, param.getCompanyId()));
        //没选中销售公司，部门不为总公司
        }else{
            //Long padMaxNum = deptLimiteService.selectById(param.getDeptId()).getMaxPadNum();
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            for(Long companyId : companyIds) {
                DealerAggregatedDTO dealerAggregatedDTO = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AGGREGATED, companyId));
                // 添加空值检查
                if (dealerAggregatedDTO != null) {
                    result.setDealderCount((result.getDealderCount() == null ? 0 : result.getDealderCount())
                            + (dealerAggregatedDTO.getDealderCount() == null ? 0 : dealerAggregatedDTO.getDealderCount()));
                    result.setGroupMgrCount((result.getGroupMgrCount() == null ? 0 : result.getGroupMgrCount())
                            + (dealerAggregatedDTO.getGroupMgrCount() == null ? 0 : dealerAggregatedDTO.getGroupMgrCount()));
                    result.setMemberCount((result.getMemberCount() == null ? 0 : result.getMemberCount())
                            + (dealerAggregatedDTO.getMemberCount() == null ? 0 : dealerAggregatedDTO.getMemberCount()));
                    result.setNormalNum((result.getNormalNum() == null ? 0 : result.getNormalNum())
                            + (dealerAggregatedDTO.getNormalNum() == null ? 0 : dealerAggregatedDTO.getNormalNum()));
                    result.setBlackNum((result.getBlackNum() == null ? 0 : result.getBlackNum())
                            + (dealerAggregatedDTO.getBlackNum() == null ? 0 : dealerAggregatedDTO.getBlackNum()));
                    result.setQwMemberNum((result.getQwMemberNum() == null ? 0 : result.getQwMemberNum())
                            + (dealerAggregatedDTO.getQwMemberNum() == null ? 0 : dealerAggregatedDTO.getQwMemberNum()));
                    result.setTodayIncreaseUserNum((result.getTodayIncreaseUserNum() == null ? 0 : result.getTodayIncreaseUserNum())
                            + (dealerAggregatedDTO.getTodayIncreaseUserNum() == null ? 0 : dealerAggregatedDTO.getTodayIncreaseUserNum()));
                    result.setOrderTotalNum((result.getOrderTotalNum() == null ? 0 : result.getOrderTotalNum())
                            + (dealerAggregatedDTO.getOrderTotalNum() == null ? 0 : dealerAggregatedDTO.getOrderTotalNum()));
                    result.setTodayOrderNum((result.getTodayOrderNum() == null ? 0 : result.getTodayOrderNum())
                            + (dealerAggregatedDTO.getTodayOrderNum() == null ? 0 : dealerAggregatedDTO.getTodayOrderNum()));
                    result.setRecvTodayNum((result.getRecvTodayNum() == null ? 0 : result.getRecvTodayNum())
                            + (dealerAggregatedDTO.getRecvTodayNum() == null ? 0 : dealerAggregatedDTO.getRecvTodayNum()));
                    result.setRecvTotalNum((result.getRecvTotalNum() == null ? 0 : result.getRecvTotalNum())
                            + (dealerAggregatedDTO.getRecvTotalNum() == null ? 0 : dealerAggregatedDTO.getRecvTotalNum()));
                    result.setGoodsTotalNum((result.getGoodsTotalNum() == null ? 0 : result.getGoodsTotalNum())
                            + (dealerAggregatedDTO.getGoodsTotalNum() == null ? 0 : dealerAggregatedDTO.getGoodsTotalNum()));
                    result.setTodayGoodsNum((result.getTodayGoodsNum() == null ? 0 : result.getTodayGoodsNum())
                            + (dealerAggregatedDTO.getTodayGoodsNum() == null ? 0 : dealerAggregatedDTO.getTodayGoodsNum()));
                    result.setPadUsedNum((result.getPadUsedNum() == null ? 0 : result.getPadUsedNum())
                            + (dealerAggregatedDTO.getPadUsedNum() == null ? 0 : dealerAggregatedDTO.getPadUsedNum()));
                }
            }
        }

        return R.ok().put("data",result);
    }


    /**
     * 短信余额
     */
    @GetMapping("/smsBalance")
    public R smsBalance(StatisticsDeptCompanyParam param){
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            return R.ok().put("data", redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_SMS_BALANCE));
        }else if(param.getCompanyId() != null){
            return R.ok().put("data", redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_SMS_BALANCE, param.getCompanyId())));
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            long smsBalance = 0L;
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            for(Long companyId : companyIds) {
                Long smsBalanceCompany = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_SMS_BALANCE, companyId));
                if (smsBalanceCompany != null) {
                    smsBalance += smsBalanceCompany;
                }
            }
            return R.ok().put("data", smsBalance);
        }
    }


    /**
     * 授权信息
     */
    @GetMapping("/authorizationInfo")
    public R authorizationInfo(StatisticsDeptCompanyParam  param){
        AuthorizationInfoDTO authorizationInfoDTO = new AuthorizationInfoDTO();
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            return R.ok().put("data", redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO));
        }else if(param.getCompanyId() != null){
            return R.ok().put("data", redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO, param.getCompanyId())));
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            AuthorizationInfoDTO authorizationInfoDTO1 = new AuthorizationInfoDTO();
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            for(Long companyId : companyIds) {
                AuthorizationInfoDTO companyDTO = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO, companyId));
                log.info("授权信息：{}", authorizationInfoDTO);
                if (companyDTO != null) {
                    authorizationInfoDTO1.setTodayWatchUserCount(
                            (authorizationInfoDTO1.getTodayWatchUserCount() == null ? 0 : authorizationInfoDTO1.getTodayWatchUserCount()) +
                                    (companyDTO.getTodayWatchUserCount() == null ? 0 : companyDTO.getTodayWatchUserCount())
                    );

                    authorizationInfoDTO1.setVersionLimit(
                            (authorizationInfoDTO1.getVersionLimit() == null ? 0 : authorizationInfoDTO1.getVersionLimit()) +
                                    (companyDTO.getVersionLimit() == null ? 0 : companyDTO.getVersionLimit())
                    );
                }
            }
        }

        return R.ok().put("data", authorizationInfoDTO);
    }


    /**
     * 当月订单数统计
     * @return
     */
    @GetMapping("/thisMonthOrderCount")
    public R thisMonthOrderCount(StatisticsDeptCompanyParam  param){
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            return redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_ORDER_COUNT);
        }else if(param.getCompanyId() != null){
            return redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_ORDER_COUNT, param.getCompanyId()));
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            List<String> datesList = new ArrayList<>();
            List<Integer> orderCountList = new ArrayList<>();
            List<Integer> payPriceList = new ArrayList<>();
            for(Long companyId : companyIds) {
                R result = redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_ORDER_COUNT, companyId));
                Object datas = result.get("datas");
                Object orderCount = result.get("orderCount");
                Object payPrice = result.get("payPrice");
                if(datas != null){
                    mergeDataListsForInteger(datesList, orderCountList, payPriceList, (List<String>)datas, (List<Integer>)orderCount, (List<Integer>)payPrice);
                }
            }
            return R.ok().put("dates", datesList).put("orderCount", orderCountList).put("payPrice", payPriceList);
        }
    }

    /**
     * 当月收益统计
     * @return
     */

    @GetMapping("/thisMonthRecvCount")
    public R thisMonthRecvCount(StatisticsDeptCompanyParam  param){
        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
            return redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_RECV_COUNT);
        }else if(param.getCompanyId() != null){
            return redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_RECV_COUNT, param.getCompanyId()));
        }else{
            Company company = new Company();
            company.setDeptId(param.getDeptId());
            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
            List<String> datesList = new ArrayList<>();
            List<Integer> orderCountList = new ArrayList<>();
            List<Float> payMoneyList = new ArrayList<>();
            for(Long companyId : companyIds) {
               R result = redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_RECV_COUNT, companyId));
               Object datas = result.get("datas");
               Object orderCount = result.get("orderCount");
               Object payMoney = result.get("payMoney");
               if(datas != null){
                   mergeDataLists(datesList, orderCountList, payMoneyList, (List<String>)datas, (List<Integer>)orderCount, (List<Float>)payMoney);
               }
            }
            return R.ok().put("dates", datesList).put("orderCount", orderCountList).put("payMoney", payMoneyList);
        }
    }

    private void mergeDataLists(List<String> datasList, List<Integer> orderCountList, List<Float> payMoneyList,
                               List<String> datas, List<Integer> orderCount, List<Float> payMoney) {

        // 遍历新数据
        for (int i = 0; i < datas.size(); i++) {
            String newData = datas.get(i);
            Integer newOrderCount = orderCount.get(i);
            Float newPayMoney = payMoney.get(i);

            // 查找在现有列表中的位置
            int existingIndex = datasList.indexOf(newData);

            if (existingIndex != -1) {
                // 如果存在，将orderCount和payMoney相加
                Integer existingOrderCount = orderCountList.get(existingIndex);
                Float existingPayMoney = payMoneyList.get(existingIndex);

                // 累加orderCount
                orderCountList.set(existingIndex,
                        (existingOrderCount == null ? 0 : existingOrderCount) +
                                (newOrderCount == null ? 0 : newOrderCount));

                // 累加payMoney
                payMoneyList.set(existingIndex,
                        (existingPayMoney == null ? 0.0f : existingPayMoney) +
                                (newPayMoney == null ? 0.0f : newPayMoney));
            } else {
                // 如果不存在，直接添加新项
                datasList.add(newData);
                orderCountList.add(newOrderCount);
                payMoneyList.add(newPayMoney);
            }
        }
    }

    private void mergeDataListsForInteger(List<String> datasList, List<Integer> orderCountList, List<Integer> payMoneyList,
                                          List<String> datas, List<Integer> orderCount, List<Integer> payMoney) {
        // 遍历新数据
        for (int i = 0; i < datas.size(); i++) {
            String newData = datas.get(i);
            Integer newOrderCount = orderCount.get(i);
            Integer newPayMoney = payMoney.get(i);

            // 查找在现有列表中的位置
            int existingIndex = datasList.indexOf(newData);

            if (existingIndex != -1) {
                // 如果存在，将orderCount和payMoney相加
                Integer existingOrderCount = orderCountList.get(existingIndex);
                Integer existingPayMoney = payMoneyList.get(existingIndex);

                // 累加orderCount
                orderCountList.set(existingIndex,
                        (existingOrderCount == null ? 0 : existingOrderCount) +
                                (newOrderCount == null ? 0 : newOrderCount));

                // 累加payMoney
                payMoneyList.set(existingIndex,
                        (existingPayMoney == null ? 0 : existingPayMoney) +
                                (newPayMoney == null ? 0 : newPayMoney));
            } else {
                // 如果不存在，直接添加新项
                datasList.add(newData);
                orderCountList.add(newOrderCount);
                payMoneyList.add(newPayMoney);
            }
        }
    }

    /**
     * @Description: 看课统计按公司
     * @Param:
     * @Return:
     * @Author xgb
     * @Date 2025/10/27 16:29
     */
    @PostMapping("/getWatchCourseStatisticsData")
    public R getWatchCourseStatisticsData(@RequestBody AnalysisPreviewQueryDTO param){
        // 从缓存获取看客统计数据
        List<WatchCourseStatisticsResultDTO> data=statisticsService.getWatchCourseStatisticsData( param);

        return R.ok().put("data", data);
    }
}
