package com.nebula.erp.inventory.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nebula.erp.inventory.utility.ApiResponseStructure;
import com.nebula.erp.inventory.utility.JwtUtils;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;

@Component
public class JwtInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtils jwtUtils;

    @Value("${allowed.ips}")
    private String allowedIps;

    private final ObjectMapper objectMapper = new ObjectMapper(); // Jackson ObjectMapper for JSON conversion

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

        // Get the client's IP address
        String clientIp = request.getRemoteAddr();

        // Split the allowed IPs into an array
        String[] allowedIpArray = allowedIps.split(",");

        // Extract the Authorization header directly from the request
        String authorizationHeader = request.getHeader("Authorization");

        // Check if the client's IP is in the allowed list
        for (String allowedIp : allowedIpArray) {
            if (clientIp.equals(allowedIp) && (authorizationHeader == null || authorizationHeader.isEmpty())) {
                return true;
            }
        }

        // Check if the Authorization header is missing
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "Authorization token is missing.");
            return false;
        }

        // Extract the token from the Authorization header
        String token = authorizationHeader.substring(7); // Remove the "Bearer " prefix

        try {
            // Check if the token is expired
            if (jwtUtils.isTokenExpired(token)) {
                sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "Token expired.");
                return false;
            }

        } catch (ExpiredJwtException e) {
            sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "Token expired at " + e.getClaims().getExpiration());
            return false;
        } catch (Exception e) {
            sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "Invalid token.");
            return false;
        }

        return true; // Allow the request to proceed
    }

    private void sendErrorResponse(HttpServletResponse response, int statusCode, String message) throws IOException {
        response.setStatus(statusCode);
        response.setContentType("application/json");

        // Creating an ApiResponseStructure object
        ApiResponseStructure<Void> apiResponse = new ApiResponseStructure<>(
                "Failure", statusCode, message, null);

        // Convert ApiResponseStructure object to JSON string
        String jsonResponse = objectMapper.writeValueAsString(apiResponse);

        // Write the JSON response to the response body
        response.getWriter().write(jsonResponse);
    }
}
