package com.app.admin.framework.system.permission.authorization.controller;

import cn.hutool.json.JSONUtil;
import com.app.admin.framework.system.administrator.model.SysAdministrator;
import com.app.admin.framework.system.module.convert.SysModuleTreeConvert;
import com.app.admin.framework.system.module.model.SysModule;
import com.app.admin.framework.system.module.service.SysModuleService;
import com.app.admin.framework.system.module.view.SysModuleTreeNode;
import com.app.admin.framework.system.permission.authorization.service.SysAuthorityService;
import com.app.framework.core.log.annotation.LogOps;
import com.app.framework.core.log.constant.LogOpsType;
import com.app.framework.core.support.auth.LoginUser;
import com.app.framework.core.support.controller.CrudControllerSupport;
import com.app.framework.core.support.view.form.AjaxResult;
import com.app.framework.core.utils.request.SessionUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 身份认证
 */
@Controller
@RequestMapping("/auth")
public class AuthController extends CrudControllerSupport {

    /**
     * 操作员菜单session名称
     */
    private final String OPERATOR_CONTEXT_MODULES = "operator_context_modules";

    @Resource
    SysModuleService sysModuleService;

    @Resource
    SysAuthorityService sysAuthorityService;

    /**
     * 用户登录
     */
    @RequestMapping(value = "/login")
    @LogOps(type = LogOpsType.LOGIN)
    @ResponseBody
    public AjaxResult login(HttpServletRequest request, String username, String password) {
        AjaxResult loginResult = sysAuthorityService.login(username, password);
        if (loginResult.success()) {
            SysAdministrator loginUser = (SysAdministrator) loginResult.getData();
            //登录用户菜单
            List<SysModule> list = sysAuthorityService.getLoginUserModule(loginUser, 1);
            List<SysModuleTreeNode> loginUserModules = new SysModuleTreeConvert().transStaticTree(list);
            //将登录的用户资源存入session
            SessionUtil.setCurrentUser(request, loginUser);
            SessionUtil.set(request, OPERATOR_CONTEXT_MODULES, loginUserModules);
            return AjaxResult.wrap(true);
        }
        return loginResult;
    }

    /**
     * 用户登录
     * 支持shiro
     */
    @RequestMapping(value = "/loginCheck")
    @LogOps(type = LogOpsType.LOGIN)
    @ResponseBody
    public AjaxResult loginByShiro(HttpServletRequest request, String username, String password, String online) {
//		boolean rememberMe = "on".equals(online) ? true : false;
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(false);
        Subject subject = SecurityUtils.getSubject();
        String msg = "登录失败";
        try {
            subject.login(token);
            if (subject.isAuthenticated()) {
                //登录用户信息
                SysAdministrator loginUser = (SysAdministrator) subject.getPrincipal();
                //登录用户菜单
                List<SysModule> list = sysAuthorityService.getLoginUserModule(loginUser, 1);
                List<SysModuleTreeNode> loginUserModules = new SysModuleTreeConvert().transStaticTree(list);
                //将登录的用户资源存入session
                SessionUtil.setCurrentUser(request, loginUser);
                SessionUtil.set(request, OPERATOR_CONTEXT_MODULES, loginUserModules);
                return AjaxResult.wrapSuccess("登录成功");
            } else {
                return AjaxResult.wrapError(msg);
            }
        } catch (IncorrectCredentialsException e) {
            msg = "登录密码错误";
        } catch (ExcessiveAttemptsException e) {
            msg = "登录失败次数过多";
        } catch (LockedAccountException e) {
            msg = "帐号已被锁定";
        } catch (DisabledAccountException e) {
            msg = "帐号已被禁用";
        } catch (ExpiredCredentialsException e) {
            msg = "帐号已过期";
        } catch (UnknownAccountException e) {
            msg = e.getMessage();
            if (StringUtils.isBlank(msg)) msg = "帐号不存在";
        } catch (UnauthorizedException e) {
            msg = "您没有得到相应的授权";
        }
        return AjaxResult.wrapError(msg);
    }

    /**
     * 用户退出登录
     */
    @RequestMapping(value = "/logout")
    @LogOps(type = LogOpsType.LOGOUT)
    public void logout(HttpServletRequest request, HttpServletResponse response) throws Exception {
        LoginUser loginUser = SessionUtil.getCurrentUser(request);

        //Session注销
        SessionUtil.removeCurrentUser(request);
        SessionUtil.remove(request, OPERATOR_CONTEXT_MODULES);
        //Shiro注销
        SecurityUtils.getSubject().logout();

        request.setAttribute("apiLoginUser", loginUser);
        request.getRequestDispatcher("/login").forward(request, response);
    }

    /**
     * 菜单点击跳转
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "jump")
    public void jump(HttpServletRequest request, HttpServletResponse response,
                     Long moduleId, Integer tabIndex, String url) throws Exception {
        Map<String, Object> params = new HashMap<>();
        SysModule module = sysModuleService.getById(moduleId);
        if (StringUtils.isNotBlank(module.getParams())) {
            params = JSONUtil.parseObj(module.getParams());
        }
        //跳转
        request.setAttribute("jumpUrl", url);
        request.setAttribute("tabIndex", tabIndex);
        request.setAttribute("module", module);
        request.setAttribute("paramsMap", params);
        request.getRequestDispatcher(url).forward(request, response);
    }

    /**
     * 菜单点击跳转
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "jump_basic")
    public void basic_jump(HttpServletRequest request, HttpServletResponse response,
                           Long moduleId, Integer tabIndex, String url) throws Exception {
        SysModule module = sysModuleService.getById(moduleId);
        //跳转
        request.setAttribute("module", module);
        request.setAttribute("tabIndex", tabIndex);
        request.getRequestDispatcher(url).forward(request, response);//会同时携带参数
    }
}
