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

import dev.lions.unionflow.server.api.payment.PaymentEvent;
import dev.lions.unionflow.server.api.payment.PaymentException;
import dev.lions.unionflow.server.payment.orchestration.PaymentOrchestrator;
import dev.lions.unionflow.server.payment.pispi.dto.Pacs002Response;
import jakarta.annotation.security.PermitAll;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Path("/api/pispi/webhook")
public class PispiWebhookResource {

    @Inject
    PispiSignatureVerifier verifier;

    @Inject
    PispiIso20022Mapper mapper;

    @Inject
    PaymentOrchestrator orchestrator;

    @POST
    @Consumes("application/xml")
    @PermitAll
    public Response recevoir(
            String rawXmlBody,
            @Context HttpHeaders headers,
            @HeaderParam("X-Forwarded-For") @DefaultValue("") String forwardedFor) {

        String clientIp = forwardedFor.isBlank() ? "unknown" : forwardedFor.split(",")[0].trim();

        if (!verifier.isIpAllowed(clientIp)) {
            log.warn("PI-SPI webhook refusé — IP non autorisée : {}", clientIp);
            return Response.status(403).entity("IP non autorisée").build();
        }

        Map<String, String> headersMap = headers.getRequestHeaders().entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));

        try {
            verifier.verifySignature(rawXmlBody, headersMap);
        } catch (PaymentException e) {
            log.warn("PI-SPI webhook — échec vérification signature : {}", e.getMessage());
            return Response.status(401).entity(e.getMessage()).build();
        }

        try {
            Pacs002Response pacs002 = Pacs002Response.fromXml(rawXmlBody);
            PaymentEvent event = mapper.fromPacs002(pacs002);
            orchestrator.handleEvent(event);
            log.info("PI-SPI webhook traité : ref={}, statut={}", event.reference(), event.status());
            return Response.ok().build();
        } catch (Exception e) {
            log.error("PI-SPI webhook — erreur traitement : {}", e.getMessage(), e);
            return Response.serverError().entity("Erreur interne").build();
        }
    }
}
