package com.greenorange.promotion.service.userInfo.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.greenorange.promotion.common.PageRequest;
import com.greenorange.promotion.constant.CommonConstant;
import com.greenorange.promotion.constant.SystemConstant;
import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.mapper.UserInfoMapper;
import com.greenorange.promotion.model.dto.CommonStringRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.*;
import com.greenorange.promotion.model.entity.*;
import com.greenorange.promotion.model.enums.CommissionStatusEnum;
import com.greenorange.promotion.model.enums.UserRoleEnum;
import com.greenorange.promotion.model.vo.dashboard.WebQueryDashboardVO;
import com.greenorange.promotion.model.vo.userPerformanceSummary.SupervisorPerformanceSummaryVO;
import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.course.CoursePromotionCommissionPendingService;
import com.greenorange.promotion.service.userInfo.EmployeePromotionRecordsService;
import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.userInfo.UserMainInfoService;
import com.greenorange.promotion.service.userInfo.UserPerformanceSummaryService;
import com.greenorange.promotion.mapper.UserPerformanceSummaryMapper;
import com.greenorange.promotion.utils.SqlUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.security.Key;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author 35880
* @description 针对表【user_performance_summary(用户绩效汇总表)】的数据库操作Service实现
* @createDate 2025-07-10 20:38:41
*/
@Service
public class UserPerformanceSummaryServiceImpl extends ServiceImpl<UserPerformanceSummaryMapper, UserPerformanceSummary>
    implements UserPerformanceSummaryService{


    private static final String KEY = "rakeRate";


    @Resource
    private RedisTemplate<String, String> redisTemplate;


    @Resource
    private CoursePromotionCommissionPendingService coursePromotionCommissionPendingService;


    @Resource
    private EmployeePromotionRecordsService employeePromotionRecordsService;


    @Resource
    private UserInfoMapper userInfoMapper;


    @Resource
    private CommonService commonService;


    /**
     * 获取查询条件
     */
    @Override
    public QueryWrapper<UserPerformanceSummary> getQueryWrapper(PageRequest pageRequest) {
        String sortField = pageRequest.getSortField();
        String sortOrder = pageRequest.getSortOrder();
        QueryWrapper<UserPerformanceSummary> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
        return queryWrapper;
    }


    /**
     * 获取课程订单的查询条件
     */
    @Override
    public QueryWrapper<CourseOrder> getCourseOrderQueryWrapper(UserCourseOrderQueryRequest userCourseOrderQueryRequest) {
        String orderNumber = userCourseOrderQueryRequest.getOrderNumber();
        String startTimeStr = userCourseOrderQueryRequest.getStartDate();
        String sortField = userCourseOrderQueryRequest.getSortField();
        String sortOrder = userCourseOrderQueryRequest.getSortOrder();
        String endTimeStr = userCourseOrderQueryRequest.getEndDate();
        DateTime startDate = null;
        DateTime endDate = null;
        boolean isAddDate = true;
        try {
            startDate = DateUtil.parse(startTimeStr, "yyyy-MM-dd HH:mm:ss");
            endDate = DateUtil.parse(endTimeStr, "yyyy-MM-dd HH:mm:ss");
        } catch (Exception e) {
            isAddDate = false;
        }
        QueryWrapper<CourseOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(orderNumber), "orderNumber", orderNumber);
        if (isAddDate) {
            queryWrapper.ge(StringUtils.isNotBlank(startTimeStr), "createTime", startDate);
            queryWrapper.le(StringUtils.isNotBlank(endTimeStr), "createTime", endDate);
        }
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
        return queryWrapper;
    }


    /**
     * Web端管理员修改一、二级抽成比例
     */
    @Override
    public void updateRakeRewards(RakeRewardsUpdateRequest rakeRewardsUpdateRequest) {
        String level = rakeRewardsUpdateRequest.getLevel();
        BigDecimal rate = rakeRewardsUpdateRequest.getRate();
        redisTemplate.opsForHash().put(KEY, level, rate.toPlainString());
    }


    /**
     * Web端管理员查询一、二级抽成比例
     */
    @Override
    public Map<String, BigDecimal> queryRakeRewardsRate() {
        // 直接从 redisTemplate 获取 HashOperations
        HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
        Map<String, String> entries = hashOps.entries(KEY);
        return entries.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        e -> new BigDecimal(e.getValue())
                ));
    }


    /**
     * Web端管理员根据级别查询抽佣比例
     */
    @Override
    public BigDecimal queryRakeRewardsRateByLevel(RakeRewardsQueryRequest rakeRewardsQueryRequest) {
        String level = rakeRewardsQueryRequest.getLevel();
        return new BigDecimal(redisTemplate.opsForHash().get(KEY, level).toString());
    }


    /**
     * 在内存 List 上模拟 MyBatis-Plus 的分页
     */
    public Page<SupervisorPerformanceSummaryVO> queryPage(UserPerformanceSummaryRankQueryRequest req, List<SupervisorPerformanceSummaryVO> allVos) {
        // 根据字段排序
        MiniUserPerformanceSummaryRankQueryRequest miniUserPerformanceSummaryRankQueryRequest = MiniUserPerformanceSummaryRankQueryRequest.builder()
                .sortField(req.getSortField())
                .sortOrder(req.getSortOrder())
                .build();
        sortPerformanceRankingList(allVos, miniUserPerformanceSummaryRankQueryRequest);

        // 计算分页
        long current  = req.getCurrent();   // 页码
        long pageSize = req.getPageSize();  // 每页大小
        long total = allVos.size();
        long offset = (current - 1) * pageSize;
        int start = (int)Math.min(offset, total);
        int end   = (int)Math.min(offset + pageSize, total);
        List<SupervisorPerformanceSummaryVO> pageList = allVos.subList(start, end);

        // 4. 封装到 MyBatis-Plus 的 Page 对象
        Page<SupervisorPerformanceSummaryVO> page = new Page<>(current, pageSize);
        page.setTotal(total);
        page.setRecords(pageList);

        return page;
    }


    /**
     * 将集合根据不同属性进行排序
     */
    public void sortPerformanceRankingList(List<SupervisorPerformanceSummaryVO> supervisorPerformanceSummaryVOS, MiniUserPerformanceSummaryRankQueryRequest miniUserPerformanceSummaryRankQueryRequest) {
        if (supervisorPerformanceSummaryVOS == null || supervisorPerformanceSummaryVOS.isEmpty()) {
            return; // 如果列表为空，不进行排序
        }

        // 创建一个 Comparator，根据 sortField 和 sortOrder 排序
        String sortField = miniUserPerformanceSummaryRankQueryRequest.getSortField();
        String sortOrder = miniUserPerformanceSummaryRankQueryRequest.getSortOrder();
        Comparator<SupervisorPerformanceSummaryVO> comparator = getComparatorForSortField(sortField);

        if (comparator == null) {
            return; // 如果没有有效的排序字段，跳过排序
        }

        // 判断排序顺序（升序或降序）
        if (CommonConstant.SORT_ORDER_DESC.equalsIgnoreCase(sortOrder)) {
            comparator = comparator.reversed(); // 如果是降序，反转 comparator
        }

        // 执行排序
        supervisorPerformanceSummaryVOS.sort(comparator);
    }



    // 根据 sortField 返回对应的 Comparator
    private static Comparator<SupervisorPerformanceSummaryVO> getComparatorForSortField(String sortField) {
        return switch (sortField) {
            case "empCount" -> Comparator.comparing(SupervisorPerformanceSummaryVO::getEmpCount);
            case "promoCount" -> Comparator.comparing(SupervisorPerformanceSummaryVO::getPromoCount);
            case "orderCount" -> Comparator.comparing(SupervisorPerformanceSummaryVO::getOrderCount);
            case "totalAmount" -> Comparator.comparing(SupervisorPerformanceSummaryVO::getTotalAmount);
            case "netAmount" -> Comparator.comparing(SupervisorPerformanceSummaryVO::getNetAmount);
            default -> null; // 无效的排序字段
        };
    }





    /**
     * 查看某个时间段的绩效
     */
    @Override
    public Map<String, Object> getPerformanceSummaryByStartAndEndTime(DateTime beginOfDay, DateTime endOfDay, UserRoleEnum userRoleEnum, Long userId) {
        Map<String, Object> performanceSummaryMap = new HashMap<>();
        Integer orderCount;
        BigDecimal orderAmount = BigDecimal.ZERO;
        Integer refundedCount = 0;
        BigDecimal refundedAmount = BigDecimal.ZERO;
        Integer promotionCount;


        LambdaQueryWrapper<CoursePromotionCommissionPending> coursePromotionQueryWrapper = new LambdaQueryWrapper<>();
        coursePromotionQueryWrapper.ge(CoursePromotionCommissionPending::getOrderCreateTime, beginOfDay);
        coursePromotionQueryWrapper.le(CoursePromotionCommissionPending::getOrderCreateTime, endOfDay);
        if (UserRoleEnum.SUPERVISOR.equals(userRoleEnum)) {
            coursePromotionQueryWrapper.eq(CoursePromotionCommissionPending::getFirstUserId, userId);
        } else if (UserRoleEnum.STAFF.equals(userRoleEnum)) {
            coursePromotionQueryWrapper.eq(CoursePromotionCommissionPending::getSecondUserId, userId);
        }
        coursePromotionQueryWrapper.select(CoursePromotionCommissionPending::getTotalAmount, CoursePromotionCommissionPending::getCommissionStatus);
        List<CoursePromotionCommissionPending> coursePromotionCommissionPendingList = coursePromotionCommissionPendingService.list(coursePromotionQueryWrapper);
        orderCount = coursePromotionCommissionPendingList.size();
        for (CoursePromotionCommissionPending coursePromotionCommissionPending : coursePromotionCommissionPendingList) {
            String commissionStatus = coursePromotionCommissionPending.getCommissionStatus();
            CommissionStatusEnum commissionStatusEnum = CommissionStatusEnum.getEnumByValue(commissionStatus);
            orderAmount = orderAmount.add(coursePromotionCommissionPending.getTotalAmount());
            if (CommissionStatusEnum.EXPIRED.equals(commissionStatusEnum)) {
                refundedCount ++;
                refundedAmount = refundedAmount.add(coursePromotionCommissionPending.getTotalAmount().multiply(SystemConstant.REFUND_RATE));
                orderAmount = orderAmount.subtract(coursePromotionCommissionPending.getTotalAmount().multiply(SystemConstant.REFUND_RATE));
            }
        }

        LambdaQueryWrapper<EmployeePromotionRecords> empQueryWrapper = new LambdaQueryWrapper<>();
        empQueryWrapper.ge(EmployeePromotionRecords::getCreateTime, beginOfDay);
        empQueryWrapper.le(EmployeePromotionRecords::getCreateTime, endOfDay);
        if (UserRoleEnum.SUPERVISOR.equals(userRoleEnum)) {
            empQueryWrapper.eq(EmployeePromotionRecords::getFirstUserId, userId);
        } else if (UserRoleEnum.STAFF.equals(userRoleEnum)) {
            empQueryWrapper.eq(EmployeePromotionRecords::getSecondUserId, userId);
        }
        empQueryWrapper.select(EmployeePromotionRecords::getId);
        promotionCount = Math.toIntExact(employeePromotionRecordsService.count(empQueryWrapper));

        performanceSummaryMap.put("orderCount", orderCount);
        performanceSummaryMap.put("orderAmount", orderAmount);
        performanceSummaryMap.put("refundCount", refundedCount);
        performanceSummaryMap.put("refundAmount", refundedAmount);
        performanceSummaryMap.put("promotionCount", promotionCount);
        return performanceSummaryMap;
    }


    /**
     * 经理查看仪表盘
     */
    @Override
    public WebQueryDashboardVO queryManagerDashboard() {
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal netAmount = BigDecimal.ZERO;
        Integer promoCount = 0;
        Integer superCount = 0;
        Integer empCount = 0;
        Integer orderCount = 0;
        BigDecimal toRelease = BigDecimal.ZERO;
        BigDecimal toSettle = BigDecimal.ZERO;
        BigDecimal settled = BigDecimal.ZERO;
        BigDecimal refunded = BigDecimal.ZERO;

        Integer todayOrderCount;
        BigDecimal todayOrderAmount;
        Integer todayRefundCount;
        BigDecimal todayRefundAmount;
        Integer todayPromotionCount;

        Integer monthOrderCount;
        BigDecimal monthOrderAmount;
        Integer monthRefundCount;
        BigDecimal monthRefundAmount;
        Integer monthPromotionCount;
        // 封装Map集合（键：userId, 值：权限）
        Map<Long, String> userRoleMap = new HashMap<>();
        LambdaQueryWrapper<UserInfo> userInfoQueryWrapper = new LambdaQueryWrapper<>();
        userInfoQueryWrapper.select(UserInfo::getId, UserInfo::getUserRole);
        List<UserInfo> userInfoList = userInfoMapper.selectList(userInfoQueryWrapper);
        for (UserInfo userInfo : userInfoList) {
            userRoleMap.put(userInfo.getId(), userInfo.getUserRole());
        }
        LambdaQueryWrapper<UserPerformanceSummary> userPerformanceSummaryQueryWrapper = new LambdaQueryWrapper<>();
        userPerformanceSummaryQueryWrapper.select(UserPerformanceSummary::getUserId, UserPerformanceSummary::getTotalAmount,
                UserPerformanceSummary::getNetAmount, UserPerformanceSummary::getPromoCount, UserPerformanceSummary::getEmpCount,
                UserPerformanceSummary::getOrderCount, UserPerformanceSummary::getToRelease, UserPerformanceSummary::getToSettle,
                UserPerformanceSummary::getSettled, UserPerformanceSummary::getRefunded);
        List<UserPerformanceSummary> userPerformanceSummaryList = this.list(userPerformanceSummaryQueryWrapper);
        for (UserPerformanceSummary userPerformanceSummary : userPerformanceSummaryList) {
            Long userId = userPerformanceSummary.getUserId();
            String userRole = userRoleMap.get(userId);
            UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);
            if (UserRoleEnum.SUPERVISOR.equals(userRoleEnum)) {
                totalAmount = totalAmount.add(userPerformanceSummary.getTotalAmount());
                netAmount = netAmount.add(userPerformanceSummary.getNetAmount());
                promoCount += userPerformanceSummary.getPromoCount();
                empCount += userPerformanceSummary.getEmpCount();
                orderCount += userPerformanceSummary.getOrderCount();
                superCount += 1;
            }
            toRelease = toRelease.add(userPerformanceSummary.getToRelease());
            toSettle = toSettle.add(userPerformanceSummary.getToSettle());
            settled = settled.add(userPerformanceSummary.getSettled());
            refunded = refunded.add(userPerformanceSummary.getRefunded());
        }


        DateTime now = DateUtil.date();

        // 查看今天的绩效
        DateTime beginOfDay = DateUtil.beginOfDay(now);
        DateTime endOfDay = DateUtil.endOfDay(now);
        Map<String, Object> todayPerformanceSummary = this.getPerformanceSummaryByStartAndEndTime(beginOfDay, endOfDay, UserRoleEnum.MANAGER, null);
        todayOrderCount = (Integer) todayPerformanceSummary.get("orderCount");
        todayOrderAmount = (BigDecimal) todayPerformanceSummary.get("orderAmount");
        todayRefundCount = (Integer) todayPerformanceSummary.get("refundCount");
        todayRefundAmount = (BigDecimal) todayPerformanceSummary.get("refundAmount");
        todayPromotionCount = (Integer) todayPerformanceSummary.get("promotionCount");

        // 查看本月的绩效
        DateTime beginOfMonth = DateUtil.beginOfMonth(now);
        DateTime endOfMonth = DateUtil.endOfMonth(now);
        Map<String, Object> monthPerformanceSummary = this.getPerformanceSummaryByStartAndEndTime(beginOfMonth, endOfMonth, UserRoleEnum.MANAGER, null);
        monthOrderCount = (Integer) monthPerformanceSummary.get("orderCount");
        monthOrderAmount = (BigDecimal) monthPerformanceSummary.get("orderAmount");
        monthRefundCount = (Integer) monthPerformanceSummary.get("refundCount");
        monthRefundAmount = (BigDecimal) monthPerformanceSummary.get("refundAmount");
        monthPromotionCount = (Integer) monthPerformanceSummary.get("promotionCount");

        WebQueryDashboardVO webQueryDashboardVO = WebQueryDashboardVO.builder()
                .totalAmount(totalAmount)
                .netAmount(netAmount)
                .promoCount(promoCount)
                .superCount(superCount)
                .empCount(empCount)
                .orderCount(orderCount)
                .toRelease(toRelease)
                .toSettle(toSettle)
                .settled(settled)
                .refunded(refunded)
                .todayOrderCount(todayOrderCount)
                .todayOrderAmount(todayOrderAmount)
                .todayRefundCount(todayRefundCount)
                .todayRefundAmount(todayRefundAmount)
                .todayPromotionCount(todayPromotionCount)
                .monthOrderCount(monthOrderCount)
                .monthOrderAmount(monthOrderAmount)
                .monthRefundCount(monthRefundCount)
                .monthRefundAmount(monthRefundAmount)
                .monthPromotionCount(monthPromotionCount)
                .build();
        return webQueryDashboardVO;
    }


    /**
     * 主管查看仪表盘
     */
    @Override
    public WebQueryDashboardVO querySupervisorOrStaffDashboard(UserRoleEnum userRoleEnum, Long userId) {
        BigDecimal totalAmount;
        BigDecimal netAmount;
        Integer promoCount;
        Integer superCount = 0;
        Integer empCount;
        Integer orderCount;
        BigDecimal toRelease;
        BigDecimal toSettle;
        BigDecimal settled;
        BigDecimal refunded;

        Integer todayOrderCount;
        BigDecimal todayOrderAmount;
        Integer todayRefundCount;
        BigDecimal todayRefundAmount;
        Integer todayPromotionCount;

        Integer monthOrderCount;
        BigDecimal monthOrderAmount;
        Integer monthRefundCount;
        BigDecimal monthRefundAmount;
        Integer monthPromotionCount;
        LambdaQueryWrapper<UserPerformanceSummary> userPerformanceSummaryLambdaQueryWrapper = commonService.buildQueryWrapperByField(UserPerformanceSummary::getUserId, userId, this);
        UserPerformanceSummary userPerformanceSummary = this.getOne(userPerformanceSummaryLambdaQueryWrapper);
        totalAmount = userPerformanceSummary.getTotalAmount();
        netAmount = userPerformanceSummary.getNetAmount();
        promoCount = userPerformanceSummary.getPromoCount();
        empCount = userPerformanceSummary.getEmpCount();
        orderCount = userPerformanceSummary.getOrderCount();
        toRelease = userPerformanceSummary.getToRelease();
        toSettle = userPerformanceSummary.getToSettle();
        settled = userPerformanceSummary.getSettled();
        refunded = userPerformanceSummary.getRefunded();


        DateTime now = DateUtil.date();

        // 查看今天的绩效
        DateTime beginOfDay = DateUtil.beginOfDay(now);
        DateTime endOfDay = DateUtil.endOfDay(now);
        Map<String, Object> todayPerformanceSummary = this.getPerformanceSummaryByStartAndEndTime(beginOfDay, endOfDay, userRoleEnum, userId);
        todayOrderCount = (Integer) todayPerformanceSummary.get("orderCount");
        todayOrderAmount = (BigDecimal) todayPerformanceSummary.get("orderAmount");
        todayRefundCount = (Integer) todayPerformanceSummary.get("refundCount");
        todayRefundAmount = (BigDecimal) todayPerformanceSummary.get("refundAmount");
        todayPromotionCount = (Integer) todayPerformanceSummary.get("promotionCount");

        // 查看本月的绩效
        DateTime beginOfMonth = DateUtil.beginOfMonth(now);
        DateTime endOfMonth = DateUtil.beginOfMonth(now);
        Map<String, Object> monthPerformanceSummary = this.getPerformanceSummaryByStartAndEndTime(beginOfMonth, endOfMonth, userRoleEnum, userId);
        monthOrderCount = (Integer) monthPerformanceSummary.get("orderCount");
        monthOrderAmount = (BigDecimal) monthPerformanceSummary.get("orderAmount");
        monthRefundCount = (Integer) monthPerformanceSummary.get("refundCount");
        monthRefundAmount = (BigDecimal) monthPerformanceSummary.get("refundAmount");
        monthPromotionCount = (Integer) monthPerformanceSummary.get("promotionCount");

        WebQueryDashboardVO webQueryDashboardVO = WebQueryDashboardVO.builder()
                .totalAmount(totalAmount)
                .netAmount(netAmount)
                .promoCount(promoCount)
                .superCount(superCount)
                .empCount(empCount)
                .orderCount(orderCount)
                .toRelease(toRelease)
                .toSettle(toSettle)
                .settled(settled)
                .refunded(refunded)
                .todayOrderCount(todayOrderCount)
                .todayOrderAmount(todayOrderAmount)
                .todayRefundCount(todayRefundCount)
                .todayRefundAmount(todayRefundAmount)
                .todayPromotionCount(todayPromotionCount)
                .monthOrderCount(monthOrderCount)
                .monthOrderAmount(monthOrderAmount)
                .monthRefundCount(monthRefundCount)
                .monthRefundAmount(monthRefundAmount)
                .monthPromotionCount(monthPromotionCount)
                .build();
        return webQueryDashboardVO;
    }


}




