package com.project.shiro.util;

import com.alibaba.fastjson.JSONObject;
import com.project.model.core.Admin;
import com.project.model.core.Menu;
import com.project.model.core.Role;
import com.project.service.core.AdminService;
import com.project.service.core.MenuService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.io.PrintWriter;
import java.util.*;

/**
 * 认证
 */
public class AuthenticationRealm extends AuthorizingRealm {

    @Resource(name = "adminServiceImpl")
    private AdminService adminService;

    @Resource(name = "menuServiceImpl")
    private MenuService menuService;

    /**
     * 获取认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken token) {
        AuthenticationToken authToken = (AuthenticationToken) token;
        // 获取登录名、密码
        String username = authToken.getUsername();
        String password = new String(authToken.getPassword());

        if (username != null && password != null) {
            Admin admin = adminService.getByLoginName(username);

            if (admin == null) {
                throw new UnknownAccountException();
            }

            if (!admin.getStatus().equals(Admin.STATUS_ENUM.ENABLE.getValue())) {
                throw new DisabledAccountException();
            }

            //用户锁定
            if (admin.getIsLocked()) {

                //账号锁定分钟数
                Date lockedDate = admin.getLockedDate();
                Date unlockedDate = DateUtils.addMinutes(lockedDate, 10);

                //判断锁定时间是否已过
                if (new Date().after(unlockedDate)) {
                    admin.setLoginFailCnt(0);
                    admin.setIsLocked(false);
                    admin.setLockedDate(null);
                    adminService.update(admin);
                } else {
                    throw new LockedAccountException();
                }
            }

            //密码不正确
            if (!DigestUtils.md5Hex(password).equals(admin.getLoginPwd())) {
                int loginFailCount = admin.getLoginFailCnt() + 1;
                if (loginFailCount >= 5) {
                    admin.setIsLocked(true);
                    admin.setLockedDate(new Date());
                }
                admin.setLoginFailCnt(loginFailCount);
                adminService.update(admin);
                throw new IncorrectCredentialsException();
            }
            admin.setLoginFailCnt(0);
            adminService.update(admin);
            return new SimpleAuthenticationInfo(new Principal(admin.getId(), username), password, getName());
        }
        throw new UnknownAccountException();
    }

    /**
     * 获取授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        Principal principal = (Principal) principals.fromRealm(getName()).iterator().next();

        if (principal != null) {
            SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo();

            //获取admin对象
            Admin adminTemp = new Admin();
            adminTemp.setId(principal.getId());
            List<Admin> admins = adminService.getAdminCascadeRole(adminTemp);
            Admin admin = admins.get(0);

            //获取用户的角色信息
            Set<String> roleSet = new HashSet<String>();
            for (Role role : admin.getRoles()) {
                if (role.getStatus().equals(Role.STATUS_ENUM.ENABLE.getValue())) {
                    roleSet.add(role.getRoleCode());
                }
            }

            //根据角色ids获取权限信息
            List<Menu> menuList = menuService.findOrdinaryMenu(principal.getId());
            Set<String> menuSet = new HashSet<String>();
            for (Menu menu : menuList) {
                if (StringUtils.isNotBlank(menu.getCode())) {
                    menuSet.add(menu.getCode());
                }
            }

            //将角色和资源放入授权对象中
            authInfo.addRoles(roleSet);
            authInfo.addStringPermissions(menuSet);
            return authInfo;
        }

        return null;
    }

    /**
     * 超级管理员自动获取所有权限
     */
//    @Override
//    public boolean isPermitted(PrincipalCollection principals, String permission) {
////        User user = ((User) principals.getPrimaryPrincipal());
////        if (Role.ADMIN_FLAG_SUPER_ADMIN == user.getRole().getAdminFlag()) {
////            return true;
////        }
//
//        return isPermitted(principals, getPermissionResolver().resolvePermission(permission));
//    }

    @Override
    public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        AuthorizationInfo info = getAuthorizationInfo(principals);
        Collection<Permission> perms = getPermissions(info);
        if (CollectionUtils.isEmpty(perms)) {
            return false;
        }

        for (Permission perm : perms) {
            if (perm.implies(permission)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 踢掉上一个登录的同名用户
     *
     * @param id 主键
     */

//    private void stopPreviousSession(Integer id) {
//        Collection<Session> sessions = sessionDAO.getActiveSessions();
//        Session currSession = SecurityUtils.getSubject().getSession();
//        Serializable sId = currSession.getId();
//        for (Session session : sessions) {
//            SimplePrincipalCollection collection = (SimplePrincipalCollection) session
//                    .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
//            if (collection == null) {
//                continue;
//            }
//
//            User u = (User) collection.getPrimaryPrincipal();
//            if (id.equals(u.getId())) {
//                if (sId.equals(session.getId())) {
//                    continue;
//                }
//
//                session.stop();
//                break;
//            }
//        }
//    }


}