package com.sunda.spmsweb.shiro;


import com.sunda.spmsuser.entity.SpmsPermission;
import com.sunda.spmsuser.entity.SpmsUser;
import com.sunda.spmsuser.service.ISpmsPermissionService;
import com.sunda.spmsuser.service.ISpmsRoleService;
import com.sunda.spmsuser.service.ISpmsUserService;
import com.sunda.spmsweb.aspect.HttpContextUtils;
import com.sunda.spmsweb.util.IPUtils;
import com.sunda.spmsweb.util.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @program: spms
 * @author: Wayne Wu
 * @description: 自定义 Realm
 * @create: 2020-10-26 15:30
 */
@Component
@Slf4j
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    ISpmsUserService iSpmsUserService;

    @Autowired
    ISpmsRoleService iSpmsRoleService;

    @Autowired
    ISpmsPermissionService iSpmsPermissionService;

//    @Autowired
//    public CustomRealm(ISpmsUserService ISpmsUserService) {
//        this.iSpmsUserService = iSpmsUserService;
//    }

    /**
     * 必须重写此方法，不然会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("——————身份认证方法——————");
        String token = (String) authenticationToken.getCredentials();
        // 解密获得username，用于和数据库进行对比
        String userId = JWTUtil.getUserId(token);
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        String ip = IPUtils.getIpAddr(request);
        log.info("ip === " + ip);
        log.info("userId === " + userId);
        if (userId == null || !JWTUtil.verify(token, userId)) {
            log.info("token 认证失败！");
            throw new AuthenticationException("token 认证失败！");
        }
        SpmsUser user = iSpmsUserService.getByUserId(userId);
        String password = user.getLoginPassword();
        if (password == null) {
            throw new AuthenticationException("该用户不存在！");
        }
        if (user.getSpmsStatus() == "0" || "0".equals(user.getSpmsStatus())) {
            throw new AuthenticationException("该用户已被封号！");
        }
        return new SimpleAuthenticationInfo(token, token, "MyRealm");
    }

    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("——————权限认证——————");
        String userId = JWTUtil.getUserId(principals.toString());
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        // 获取用户角色集，此处最好使用缓存提升速度
        List<Map<String, Object>> roleList = iSpmsRoleService.getRoleById(userId);
        Set<String> roleSet = new HashSet<String>();
        if (roleList.size() > 0){
            for (Map<String, Object> map : roleList) {
                roleSet.add(map.get("roleId").toString());
            }
        }
        log.info("用户角色：roleSet ======== " + roleSet.toString());
        simpleAuthorizationInfo.setRoles(roleSet);

        // 获取用户权限集
        List<SpmsPermission> permissionList = iSpmsPermissionService.getUserPerms(userId);
        Set<String> permissionSet = new HashSet<String>();
        if (permissionList.size() > 0){
            for (SpmsPermission p : permissionList) {
                permissionSet.add(p.getPerms());
            }
        }
        log.info("用户权限：permissionSet ======== " + permissionSet.toString() + "\n");
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;

    }
}
