package com.spring.infra.security.error;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.security.SignatureException;
import lombok.RequiredArgsConstructor;

@RestControllerAdvice
@RequiredArgsConstructor
public class SecurityExceptionHandler {

    private final AccessDeniedHandler accessDeniedHandler;

    @ExceptionHandler(SecurityAuthException.class)
    public SecurityErrorResponse handleAuthenticationException(SecurityAuthException e) {
        return SecurityErrorResponse.valueOf(e.getExceptionRule());
    }

    @ExceptionHandler(AuthenticationException.class)
    public SecurityErrorResponse handleAuthenticationException() {
        return SecurityErrorResponse.valueOf(SecurityExceptionRule.USER_UNAUTHORIZED);
    }

    @ExceptionHandler(SignatureException.class)
    public SecurityErrorResponse handleSignatureException() {
        return SecurityErrorResponse.valueOf(SecurityExceptionRule.SIGNATURE_ERROR);
    }

    @ExceptionHandler(MalformedJwtException.class)
    public SecurityErrorResponse handleMalformedJwtException() {
        return SecurityErrorResponse.valueOf(SecurityExceptionRule.MALFORMED_JWT_ERROR);
    }

    @ExceptionHandler(ExpiredJwtException.class)
    public SecurityErrorResponse handleExpiredJwtException() {
        return SecurityErrorResponse.valueOf(SecurityExceptionRule.EXPIRED_JWT_ERROR);
    }

    @ExceptionHandler(AccessDeniedException.class)
    public void handleAccessDeniedException(
        AccessDeniedException ex, HttpServletRequest request, HttpServletResponse response
    ) throws IOException, ServletException {
        accessDeniedHandler.handle(request, response, ex);
    }

}
