package com.njcn.product.auth.exception;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.nimbusds.jose.JWSObject;
import com.njcn.common.pojo.constant.LogInfo;
import com.njcn.common.pojo.constant.SecurityConstants;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;

import com.njcn.product.auth.pojo.enums.UserResponseEnum;
import com.njcn.product.auth.service.IUserService;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @author hongawen
 * @version 1.0.0
 * @date 2021年05月17日 12:46
 */
@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AuthExceptionHandler {

    private final IUserService userService;

//    private final ILogService logService;

    /**
     * 用户名和密码非法
     */
    @ExceptionHandler(InvalidGrantException.class)
    public HttpResult<String> handleInvalidGrantException(HttpServletRequest httpServletRequest, InvalidGrantException invalidGrantException) {
        String loginName = invalidGrantException.getMessage();
        log.error("捕获用户名密码错误");
        String result = userService.updateUserLoginErrorTimes(loginName);
        if (result.equals(UserResponseEnum.LOGIN_USER_LOCKED.getMessage())) {
//            logService.recodeAuthExceptionLog(invalidGrantException, httpServletRequest, UserResponseEnum.LOGIN_USER_LOCKED.getMessage(), loginName);
            return HttpResultUtil.assembleResult(UserResponseEnum.LOGIN_USER_LOCKED.getCode(), null, UserResponseEnum.LOGIN_USER_LOCKED.getMessage());
        } else {
//            logService.recodeAuthExceptionLog(invalidGrantException, httpServletRequest, UserResponseEnum.LOGIN_WRONG_PWD.getMessage(), loginName);
            return HttpResultUtil.assembleResult(UserResponseEnum.LOGIN_WRONG_PWD.getCode(), null, UserResponseEnum.LOGIN_WRONG_PWD.getMessage());
        }
    }


    /**
     * 不支持的认证方式
     * <p>
     * 不支持的认证方式 目前支持：用户名密码：password、刷新token：refresh-token
     */
    @ExceptionHandler(UnsupportedGrantTypeException.class)
    public HttpResult<String> unsupportedGrantTypeExceptionException(HttpServletRequest httpServletRequest, UnsupportedGrantTypeException unsupportedGrantTypeException) {
        String loginName = RequestUtil.getLoginName(httpServletRequest);
//        logService.recodeAuthExceptionLog(unsupportedGrantTypeException, httpServletRequest, UserResponseEnum.UNSUPPORTED_GRANT_TYPE.getMessage(), loginName);
        return HttpResultUtil.assembleResult(UserResponseEnum.UNSUPPORTED_GRANT_TYPE.getCode(), null, UserResponseEnum.UNSUPPORTED_GRANT_TYPE.getMessage());
    }

    /**
     * oAuth2中token校验异常
     */
    @SneakyThrows
    @ExceptionHandler(InvalidTokenException.class)
    public HttpResult<String> invalidTokenExceptionException(HttpServletRequest httpServletRequest, InvalidTokenException invalidTokenException) {
        final String EXPIRED_KEY = "Invalid refresh token (expired):";
        if (invalidTokenException.getMessage().startsWith(EXPIRED_KEY)) {
            String message = invalidTokenException.getMessage();
            message = message.substring(EXPIRED_KEY.length());
            JWSObject jwsObject = JWSObject.parse(message);
            String payload = jwsObject.getPayload().toString();
            JSONObject jsonObject = JSONUtil.parseObj(payload);
//            logService.recodeAuthExceptionLog(invalidTokenException, httpServletRequest, UserResponseEnum.REFRESH_TOKEN_EXPIRE_JWT.getMessage(), jsonObject.getStr(SecurityConstants.USER_NAME_KEY));
            return HttpResultUtil.assembleResult(UserResponseEnum.REFRESH_TOKEN_EXPIRE_JWT.getCode(), null, UserResponseEnum.REFRESH_TOKEN_EXPIRE_JWT.getMessage());
        }
//        logService.recodeAuthExceptionLog(invalidTokenException, httpServletRequest, UserResponseEnum.PARSE_TOKEN_FORBIDDEN_JWT.getMessage(), LogInfo.UNKNOWN_USER);
        return HttpResultUtil.assembleResult(UserResponseEnum.PARSE_TOKEN_FORBIDDEN_JWT.getCode(), null, UserResponseEnum.PARSE_TOKEN_FORBIDDEN_JWT.getMessage());
    }


}
