package cn.bunny.service.service.impl;

import cn.bunny.common.service.utils.EmptyUtil;
import cn.bunny.common.service.utils.JwtHelper;
import cn.bunny.dto.user.LoginDto;
import cn.bunny.entity.system.admin.AdminPower;
import cn.bunny.entity.system.admin.auth.AuthUserRole;
import cn.bunny.entity.system.email.EmailSend;
import cn.bunny.entity.system.email.EmailSendInit;
import cn.bunny.entity.system.email.EmailUsers;
import cn.bunny.entity.system.user.User;
import cn.bunny.module.mail.utils.MailSenderUtil;
import cn.bunny.result.constant.ExceptionConstant;
import cn.bunny.result.constant.MailMessageConstant;
import cn.bunny.result.constant.RedisUserConstant;
import cn.bunny.service.mapper.AdminPowerMapper;
import cn.bunny.service.mapper.AdminRoleMapper;
import cn.bunny.service.mapper.EmailUsersMapper;
import cn.bunny.service.mapper.UserMapper;
import cn.bunny.service.service.UserService;
import cn.bunny.vo.system.login.LoginVo;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户信息 服务实现类
 * </p>
 *
 * @author Bunny
 * @since 2024-05-18
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private AdminRoleMapper roleMapper;
    @Autowired
    private AdminPowerMapper powerMapper;
    @Autowired
    private EmailUsersMapper emailUsersMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 前台用户登录接口
     *
     * @param loginDto 登录参数
     * @return 登录后结果返回
     */
    @Override
    public LoginVo login(LoginDto loginDto) {
        // 判断用户和密码是否为空
        String username = loginDto.getUsername();
        EmptyUtil.isEmpty(username, ExceptionConstant.USERNAME_IS_EMPTY_Exception);
        // 密码不能为空
        EmptyUtil.isEmpty(loginDto.getPassword(), ExceptionConstant.PASSWORD_NOT_EMPTY_Exception);
        String password = DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes());
        // 查询数据库，用户对应的角色、权限
        User user = baseMapper.login(username, password);
        Long userId = user.getId();

        // 查询用户所有的角色信息
        AuthUserRole[] roleList = roleMapper.selectByRoleWithUserId(userId);
        List<String> roleCodeList = Arrays.stream(roleList).map(AuthUserRole::getRoleCode).toList();
        List<Long> roleIdList = Arrays.stream(roleList).map(AuthUserRole::getRoleId).toList();
        // 查询用户权限信息
        AdminPower[] adminPowerList = powerMapper.selectByPowerWithRoleIdList(roleIdList);
        List<String> powerCodeList = Arrays.stream(adminPowerList).map(AdminPower::getPowerCode).toList();

        // 设置返回类型
        LoginVo loginVo = new LoginVo();
        BeanUtils.copyProperties(user, loginVo);
        String token = JwtHelper.createToken(loginVo.getId(), loginVo.getEmail(), 7);
        loginVo.setToken(token);
        loginVo.setRoleList(roleCodeList);
        loginVo.setPowerList(powerCodeList);

        return loginVo;
    }

    /**
     * 发送邮箱验证码
     *
     * @param email 邮箱
     */
    @Override
    public void sendEmail(String email) {
        // 从数据库中获取发送邮箱参数
        EmailUsers emailUsers = emailUsersMapper.selectOne(Wrappers.<EmailUsers>lambdaQuery().eq(EmailUsers::getIsDefault, 1));
        EmailSendInit emailSendInit = new EmailSendInit();
        // 判断发送邮箱邮件是否为空
        EmptyUtil.isEmpty(emailUsers, MailMessageConstant.EMAIL_CONFIG_NOT_FOUND);
        BeanUtils.copyProperties(emailUsers, emailSendInit);
        emailSendInit.setUsername(emailUsers.getEmail());
        // 生成验证码
        MailSenderUtil mailSenderUtil = new MailSenderUtil(emailSendInit);
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2);
        // 生成验证码和可以
        String code = captcha.getCode();
        // 发送验证码
        EmailSend emailSend = new EmailSend();
        emailSend.setSubject("邮箱验证码");
        emailSend.setMessage(code);
        emailSend.setSendTo(email);
        emailSend.setIsRichText(false);
        mailSenderUtil.sendSimpleEmail(emailSend);

        // 将验证码保存到Redis中，并设置15分钟过期
        redisTemplate.opsForValue().set(RedisUserConstant.ADMIN_EMAIL_CODE_PREFIX + email, code, 15, TimeUnit.MINUTES);
    }
}
