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

import cn.hutool.core.lang.Assert;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.security.contant.AuthWay;
import com.njzscloud.common.security.ex.UserLoginException;
import com.njzscloud.common.security.support.*;
import com.njzscloud.common.security.util.EncryptUtil;
import lombok.RequiredArgsConstructor;

import java.util.Set;

/**
 * 账号密码登录认证器
 */
@RequiredArgsConstructor
public class PasswordAuthenticationProvider extends AbstractAuthenticationProvider {
    private final IUserService iUserService;
    private final IRoleService iRoleService;
    private final IResourceService iResourceService;

    /**
     * 读取用户信息
     *
     * @param loginForm 登录表单
     * @return 用户信息
     */
    @Override
    protected UserDetail retrieveUser(LoginForm loginForm) throws UserLoginException {
        PasswordLoginForm passwordLoginForm = (PasswordLoginForm) loginForm;
        String account = passwordLoginForm.getAccount();
        UserDetail userDetail = iUserService.selectUserByAccount(account);
        if (userDetail == null) throw new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "账号或密码错误");
        Long userId = userDetail.getUserId();
        Set<String> roles = iRoleService.selectRoleByUserId(userId);
        Resource resource = iResourceService.selectResourceByUserId(userId);
        return userDetail
                .setAuthWay(AuthWay.PASSWORD)
                .setRoles(roles)
                .setResource(resource)
                ;
    }


    @Override
    protected void afterCheck(LoginForm loginForm, UserDetail userDetail) throws UserLoginException {
        String secret = userDetail.getSecret();
        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;
    }
}
