package dev.lions.unionflow.server.payment.pispi;

import dev.lions.unionflow.server.api.payment.PaymentException;
import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HexFormat;
import java.util.Map;
import java.util.Optional;

@ApplicationScoped
public class PispiSignatureVerifier {

    @ConfigProperty(name = "pispi.webhook.secret")
    Optional<String> webhookSecretOpt;

    @ConfigProperty(name = "pispi.webhook.allowed-ips")
    Optional<String> allowedIpsOpt;

    String webhookSecret;
    String allowedIps;

    @jakarta.annotation.PostConstruct
    void init() {
        webhookSecret = webhookSecretOpt.orElse("");
        allowedIps = allowedIpsOpt.orElse("");
    }

    /** Readiness helper (P1-NEW-15) — TRUE si webhook secret HMAC est configuré. */
    public boolean hasWebhookSecret() {
        return webhookSecret != null && !webhookSecret.isEmpty();
    }

    public boolean isIpAllowed(String ip) {
        if (allowedIps == null || allowedIps.isBlank()) {
            return true;
        }
        return Arrays.asList(allowedIps.split(",")).stream()
                .map(String::trim)
                .anyMatch(allowed -> allowed.equals(ip));
    }

    public boolean verifySignature(String rawBody, Map<String, String> headers) throws PaymentException {
        if (webhookSecret == null || webhookSecret.isBlank()) {
            return true;
        }

        // Recherche insensible à la casse
        String receivedSignature = headers.entrySet().stream()
                .filter(e -> "X-PISPI-Signature".equalsIgnoreCase(e.getKey()))
                .map(Map.Entry::getValue)
                .findFirst()
                .orElse(null);

        if (receivedSignature == null) {
            throw new PaymentException("PISPI", "Signature PI-SPI absente", 401);
        }

        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(webhookSecret.getBytes(), "HmacSHA256"));
            String computed = HexFormat.of().formatHex(mac.doFinal(rawBody.getBytes()));

            if (!MessageDigest.isEqual(computed.getBytes(), receivedSignature.getBytes())) {
                throw new PaymentException("PISPI", "Signature PI-SPI invalide", 401);
            }
            return true;
        } catch (PaymentException e) {
            throw e;
        } catch (Exception e) {
            throw new PaymentException("PISPI", "Erreur lors de la vérification de signature : " + e.getMessage(), 500, e);
        }
    }
}
