package com.njzscloud.common.security.module.password;

import cn.hutool.core.lang.Assert;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.core.ex.SysThrowable;
import com.njzscloud.common.security.contant.AuthWay;
import com.njzscloud.common.security.ex.UserLoginException;
import com.njzscloud.common.security.support.AbstractAuthenticationProvider;
import com.njzscloud.common.security.support.IAuthService;
import com.njzscloud.common.security.support.LoginForm;
import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.common.security.util.EncryptUtil;
import lombok.RequiredArgsConstructor;

import java.util.Set;

/**
 * 账号密码登录认证器
 */
@RequiredArgsConstructor
public class PasswordAuthenticationProvider extends AbstractAuthenticationProvider {
    private final IAuthService iAuthService;

    /**
     * 读取用户信息
     *
     * @param loginForm 登录表单
     * @return 用户信息
     */
    @Override
    protected UserDetail retrieveUser(LoginForm loginForm) throws UserLoginException {
        PasswordLoginForm passwordLoginForm = (PasswordLoginForm) loginForm;
        UserDetail userDetail;
        try {
            userDetail = iAuthService.selectUser(passwordLoginForm);
        } catch (SysThrowable e) {
            throw new UserLoginException(e.msg, e.message.toString());
        }
        if (userDetail == null) throw new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "账号或密码错误");
        Long userId = userDetail.getUserId();
        Set<String> roles = iAuthService.selectRole(userId);
        return userDetail
            .setAuthWay(AuthWay.PASSWORD)
            .setRoles(roles)
            ;
    }


    @Override
    protected void afterCheck(LoginForm loginForm, UserDetail userDetail) throws UserLoginException {
        String secret = userDetail.getSecret();
        Assert.notBlank(secret, () -> new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "当前账号不支持密码登录"));
        PasswordLoginForm passwordLoginForm = (PasswordLoginForm) loginForm;
        Assert.isTrue(EncryptUtil.matches(passwordLoginForm.getSecret(), secret), () -> new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "账号或密码错误"));
    }

    /**
     * 获取登录表单类型
     *
     * @return 登录表单类型
     * @see PasswordLoginForm
     */
    @Override
    protected Class<?> getLoginFormClazz() {
        return PasswordLoginForm.class;
    }
}
