package com.ads.business.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ads.business.dao.UserDao;
import com.ads.business.entity.User;
import com.ads.business.service.LoginService;
import com.ads.business.service.data.GetLoginInData;
import com.ads.business.service.data.GetLoginOutData;
import com.ads.common.data.JsonResult;
import com.ads.common.enums.CommonStatusEnum;
import com.ads.common.exception.BusinessException;
import com.ads.common.redis.RedisKeyConstant;
import com.ads.common.redis.RedisManager;
import com.ads.common.util.OnlineUserUtils;
import com.ads.common.util.UtilConst;
import com.ads.common.util.UtilMessage;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @Return
 * @Author hou
 * @Date 2021/10/21 16:22
 * @Destription
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    @Resource
    private UserDao userDao;

    @Resource
    private RedisManager redisManager;

    @Override
    public JsonResult<GetLoginOutData> login(GetLoginInData inData) {
        log.info("用户登录 data:{}", JSON.toJSONString(inData));
        User user = userDao.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getAccount, inData.getAccount()));
        if (ObjectUtil.isNull(user)) {
            throw new BusinessException(UtilMessage.LOGIN_NO_ACCOUNT);
        }
        if (CommonStatusEnum.NO.getCode().equals(user.getStatus())) {
            throw new BusinessException(UtilMessage.LOGIN_ACCOUNT_INVALID);
        }
        // 密文
        String passwordDb = user.getPassword();
        // 密码匹配
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(inData.getPassword(), passwordDb);
        if (!matches) {
            throw new BusinessException(UtilMessage.LOGIN_PASSWORD_ERROR);
        }
        GetLoginOutData loginOutData = new GetLoginOutData();
        loginOutData.setUserId(user.getUserId().toString());
        loginOutData.setName(user.getName());
        loginOutData.setAccount(user.getAccount());
        String token = IdUtil.simpleUUID();
        loginOutData.setToken(token);
        redisManager.set(RedisKeyConstant.PREFIX + token, JSON.toJSONString(loginOutData), UtilConst.TOKEN_EXPIRE);

        return JsonResult.success(loginOutData, UtilMessage.LOGIN_SUCCESS);
    }

    @Override
    public JsonResult logout(String token) {
        log.info("用户退出登录 token:{}", token);
        redisManager.delete(token);
        return JsonResult.success(null, UtilMessage.LOGIN_OUT_SUCCESS);
    }

    @Override
    public JsonResult resetPassword(GetLoginInData inData) {
        GetLoginOutData loginUser = OnlineUserUtils.get();
        log.info("重置用户密码 user:{}, data:{}",JSON.toJSONString(loginUser), JSON.toJSONString(inData));
        if (inData.getOldPassword().equals(inData.getNewPassword())) {
            throw new BusinessException(UtilMessage.UPDATE_PWD_SAME_PASSWORD);
        }
        User user = userDao.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getAccount, inData.getAccount()));
        if (ObjectUtil.isNull(user)) {
            throw new BusinessException(UtilMessage.LOGIN_NO_ACCOUNT);
        }
        if (CommonStatusEnum.NO.getCode().equals(user.getStatus())) {
            throw new BusinessException(UtilMessage.LOGIN_ACCOUNT_INVALID);
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encodePassword = passwordEncoder.encode(inData.getPassword());
        user.setPassword(encodePassword);
        user.setUpdateUser(Long.valueOf(loginUser.getUserId()));
        user.setUpdateTime(new Date());
        userDao.updateById(user);
        return JsonResult.success(null, UtilMessage.SAVE_MESSAGE_SUCCESS);
    }

    @Override
    public JsonResult updatePassword(GetLoginInData inData) {
        GetLoginOutData loginUser = OnlineUserUtils.get();
        log.info("用户修改密码 user:{}, data:{}",JSON.toJSONString(loginUser), JSON.toJSONString(inData));
        if (inData.getOldPassword().equals(inData.getNewPassword())) {
            throw new BusinessException("新密码和原密码不能相同");
        }
        User user = userDao.selectById(loginUser.getUserId());
        if (ObjectUtil.isNull(user)) {
            throw new BusinessException(UtilMessage.LOGIN_NO_ACCOUNT);
        }
        if (CommonStatusEnum.NO.getCode().equals(user.getStatus())) {
            throw new BusinessException(UtilMessage.LOGIN_ACCOUNT_INVALID);
        }
        // 密文
        String passwordDb = user.getPassword();
        // 密码匹配
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(inData.getOldPassword(), passwordDb);
        if (!matches) {
            throw new BusinessException("旧密码错误");
        }
        String encodePassword = passwordEncoder.encode(inData.getPassword());
        user.setPassword(encodePassword);
        user.setUpdateUser(Long.valueOf(loginUser.getUserId()));
        user.setUpdateTime(new Date());
        userDao.updateById(user);
        return JsonResult.success(null, UtilMessage.SAVE_MESSAGE_SUCCESS);
    }
}
