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

import dev.lions.unionflow.server.api.payment.CheckoutRequest;
import dev.lions.unionflow.server.api.payment.PaymentEvent;
import dev.lions.unionflow.server.api.payment.PaymentStatus;
import dev.lions.unionflow.server.payment.pispi.dto.Pacs002Response;
import dev.lions.unionflow.server.payment.pispi.dto.Pacs008Request;
import jakarta.enterprise.context.ApplicationScoped;

import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@ApplicationScoped
public class PispiIso20022Mapper {

    public Pacs008Request toPacs008(CheckoutRequest req, String institutionBic) {
        Pacs008Request pacs = new Pacs008Request();

        pacs.setMessageId("UFMSG-" + UUID.randomUUID().toString().replace("-", "").substring(0, 16).toUpperCase());
        pacs.setCreationDateTime(DateTimeFormatter.ISO_INSTANT.format(Instant.now()));
        pacs.setNumberOfTransactions("1");

        // ISO 20022 : EndToEndId max 35 chars
        String ref = req.reference();
        pacs.setEndToEndId(ref.length() > 35 ? ref.substring(0, 35) : ref);

        pacs.setInstrId("UFINS-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase());
        pacs.setAmount(req.amount());
        pacs.setCurrency(req.currency());

        String customerName = req.metadata() != null
                ? req.metadata().getOrDefault("customerName", "MEMBRE UNIONFLOW")
                : "MEMBRE UNIONFLOW";
        pacs.setDebtorName(customerName);
        pacs.setDebtorBic(institutionBic);

        String creditorName = req.metadata() != null
                ? req.metadata().getOrDefault("creditorName", "ORGANISATION UNIONFLOW")
                : "ORGANISATION UNIONFLOW";
        pacs.setCreditorName(creditorName);
        pacs.setCreditorBic(institutionBic);

        // ISO 20022 : RemittanceInfo max 140 chars
        pacs.setRemittanceInfo(ref.length() > 140 ? ref.substring(0, 140) : ref);

        return pacs;
    }

    public PaymentStatus fromPacs002Status(String isoCode) {
        return switch (isoCode) {
            case "ACSC" -> PaymentStatus.SUCCESS;
            case "ACSP" -> PaymentStatus.PROCESSING;
            case "RJCT" -> PaymentStatus.FAILED;
            case "PDNG" -> PaymentStatus.INITIATED;
            default -> PaymentStatus.PROCESSING;
        };
    }

    public PaymentEvent fromPacs002(Pacs002Response resp) {
        return new PaymentEvent(
                resp.getClearingSystemReference(),
                resp.getOriginalEndToEndId(),
                fromPacs002Status(resp.getTransactionStatus()),
                null,
                resp.getClearingSystemReference(),
                resp.getAcceptanceDateTime() != null ? resp.getAcceptanceDateTime() : Instant.now()
        );
    }
}
