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

import cn.hutool.core.util.RandomUtil;
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.ThrowUtils;
import com.greenorange.promotion.mapper.UserInfoMapper;
import com.greenorange.promotion.model.dto.projectCommission.ProjectCommissionAddRequest;
import com.greenorange.promotion.model.dto.userInfo.*;
import com.greenorange.promotion.model.entity.ProjectCommission;
import com.greenorange.promotion.model.entity.SubUserProjectCommission;
import com.greenorange.promotion.model.entity.UserInfo;
import com.greenorange.promotion.model.entity.UserMainInfo;
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.SubUserProjectCommissionService;
import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.userInfo.UserMainInfoService;
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.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* @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;


    /**
     * 获取查询条件
     */
    @Override
    public QueryWrapper<UserInfo> getQueryWrapper(UserInfoQueryRequest userInfoQueryRequest) {
        Long id = userInfoQueryRequest.getId();
        String phoneNumber = userInfoQueryRequest.getPhoneNumber();
        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.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
    public void userInfoMiniRegister(UserInfoRegisterRequest userInfoRegisterRequest) {
        String phoneNumber = userInfoRegisterRequest.getPhoneNumber();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式无效");
        LambdaQueryWrapper<UserInfo> phoneNumberLambdaQueryWrapper = new LambdaQueryWrapper<>();
        phoneNumberLambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber);
        UserInfo userInfo = this.getOne(phoneNumberLambdaQueryWrapper);
        ThrowUtils.throwIf(userInfo != null, ErrorCode.OPERATION_ERROR, "手机号已注册");

        String verificationCode = userInfoRegisterRequest.getVerificationCode();
        String code = redisTemplate.opsForValue().get(SystemConstant.VERIFICATION_CODE + ":" + verificationCode);
        ThrowUtils.throwIf(code == null, ErrorCode.OPERATION_ERROR, "验证码已失效");

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

        String invitationCode = userInfoRegisterRequest.getInvitationCode();
        LambdaQueryWrapper<UserInfo> invitedLambdaQueryWrapper = new LambdaQueryWrapper<>();
        invitedLambdaQueryWrapper.eq(UserInfo::getInvitationCode, invitationCode);
        UserInfo parentUserInfo = this.getOne(invitedLambdaQueryWrapper);
        ThrowUtils.throwIf(parentUserInfo == null, ErrorCode.OPERATION_ERROR, "邀请码错误");


        UserInfo myUserInfo = commonService.copyProperties(userInfoRegisterRequest, UserInfo.class);
        // 判断当前用户是否是根节点
        List<UserInfo> userInfoList = commonService.findByFieldEqTargetField(UserInfo::getUserRole, UserConstant.DEFAULT_ROLE, this);
        if (userInfoList.isEmpty()) myUserInfo.setParentUserId(0L);
        myUserInfo.setParentUserId(parentUserInfo.getId());
        myUserInfo.setInvitationCode(RandomUtil.randomNumbers(6));
        myUserInfo.setUserAccount(phoneNumber);
        myUserInfo.setUserRole(UserConstant.DEFAULT_ROLE);
        myUserInfo.setUserAvatar(UserConstant.USER_DEFAULT_AVATAR);
        this.save(myUserInfo);
        UserMainInfo userMainInfo = new UserMainInfo();
        userMainInfo.setUserId(myUserInfo.getId());

        // 生成邀请二维码
        try {
            String view = wechatGetQrcodeService.getWxQrCode(myUserInfo.getInvitationCode());
            userMainInfo.setInviteQrCode(view);
        } catch (IOException e) {
            e.printStackTrace();
        }
        userMainInfoService.save(userMainInfo);

        // 查询上级用户的项目抽佣记录
        List<ProjectCommission> projectCommissionList = commonService.findByFieldEqTargetField(ProjectCommission::getUserId, parentUserInfo.getId(), projectCommissionService);
        // 插入当前用户的项目抽佣记录
        List<ProjectCommission> projectCommissions = new ArrayList<>();
        for (ProjectCommission projectCommission : projectCommissionList) {
            ProjectCommissionAddRequest projectCommissionAddRequest = commonService.copyProperties(projectCommission, ProjectCommissionAddRequest.class);
            ProjectCommission proCommission = commonService.copyProperties(projectCommissionAddRequest, ProjectCommission.class);
            proCommission.setMyUnitPrice(projectCommission.getMyUnitPrice().multiply(BigDecimal.ONE.subtract(projectCommission.getCurrentCommissionRate())));
            proCommission.setCurrentCommissionRate(BigDecimal.ZERO);
            proCommission.setUserId(myUserInfo.getId());
            projectCommissions.add(proCommission);
        }
        projectCommissionService.saveBatch(projectCommissions);
        // 插入下级用户的项目明细抽佣记录
        List<ProjectCommission> proCommissionList = commonService.findByFieldEqTargetField(ProjectCommission::getUserId, parentUserInfo.getId(), projectCommissionService);
        List<SubUserProjectCommission> subUserProjectCommissionList = new ArrayList<>();
        for (ProjectCommission projectCommission : proCommissionList) {
            ProjectCommissionAddRequest projectCommissionAddRequest = commonService.copyProperties(projectCommission, ProjectCommissionAddRequest.class);
            SubUserProjectCommission subUserProjectCommission = commonService.copyProperties(projectCommissionAddRequest, SubUserProjectCommission.class);
            subUserProjectCommission.setSubUserId(myUserInfo.getId());
            subUserProjectCommissionList.add(subUserProjectCommission);
        }
        subUserProjectCommissionService.saveBatch(subUserProjectCommissionList);
    }



    /**
     * 小程序端用户密码登录
     */
    @Override
    public String userInfoMiniLoginByPwd(UserInfoMiniPasswordLoginRequest userInfoMiniPasswordLoginRequest) {
        String phoneNumber = userInfoMiniPasswordLoginRequest.getPhoneNumber();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式无效");
        String userPassword = userInfoMiniPasswordLoginRequest.getUserPassword();
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserInfo::getPhoneNumber, phoneNumber).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);
        return jwtUtils.generateToken(payload);
    }




    /**
     * 小程序用户验证码登录
     */
    @Override
    public String userInfoMiniLoginByVcd(UserInfoMiniVerifyCodeLoginRequest userInfoMiniVerifyCodeLoginRequest) {
        String phoneNumber = userInfoMiniVerifyCodeLoginRequest.getPhoneNumber();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式无效");

        String verificationCode = userInfoMiniVerifyCodeLoginRequest.getVerificationCode();
        String code = redisTemplate.opsForValue().get(SystemConstant.VERIFICATION_CODE + ":" + verificationCode);
        ThrowUtils.throwIf(code == null, ErrorCode.OPERATION_ERROR, "验证码已失效");

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

        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);
        return jwtUtils.generateToken(payload);
    }



    /**
     * 小程序用户重置密码
     */
    @Override
    public void userInfoMiniResetPwd(UserInfoResetRequest userInfoResetRequest) {
        String phoneNumber = userInfoResetRequest.getPhoneNumber();
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式无效");

        String verificationCode = userInfoResetRequest.getVerificationCode();
        String code = redisTemplate.opsForValue().get(SystemConstant.VERIFICATION_CODE + ":" + verificationCode);
        ThrowUtils.throwIf(code == null, ErrorCode.OPERATION_ERROR, "验证码已失效");

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

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

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


    /**
     * 小程序用户获取验证码
     */
    @Override
    public String getVerificationCode(String phoneNumber) {
        ThrowUtils.throwIf(RegexUtils.isPhoneInvalid(phoneNumber), ErrorCode.PARAMS_ERROR, "手机号格式错误");

        // 判断手机号是否已注册
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        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;
    }


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


}




