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

import cn.hutool.core.util.RandomUtil;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.constant.CommonConstant;
import com.greenorange.promotion.constant.SystemConstant;
import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.mapper.UserInfoMapper;
import com.greenorange.promotion.mapper.UserPerformanceSummaryMapper;
import com.greenorange.promotion.model.dto.advancementApply.AdvancementApplyApproveRequest;
import com.greenorange.promotion.model.dto.projectCommission.ProjectCommissionAddRequest;
import com.greenorange.promotion.model.dto.userInfo.*;
import com.greenorange.promotion.model.entity.*;
import com.greenorange.promotion.model.enums.ReviewStatusEnum;
import com.greenorange.promotion.model.enums.UserRoleEnum;
import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.project.ProjectCommissionService;
import com.greenorange.promotion.service.project.ProjectDetailService;
import com.greenorange.promotion.service.project.SubUserProjectCommissionService;
import com.greenorange.promotion.service.userInfo.*;
import com.greenorange.promotion.service.wechat.WechatGetQrcodeService;
import com.greenorange.promotion.utils.JWTUtils;
import com.greenorange.promotion.utils.RegexUtils;
import com.greenorange.promotion.utils.SendSmsUtil;
import com.greenorange.promotion.utils.SqlUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
* @author 35880
* @description 针对表【user_info(用户基本信息表)】的数据库操作Service实现
* @createDate 2025-04-24 11:47:37
*/
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
    implements UserInfoService{

    @Resource
    private JWTUtils jwtUtils;


    @Resource
    private CommonService commonService;


    @Resource
    private UserMainInfoService userMainInfoService;


    @Resource
    private RedisTemplate<String, String> redisTemplate;


    @Resource
    private WechatGetQrcodeService wechatGetQrcodeService;


    @Resource
    private ProjectCommissionService projectCommissionService;


    @Resource
    private SubUserProjectCommissionService subUserProjectCommissionService;


    @Resource
    private UserInfoMapper userInfoMapper;


    @Resource
    private ProjectDetailService projectDetailService;


    @Resource
    private AdvancementApplyService advancementApplyService;


    @Resource
    private UserPerformanceSummaryService userPerformanceSummaryService;


    @Resource
    private EmployeePromotionRecordsService employeePromotionRecordsService;






    /**
     * 获取查询条件
     */
    @Override
    public QueryWrapper<UserInfo> getQueryWrapper(UserInfoQueryRequest userInfoQueryRequest) {
        Long id = userInfoQueryRequest.getId();
        String phoneNumber = userInfoQueryRequest.getPhoneNumber();
        String userRole = userInfoQueryRequest.getUserRole();
        String sortField = userInfoQueryRequest.getSortField();
        String sortOrder = userInfoQueryRequest.getSortOrder();
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(id != null, "id", id);
        queryWrapper.eq(StringUtils.isNotBlank(phoneNumber), "phoneNumber", phoneNumber);
        queryWrapper.eq(StringUtils.isNotBlank(userRole), "userRole", userRole);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
        return queryWrapper;
    }


    /**
     * web端用户登录
     */
    @Override
    public String userInfoLogin(UserInfoLoginRequest userInfoLoginRequest) {
        String userAccount = userInfoLoginRequest.getUserAccount();
        String userPassword = userInfoLoginRequest.getUserPassword();
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserInfo::getUserAccount, userAccount).eq(UserInfo::getUserPassword, userPassword);
        UserInfo userInfo = this.getOne(lambdaQueryWrapper);
        ThrowUtils.throwIf(userInfo == null, ErrorCode.OPERATION_ERROR, "账号或密码错误");

        String userRole = userInfo.getUserRole();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);
        ThrowUtils.throwIf(!UserRoleEnum.ADMIN.equals(userRoleEnum) && !UserRoleEnum.BOSS.equals(userRoleEnum), ErrorCode.NO_AUTH_ERROR);

        Map<String, String> payload = new HashMap<>();
        payload.put("userAccount", userAccount);
        payload.put("userPassword", userPassword);
        return jwtUtils.generateToken(payload);
    }






    /**
     * 小程序用户注册
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void userInfoMiniRegister(UserInfoRegisterRequest userInfoRegisterRequest) {
        String nickName = userInfoRegisterRequest.getNickName();
        String phoneNumber = userInfoRegisterRequest.getPhoneNumber();
        String verificationCode = userInfoRegisterRequest.getVerificationCode();
        String userRole = userInfoRegisterRequest.getUserRole();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);
        // 校验用户手机号和验证码
        checkPhoneAndVerificationCode(phoneNumber, verificationCode, userRoleEnum);
        // 如果注册主管，校验昵称是否重复
        if (UserRoleEnum.SUPERVISOR.equals(userRoleEnum)) {
            LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(UserInfo::getNickName, nickName).eq(UserInfo::getUserRole, UserConstant.SUPERVISOR_ROLE);
            UserInfo userInfo = this.getOne(lambdaQueryWrapper);
            ThrowUtils.throwIf(userInfo != null, ErrorCode.OPERATION_ERROR, "昵称已存在");
        }

        // 根据邀请码获得上级用户信息
        String invitationCode = userInfoRegisterRequest.getInvitationCode();
        UserInfo parentUserInfo = getParentUserInfoByInvitationCode(invitationCode);
        String parentUserRole = parentUserInfo.getUserRole();
        UserRoleEnum parentUserRoleEnum = UserRoleEnum.getEnumByValue(parentUserRole);
        Map<UserRoleEnum, Integer> userRoleMap = new HashMap<>();
        userRoleMap.put(UserRoleEnum.USER, 1);
        userRoleMap.put(UserRoleEnum.STAFF, 2);
        userRoleMap.put(UserRoleEnum.SUPERVISOR, 3);
        userRoleMap.put(UserRoleEnum.MANAGER, 4);
        int level = userRoleMap.get(parentUserRoleEnum) - userRoleMap.get(userRoleEnum);
        if (!(level == 1 || level == 0 && UserRoleEnum.USER.equals(userRoleEnum) && UserRoleEnum.USER.equals(parentUserRoleEnum)))
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "邀请码错误");

        // 保存用户
        UserInfo myUserInfo = commonService.copyProperties(userInfoRegisterRequest, UserInfo.class);
        myUserInfo.setParentUserId(parentUserInfo.getId());
        // 获取唯一的邀请码
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(UserInfo::getInvitationCode);
        lambdaQueryWrapper.in(UserInfo::getUserRole, UserConstant.DEFAULT_ROLE, UserConstant.STAFF_ROLE, UserConstant.SUPERVISOR_ROLE, UserConstant.MANAGER_ROLE);
        List<UserInfo> userInfos;
        String inviteCode;
        while (true) {
            String tempCode = RandomUtil.randomNumbers(6);
            userInfos = this.list(lambdaQueryWrapper);
            boolean exists = userInfos.stream()
                    .anyMatch(u -> u.getInvitationCode().equals(tempCode));
            if (!exists) {
                inviteCode = tempCode;
                break;
            }
        }
        myUserInfo.setInvitationCode(inviteCode);
        myUserInfo.setUserAccount(phoneNumber);
        myUserInfo.setUserRole(userRole);
        myUserInfo.setUserAvatar(UserConstant.USER_DEFAULT_AVATAR);
        this.save(myUserInfo);

        // 添加用户绩效记录
        if (UserRoleEnum.SUPERVISOR.equals(userRoleEnum) || UserRoleEnum.STAFF.equals(userRoleEnum)) {
            UserPerformanceSummary userPerformanceSummary = UserPerformanceSummary.builder().userId(myUserInfo.getId()).build();
            userPerformanceSummaryService.save(userPerformanceSummary);
        }

        // 更新上级用户的数量
        updateParentUserInfoEmpCount(myUserInfo.getId(), userRoleEnum);

        // 生成邀请二维码
        String invitationQrcode = generateInvitationQrcode(myUserInfo.getInvitationCode(), userRoleEnum);
        UserMainInfo userMainInfo = UserMainInfo.builder().userId(myUserInfo.getId()).inviteQrCode(invitationQrcode).build();
        userMainInfoService.save(userMainInfo);

        // 批量保存当前用户的项目明细抽佣记录和下级用户项目明细抽佣记录
        saveBatchProjectCommissionAndSubUserProjectCommission(myUserInfo.getId(), parentUserInfo.getId());
    }



    /**
     * 小程序端用户密码登录
     */
    @Override
    public String userInfoMiniLoginByPwd(UserInfoMiniPasswordLoginRequest userInfoMiniPasswordLoginRequest) {
        String phoneNumber = userInfoMiniPasswordLoginRequest.getPhoneNumber();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式无效");
        String userPassword = userInfoMiniPasswordLoginRequest.getUserPassword();
        String userRole = userInfoMiniPasswordLoginRequest.getUserRole();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (UserRoleEnum.USER.equals(userRoleEnum)) {
            lambdaQueryWrapper.eq(UserInfo::getUserRole, userRole);
            lambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber);
            UserInfo userInfo = this.getOne(lambdaQueryWrapper);
            ThrowUtils.throwIf(userInfo == null, ErrorCode.OPERATION_ERROR, "手机号未注册");
        } else {
            lambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber);
            lambdaQueryWrapper.in(UserInfo::getUserRole, UserRoleEnum.STAFF.getValue(), UserRoleEnum.SUPERVISOR.getValue(), UserRoleEnum.MANAGER.getValue());
            UserInfo userInfo = this.getOne(lambdaQueryWrapper);
            ThrowUtils.throwIf(userInfo == null, ErrorCode.OPERATION_ERROR, "手机号未注册");
            UserRoleEnum currentUserRoleEnum = UserRoleEnum.getEnumByValue(userInfo.getUserRole());
            ThrowUtils.throwIf(!userRoleEnum.equals(currentUserRoleEnum), ErrorCode.OPERATION_ERROR, "该手机号为" + currentUserRoleEnum.getText() + "账号");
        }
        lambdaQueryWrapper.eq(UserInfo::getUserPassword, userPassword);
        UserInfo userInfo = this.getOne(lambdaQueryWrapper);
        ThrowUtils.throwIf(userInfo == null, ErrorCode.OPERATION_ERROR, "密码不正确");


        Map<String, String> payload = new HashMap<>();
        payload.put("userAccount", phoneNumber);
        payload.put("userPassword", userPassword);
        payload.put("userRole", userInfo.getUserRole());
        return jwtUtils.generateToken(payload);
    }




    /**
     * 小程序用户验证码登录
     */
    @Override
    public String userInfoMiniLoginByVcd(UserInfoMiniVerifyCodeLoginRequest userInfoMiniVerifyCodeLoginRequest) {
        String phoneNumber = userInfoMiniVerifyCodeLoginRequest.getPhoneNumber();
        String verificationCode = userInfoMiniVerifyCodeLoginRequest.getVerificationCode();
        // 校验用户手机号和验证码
        checkPhoneAndVerificationCode(phoneNumber, verificationCode, null);

        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber);
        UserInfo userInfo = this.getOne(lambdaQueryWrapper);
        String userPassword = userInfo.getUserPassword();

        Map<String, String> payload = new HashMap<>();
        payload.put("userAccount", phoneNumber);
        payload.put("userPassword", userPassword);
        payload.put("userRole", userInfo.getUserRole());
        return jwtUtils.generateToken(payload);
    }



    /**
     * 小程序用户重置密码
     */
    @Override
    public void userInfoMiniResetPwd(UserInfoResetRequest userInfoResetRequest, boolean isInner) {
        String phoneNumber = userInfoResetRequest.getPhoneNumber();
        String verificationCode = userInfoResetRequest.getVerificationCode();
        // 校验用户手机号和验证码
        checkPhoneAndVerificationCode(phoneNumber, verificationCode, null);

        String userPassword = userInfoResetRequest.getUserPassword();
        String userConfirmPassword = userInfoResetRequest.getUserConfirmPassword();
        ThrowUtils.throwIf(!userPassword.equals(userConfirmPassword), ErrorCode.OPERATION_ERROR, "两次密码不一致");

        // 更新用户密码
        String userRole = userInfoResetRequest.getUserRole();
        LambdaUpdateWrapper<UserInfo> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(UserInfo::getPhoneNumber, phoneNumber).set(UserInfo::getUserPassword, userPassword);
        lambdaUpdateWrapper.eq(UserInfo::getUserRole, userRole);
        this.update(lambdaUpdateWrapper);

        if (isInner) {
            // 获取token的过期时间
            String sourceToken = userInfoResetRequest.getSourceToken();
            if (StringUtils.isNotBlank(sourceToken)) {
                DecodedJWT decodedJWT = jwtUtils.verify(sourceToken);
                long expirationTime = decodedJWT.getExpiresAt().getTime() - System.currentTimeMillis();
                // 将token存入Redis黑名单，并设置过期时间与token一致
                redisTemplate.opsForValue().set(sourceToken, sourceToken, expirationTime, TimeUnit.MILLISECONDS);
            }
        }
    }


    /**
     * 小程序用户获取验证码（用于密码登录和忘记密码）
     */
    @Override
    public String getVerificationCodeForPwdLogin(VerificationCodeGetRequest verificationCodeGetRequest) {
        String phoneNumber = verificationCodeGetRequest.getPhoneNumber();
        String userRole = verificationCodeGetRequest.getUserRole();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式错误");

        // 判断手机号是否已注册
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber).eq(UserInfo::getUserRole, userRole);
        UserInfo userInfo = this.getOne(lambdaQueryWrapper);
        ThrowUtils.throwIf(userInfo == null, ErrorCode.OPERATION_ERROR, "手机号未注册");

        String verificationCode = SendSmsUtil.getVerificationCode(phoneNumber);
        ThrowUtils.throwIf(verificationCode == null, ErrorCode.OPERATION_ERROR, "验证码获取失败");
        redisTemplate.opsForValue().set(SystemConstant.VERIFICATION_CODE + ":" + verificationCode, verificationCode, 5, TimeUnit.MINUTES);
        return verificationCode;
    }


    /**
     * 小程序用户获取验证码（用于注册）
     */
    @Override
    public String getVerificationCodeForRegister(VerificationCodeGetRequest verificationCodeGetRequest) {
        String phoneNumber = verificationCodeGetRequest.getPhoneNumber();
        String userRole = verificationCodeGetRequest.getUserRole();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式错误");

        // 判断手机号是否已注册
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);
        if (userRoleEnum == UserRoleEnum.USER) {
            lambdaQueryWrapper.eq(UserInfo::getUserRole, UserConstant.DEFAULT_ROLE);
        } else {
            lambdaQueryWrapper.in(UserInfo::getUserRole, UserConstant.STAFF_ROLE, UserConstant.SUPERVISOR_ROLE, UserConstant.MANAGER_ROLE);
        }
        lambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber);
        UserInfo userInfo = this.getOne(lambdaQueryWrapper);
        ThrowUtils.throwIf(userInfo != null, ErrorCode.OPERATION_ERROR, "手机号已注册");

        String verificationCode = SendSmsUtil.getVerificationCode(phoneNumber);
        ThrowUtils.throwIf(verificationCode == null, ErrorCode.OPERATION_ERROR, "验证码获取失败");
        redisTemplate.opsForValue().set(SystemConstant.VERIFICATION_CODE + ":" + verificationCode, verificationCode, 5, TimeUnit.MINUTES);
        return verificationCode;
    }



    /**
     * 校验用户手机号和验证码
     */
    @Override
    public void checkPhoneAndVerificationCode(String phoneNumber, String verificationCode, UserRoleEnum userRoleEnum) {
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式无效");
        if (userRoleEnum != null) {
            LambdaQueryWrapper<UserInfo> phoneNumberLambdaQueryWrapper = new LambdaQueryWrapper<>();
            phoneNumberLambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber);
            phoneNumberLambdaQueryWrapper = getQueryWrapperByUserRole(userRoleEnum, phoneNumberLambdaQueryWrapper);
            UserInfo userInfo = this.getOne(phoneNumberLambdaQueryWrapper);
            if (userInfo != null) {
                String userRole = userInfo.getUserRole();
                UserRoleEnum currentUserRoleEnum = UserRoleEnum.getEnumByValue(userRole);
                if (!currentUserRoleEnum.equals(userRoleEnum)) throw new BusinessException(ErrorCode.OPERATION_ERROR, "该手机号为"+ currentUserRoleEnum.getText() +"账号");
                else throw new BusinessException(ErrorCode.OPERATION_ERROR, "该手机号已注册");
            }
        }
        String code = redisTemplate.opsForValue().get(SystemConstant.VERIFICATION_CODE + ":" + verificationCode);
        ThrowUtils.throwIf(code == null, ErrorCode.OPERATION_ERROR, "验证码已失效");

//        // 移除验证码
//        redisTemplate.delete(SystemConstant.VERIFICATION_CODE + ":" + verificationCode);
    }


    /**
     * 根据用户权限来获取查询条件
     */
    @Override
    public LambdaQueryWrapper<UserInfo> getQueryWrapperByUserRole(UserRoleEnum userRoleEnum, LambdaQueryWrapper<UserInfo> userInfoLambdaQueryWrapper) {
        if (userRoleEnum.equals(UserRoleEnum.USER)) {
            userInfoLambdaQueryWrapper.eq(UserInfo::getUserRole, userRoleEnum.getValue());
        } else {
            userInfoLambdaQueryWrapper.in(UserInfo::getUserRole, UserRoleEnum.MANAGER.getValue(), UserRoleEnum.SUPERVISOR.getValue(), UserRoleEnum.STAFF.getValue());
        }
        return userInfoLambdaQueryWrapper;
    }


    /**
     * 小程序端员工信息注册
     */
    @Override
    public void staffUserInfoMiniRegister(AdvancementApplyApproveRequest advancementApplyApproveRequest) {
        // 获取晋升申请记录信息
        Long applyId = advancementApplyApproveRequest.getApplyId();
        AdvancementApply advancementApply = advancementApplyService.getById(applyId);
        String phoneNumber = advancementApply.getPhone();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式无效");
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber)
                .in(UserInfo::getUserRole, UserConstant.STAFF_ROLE, UserConstant.SUPERVISOR_ROLE, UserConstant.MANAGER_ROLE);
        UserInfo userInfo = this.getOne(lambdaQueryWrapper);
        ThrowUtils.throwIf(userInfo != null, ErrorCode.OPERATION_ERROR, "手机号已注册");

        // 根据邀请码获得上级用户信息
        Long userId = advancementApplyApproveRequest.getUserId();
        UserInfo parentUserInfo = this.getById(userId);

        // 添加用户
        UserInfo myUserInfo = UserInfo.builder()
                .nickName(advancementApply.getName())
                .phoneNumber(advancementApply.getPhone())
                .userAvatar(UserConstant.USER_DEFAULT_AVATAR)
                .userAccount(phoneNumber)
                .userPassword(RandomUtil.randomNumbers(6) + RandomStringUtils.random(3, true, false))
                .invitationCode(RandomUtil.randomNumbers(6))
                .userRole(UserConstant.STAFF_ROLE)
                .parentUserId(parentUserInfo.getId())
                .build();
        this.save(myUserInfo);

        // 添加用户绩效记录
        UserPerformanceSummary userPerformanceSummary = UserPerformanceSummary.builder().userId(myUserInfo.getId()).build();
        userPerformanceSummaryService.save(userPerformanceSummary);
        // 更新上级主管用户的员工数量和经理用户的员工数量
        updateParentUserInfoEmpCount(myUserInfo.getId(), UserRoleEnum.STAFF);

        // 生成邀请二维码
        String invitationQrcode = generateInvitationQrcode(myUserInfo.getInvitationCode(), UserRoleEnum.STAFF);
        UserMainInfo userMainInfo = UserMainInfo.builder().userId(myUserInfo.getId()).inviteQrCode(invitationQrcode).build();
        userMainInfoService.save(userMainInfo);

//        // 批量保存当前用户的项目明细抽佣记录和下级用户项目明细抽佣记录
//        saveBatchProjectCommissionAndSubUserProjectCommission(myUserInfo.getId(), parentUserInfo.getId());

        // 修改晋升申请记录的审核状态，并绑定申请成功的用户id
        LambdaUpdateWrapper<AdvancementApply> advancementApplyLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        advancementApplyLambdaUpdateWrapper.eq(AdvancementApply::getId, advancementApply.getId())
                .set(AdvancementApply::getReviewStatus, ReviewStatusEnum.APPROVED.getValue())
                .set(AdvancementApply::getUserId, myUserInfo.getId());
        advancementApplyService.update(advancementApplyLambdaUpdateWrapper);
    }


    /**
     * 更新上级用户的数量
     */
    private void updateParentUserInfoEmpCount(Long userId, UserRoleEnum userRoleEnum) {
        if (UserRoleEnum.SUPERVISOR.equals(userRoleEnum)) return ;
        List<Long> pathToRoot = findPathToRoot(userId);
        List<Long> subPathToRoot;
        if (UserRoleEnum.USER.equals(userRoleEnum)) subPathToRoot = pathToRoot.subList(1, 3);
        else subPathToRoot = pathToRoot.subList(1, 2);
        List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetField(subPathToRoot, userPerformanceSummaryService, Function.identity(), UserPerformanceSummary::getUserId);
        for (UserPerformanceSummary userPerformanceSummary : userPerformanceSummaryList) {
            if (userRoleEnum.equals(UserRoleEnum.USER)) {
                userPerformanceSummary.setPromoCount(userPerformanceSummary.getPromoCount() + 1);
            } else if (userRoleEnum.equals(UserRoleEnum.STAFF)) {
                userPerformanceSummary.setEmpCount(userPerformanceSummary.getEmpCount() + 1);
            }
        }
        userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList);

        // 如果是普通用户，就添加一条员工推广记录
        if (userRoleEnum.equals(UserRoleEnum.USER)) {
            EmployeePromotionRecords employeePromotionRecords = EmployeePromotionRecords.builder()
                    .firstUserId(subPathToRoot.get(0))
                    .secondUserId(subPathToRoot.get(1))
                    .userId(userId)
                    .build();
            employeePromotionRecordsService.save(employeePromotionRecords);
        }
    }


    /**
     * 获取小程序用户的查询条件
     */
    @Override
    public LambdaQueryWrapper<UserInfo> getMiniUserInfoQueryWrapper() {
        LambdaQueryWrapper<UserInfo> userInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userInfoLambdaQueryWrapper.in(UserInfo::getUserRole, UserRoleEnum.USER, UserRoleEnum.MANAGER, UserRoleEnum.SUPERVISOR, UserRoleEnum.STAFF);
        return userInfoLambdaQueryWrapper;
    }


    /**
     * 根据邀请码获得上级用户信息
     */
    private UserInfo getParentUserInfoByInvitationCode(String invitationCode) {
        LambdaQueryWrapper<UserInfo> invitedLambdaQueryWrapper = new LambdaQueryWrapper<>();
        invitedLambdaQueryWrapper.eq(UserInfo::getInvitationCode, invitationCode);
        UserInfo parentUserInfo = this.getOne(invitedLambdaQueryWrapper);
        ThrowUtils.throwIf(parentUserInfo == null, ErrorCode.OPERATION_ERROR, "邀请码错误");
        return parentUserInfo;
    }


    /**
     *  批量更新父级用户团队人数
     */
    private UserMainInfo updateParentUserInfoTeamCount(Long userId) {
        UserMainInfo userMainInfo = new UserMainInfo();
        userMainInfo.setUserId(userId);
        List<Long> pathToRoot = this.findPathToRoot(userId);
        List<UserMainInfo> userMainInfoList = commonService.findByFieldInTargetField(pathToRoot, userMainInfoService, id -> id, UserMainInfo::getUserId);
        for (UserMainInfo mainInfo : userMainInfoList) {
            mainInfo.setTeamSize(mainInfo.getTeamSize() + 1);
        }
        userMainInfoService.updateBatchById(userMainInfoList);
        return userMainInfo;
    }



    /**
     * 生成邀请二维码
     */
    private String generateInvitationQrcode(String invitationCode, UserRoleEnum userRoleEnum) {
        try {
            return wechatGetQrcodeService.getWxQrCode(invitationCode, userRoleEnum);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 批量保存当前用户的项目明细抽佣记录和下级用户项目明细抽佣记录
     */
    private void saveBatchProjectCommissionAndSubUserProjectCommission(Long userId, Long parentUserId) {
        // 查询上级用户的项目抽佣记录
        List<ProjectCommission> projectCommissionList = commonService.findByFieldEqTargetField(ProjectCommission::getUserId, parentUserId, projectCommissionService);
        // 封装Map集合（键：项目明细id, 值：项目最小价格）
        Map<Long, BigDecimal> projectDetailMinPriceMap = new HashMap<>();
        List<ProjectDetail> projectDetailList = commonService.findByFieldInTargetFieldWithSpecificFields(projectCommissionList, projectDetailService, ProjectCommission::getProjectDetailId, ProjectDetail::getId,
                List.of(ProjectDetail::getId, ProjectDetail::getProjectMinSettlementPrice));
        for (ProjectDetail projectDetail : projectDetailList) {
            projectDetailMinPriceMap.put(projectDetail.getId(), projectDetail.getProjectMinSettlementPrice());
        }
        // 插入当前用户的项目抽佣记录
        List<ProjectCommission> projectCommissions = new ArrayList<>();
        for (ProjectCommission projectCommission : projectCommissionList) {
            ProjectCommissionAddRequest projectCommissionAddRequest = commonService.copyProperties(projectCommission, ProjectCommissionAddRequest.class);
            ProjectCommission proCommission = commonService.copyProperties(projectCommissionAddRequest, ProjectCommission.class);
            // 获取当前项目明细的最小结算价格
            BigDecimal projectMinSettlementPrice = projectDetailMinPriceMap.get(projectCommission.getProjectDetailId());
            BigDecimal currentSettlementPrice = projectCommission.getMyUnitPrice().multiply(BigDecimal.ONE.subtract(projectCommission.getCurrentCommissionRate().divide(BigDecimal.valueOf(100))));
            // 比较当前结算价格和项目明细最小结算价格，取出最大值
            proCommission.setMyUnitPrice(projectMinSettlementPrice.max(currentSettlementPrice));
            proCommission.setCurrentCommissionRate(BigDecimal.ZERO);
            proCommission.setUserId(userId);
            projectCommissions.add(proCommission);
        }
        projectCommissionService.saveBatch(projectCommissions);
        // 插入下级用户的项目明细抽佣记录
        List<SubUserProjectCommission> subUserProjectCommissionList = new ArrayList<>();
        for (ProjectCommission projectCommission : projectCommissionList) {
            ProjectCommissionAddRequest projectCommissionAddRequest = commonService.copyProperties(projectCommission, ProjectCommissionAddRequest.class);
            SubUserProjectCommission subUserProjectCommission = commonService.copyProperties(projectCommissionAddRequest, SubUserProjectCommission.class);
            subUserProjectCommission.setSubUserId(userId);
            subUserProjectCommissionList.add(subUserProjectCommission);
        }
        subUserProjectCommissionService.saveBatch(subUserProjectCommissionList);
    }



    /**
     * 查询从 userId 一路到根节点的所有 id，按 depth 倒序（根先出）
     */
    @Override
    public List<Long> findPathToRoot(Long userId) {
        return userInfoMapper.findPathToRoot(userId);
    }



    /**
     * 查询当前用户的所有下级用户（包括间接）
     */
    @Override
    public List<Long> findAllSubUser(Long userId) {
        return userInfoMapper.findAllSubUser(userId);
    }





}




