package com.qqchen.deploy.backend.framework.security.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.utils.MessageUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

    private final ObjectMapper objectMapper;

    public CustomAuthenticationEntryPoint(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                        AuthenticationException authException) throws IOException {
        if (!isErrorDispatch(request)) {
            log.error("Custom authentication entry point error", authException);
        }

        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());

        Response<?> errorResponse;
        
        if (authException instanceof BadCredentialsException) {
            errorResponse = Response.error(ResponseCode.LOGIN_ERROR);
        } else if (authException instanceof InternalAuthenticationServiceException) {
            errorResponse = Response.error(ResponseCode.ERROR);
        } else if (authException instanceof InsufficientAuthenticationException) {
            errorResponse = Response.error(ResponseCode.AUTH_REQUIRED);
        } else {
            errorResponse = Response.error(ResponseCode.UNAUTHORIZED);
        }

        objectMapper.writeValue(response.getOutputStream(), errorResponse);
    }

    private boolean isErrorDispatch(HttpServletRequest request) {
        String errorPath = "/error";
        String requestUri = request.getRequestURI();
        return requestUri != null && requestUri.equals(errorPath);
    }
} 