package com.njcn.user.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.constant.PatternRegex;
import com.njcn.common.pojo.constant.SecurityConstants;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.PubUtils;
import com.njcn.common.utils.sm.Sm2;
import com.njcn.common.utils.sm.Sm4Utils;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.user.enums.UserResponseEnum;
import com.njcn.user.mapper.UserMapper;
import com.njcn.user.mapper.UserSetMapper;
import com.njcn.user.pojo.constant.UserDefaultPassword;
import com.njcn.user.pojo.param.UserParam;
import com.njcn.user.pojo.po.User;
import com.njcn.user.pojo.po.UserSet;
import com.njcn.user.service.IUserSetService;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2021-12-13
 */
@Service
@RequiredArgsConstructor
public class UserSetServiceImpl extends ServiceImpl<UserSetMapper, UserSet> implements IUserSetService {

    private final RedisUtil redisUtil;

    private final UserMapper userMapper;

    @Override
    public UserSet addUserSet(UserParam.UserAddParam addUserParam) {
        String userId;
        UserSet userSet = new UserSet();
        if (StringUtils.isBlank(addUserParam.getId()) || Objects.isNull(addUserParam.getId())){
            userId = IdUtil.simpleUUID();
        } else {
            userId = addUserParam.getId();
        }
        userSet.setUserId(userId);
        String secretKey = PubUtils.randomCode(16);
        userSet.setSecretKey(secretKey);
        Sm4Utils sm4 = new Sm4Utils(secretKey);
        //SM4加密初始默认密码
        String strSm4 = sm4.encryptData_ECB(UserDefaultPassword.DEFAULT_PASSWORD);
        userSet.setStandBy(strSm4);
        this.save(userSet);
        return userSet;
    }

    @Override
    public String updatePassword(String id,String newPassword,Boolean result) {
        String password = getSecretPassword(newPassword);
        return updatePsd(id,password,result);
    }

    @Override
    public String updateFirstPassword(String id, String newPassword, String name, String ip) {
        String password = getSecretPasswordNotLogin(newPassword, name, ip);
        return updatePsd(id,password,true);
    }

    @Override
    public String forgetPassword(String id, String newPassword, String name, String ip) {
        String password = getSecretPasswordNotLogin(newPassword, name, ip);
        return updatePsd(id,password,false);
    }

    @Override
    public String getDecryptPassword(String password) {
        return getSecretPassword(password);
    }

    @Override
    public UserSet getUserSetByUserId(String userId) {
        return this.lambdaQuery().eq(UserSet::getUserId,userId).one();
    }

    @Override
    public UserSet addAppUserSet() {
        UserSet userSet = new UserSet();
        String userId = IdUtil.simpleUUID();
        userSet.setUserId(userId);
        String secretKey = PubUtils.randomCode(16);
        userSet.setSecretKey(secretKey);
        Sm4Utils sm4 = new Sm4Utils(secretKey);
        //随机生成8位密码
        String password = PubUtils.getCode(8);
        redisUtil.saveByKey(userId,password);
        //SM4加密初始默认密码
        String strSm4 = sm4.encryptData_ECB(password);
        userSet.setStandBy(strSm4);
        this.save(userSet);
        return userSet;
    }

    /**
     * 修改密码公共方法
     * @param id 用户id
     * @param password 密码
     */
    private String updatePsd(String id, String password,Boolean result) {
        Sm4Utils sm4;
        String psd,strSm4;
        if (result){
            String standard = PatternRegex.PASSWORD_REGEX;
            Pattern pattern = Pattern.compile(standard);
            Matcher m=pattern.matcher(password);
            if (!m.find()){
                throw new BusinessException(UserResponseEnum.SPECIAL_PASSWORD);
            }
        //密码是否需要复杂校验
        } else {
            String standard = PatternRegex.APP_PASSWORD_REGEX;
            Pattern pattern = Pattern.compile(standard);
            Matcher m=pattern.matcher(password);
            if (!m.find()){
                throw new BusinessException(UserResponseEnum.APP_PASSWORD);
            }
        }
        UserSet userSet = this.lambdaQuery().eq(UserSet::getUserId, id).one();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("sys_user.id",id);
        User user = userMapper.selectOne(userQueryWrapper);
        String secretPassword = user.getPassword();
        if (Objects.isNull(userSet)){
            UserSet newUserSet = new UserSet();
            String secretKey = PubUtils.randomCode(16);
            newUserSet.setSecretKey(secretKey);
            sm4 = new Sm4Utils(secretKey);
            strSm4 = sm4.encryptData_ECB(password);
            newUserSet.setStandBy(strSm4);
            newUserSet.setUserId(id);
            this.save(newUserSet);
            psd = sm4.encryptData_ECB(strSm4 + secretKey);
        } else {
            sm4 = new Sm4Utils(userSet.getSecretKey());
            strSm4 = sm4.encryptData_ECB(password);
            psd = sm4.encryptData_ECB(strSm4 + userSet.getSecretKey());
        }
        if (Objects.equals(secretPassword,psd)){
            throw new BusinessException(UserResponseEnum.REPEAT_PASSWORD);
        }
        return psd;
    }


    /**
     * 未登录
     * 前端密文密码解码
     */
    private String getSecretPasswordNotLogin(String password, String name, String ip) {
        String privateKey = redisUtil.getStringByKey(name + ip);
        //秘钥用完即删
        redisUtil.delete(name + ip);
        //对SM2解密面进行验证
        password = Sm2.getPasswordSM2Verify(privateKey, password);
        if (StrUtil.isBlankIfStr(password)) {
            throw new BusinessException(UserResponseEnum.PASSWORD_TRANSPORT_ERROR);
        }
        return password;
    }

    /**
     * 登陆后
     * 前端密文密码解码
     */
    private String getSecretPassword(String password) {
        String loginName = RequestUtil.getUsername();
        String ip = Objects.requireNonNull(RequestUtil.getRequest()).getHeader(SecurityConstants.REQUEST_HEADER_KEY_CLIENT_REAL_IP);
        String privateKey = redisUtil.getStringByKey(loginName + ip);
        //秘钥用完即删
        redisUtil.delete(loginName + ip);
        //对SM2解密面进行验证
        password = Sm2.getPasswordSM2Verify(privateKey, password);
        if (StrUtil.isBlankIfStr(password)) {
            throw new BusinessException(UserResponseEnum.PASSWORD_TRANSPORT_ERROR);
        }
        return password;
    }
}
