package com.mosquito.project.web;

import com.mosquito.project.persistence.repository.ApiKeyRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Base64;

public class ApiKeyAuthInterceptor implements HandlerInterceptor {

    private static final String API_KEY_HEADER = "X-API-Key";
    private static final String API_KEY_PREFIX_ATTR = "apiKeyPrefix";

    private final ApiKeyRepository apiKeyRepository;

    public ApiKeyAuthInterceptor(ApiKeyRepository apiKeyRepository) {
        this.apiKeyRepository = apiKeyRepository;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String rawApiKey = request.getHeader(API_KEY_HEADER);
        if (rawApiKey == null || rawApiKey.isBlank()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        String prefix = rawApiKey.substring(0, Math.min(12, rawApiKey.length())).trim();
        var candidateOpt = apiKeyRepository.findByKeyPrefix(prefix);
        if (candidateOpt.isEmpty()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        var entity = candidateOpt.get();
        if (entity.getRevokedAt() != null) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        // verify hash using same PBKDF2 as service
        try {
            byte[] salt = Base64.getDecoder().decode(entity.getSalt());
            javax.crypto.SecretKeyFactory skf = javax.crypto.SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            javax.crypto.spec.PBEKeySpec spec = new javax.crypto.spec.PBEKeySpec(rawApiKey.toCharArray(), salt, 185000, 256);
            byte[] derived = skf.generateSecret(spec).getEncoded();
            String computed = Base64.getEncoder().encodeToString(derived);
            if (!computed.equals(entity.getKeyHash())) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return false;
            }
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        request.setAttribute(API_KEY_PREFIX_ATTR, prefix);
        return true;
    }
}
