package com.mortals.xhx.base.framework.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.annotation.UnAuth;
import com.mortals.framework.common.Rest;
import com.mortals.framework.service.IAuthTokenService;
import com.mortals.framework.service.IUser;
import com.mortals.framework.util.AESUtil;
import com.mortals.framework.utils.ServletUtils;
import com.mortals.framework.web.interceptor.BaseInterceptor;
import com.mortals.xhx.base.framework.config.InterceptorConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

import static com.mortals.xhx.common.key.ErrorCode.*;

/**
 * 用户权限验证，基于token
 *
 * @author: zxfei
 * @date: 2022/4/24 11:04
 */
@Component
public class AuthUserInterceptor extends BaseInterceptor {
    @Autowired
    private InterceptorConfig config;
    @Autowired
    private IAuthTokenService authTokenService;

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE - 9;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        JSONObject ret = new JSONObject();
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            UnAuth annotation = method.getAnnotation(UnAuth.class);
            if (annotation != null) {
                //取消校验
                return true;
            }
        }else if(handler instanceof ResourceHttpRequestHandler){
            return true;
        }
        try {
            String uri = request.getServletPath();
            //校验配置的请求路径是否需要检查权限
            if (config.needCheckAuth(uri)) {
                //需要校验权限
                boolean auth = this.checkAuth(request, uri, config.getSecurityKey());
                if (!auth) {
                    //校验token不正常
                    String token = authTokenService.getToken(request);
                    if(ObjectUtils.isEmpty(token)){
                        ServletUtils.renderString(response, JSONObject.toJSONString(Rest.fail(ERROR_TOKEN_UNAUTHORIZED, ERROR_TOKEN_UNAUTHORIZED_CONTENT)));
                        return false;
                    }
                    //不存在时候 如果是管理员也不做拦截
                    IUser loginUser = authTokenService.getLoginUser(request);
                    if (ObjectUtils.isEmpty(loginUser)) {
                        ServletUtils.renderString(response, JSONObject.toJSONString(Rest.fail(ERROR_TOKEN_EXPIRED, ERROR_TOKEN_EXPIRED_CONTENT)));
                        return false;
                    } else if (loginUser.isAdmin() || loginUser.getUserType() == 1) {
                        return super.preHandle(request, response, handler);
                    } else {
                        ServletUtils.renderString(response, JSONObject.toJSONString(Rest.fail(ERROR_USER_OPERATION, ERROR_USER_OPERATION_CONTENT)));
                        return false;
                    }
                }
            }
        } catch (Exception e) {
            logger.error("权限校验拦截请求处理异常-->" + e.getMessage());
            writeJsonResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "用户权限校验异常");
            return false;
        }

        return super.preHandle(request, response, handler);
    }

    private boolean checkAuth(HttpServletRequest request, String requestUrl, String securityKey) throws Exception {
        int code = requestUrl.hashCode() & (Integer.MAX_VALUE - 1);
        IUser loginUser = authTokenService.getLoginUser(request);
        if (ObjectUtils.isEmpty(loginUser)) return false;
        String menuUrl = loginUser.getMenuUrl();
        if (ObjectUtils.isEmpty(menuUrl)) return false;
        menuUrl = AESUtil.decrypt(menuUrl, securityKey);
        String codes = "," + menuUrl + ",";
        String codeKey = "," + code + ",";
        if (codes.indexOf(codeKey) != -1) {
            return true;
        }
        return false;
    }

}
