package dev.lions.unionflow.server.resource;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.TransactionEpargneRequest;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
import dev.lions.unionflow.server.entity.IntentionPaiement;
import dev.lions.unionflow.server.repository.IntentionPaiementRepository;
import dev.lions.unionflow.server.service.VersementService;
import dev.lions.unionflow.server.service.mutuelle.epargne.TransactionEpargneService;
import jakarta.annotation.security.PermitAll;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;

import java.math.BigDecimal;
import java.net.URI;
import java.util.UUID;

/**
 * Redirection après paiement Wave (spec Checkout API).
 * Wave redirige le client vers success_url ou error_url (https).
 * On renvoie une 302 vers le deep link de l'app (unionflow://payment?result=...&ref=...).
 * En mode mock : GET /success exécute aussi la validation simulée (intention COMPLETEE, cotisations PAYEE)
 * pour que le flux "Ouvrir Wave" → retour app soit entièrement mocké.
 */
@Path("/api/wave-redirect")
@PermitAll
public class WaveRedirectResource {

    private static final Logger LOG = Logger.getLogger(WaveRedirectResource.class);
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @ConfigProperty(name = "wave.deep.link.scheme", defaultValue = "unionflow")
    String deepLinkScheme;

    @ConfigProperty(name = "wave.mock.enabled", defaultValue = "false")
    boolean mockEnabled;

    @Inject
    IntentionPaiementRepository intentionPaiementRepository;

    @Inject
    TransactionEpargneService transactionEpargneService;

    @Inject
    VersementService versementService;

    @GET
    @Path("/success")
    @Transactional
    public Response success(@QueryParam("ref") String ref) {
        LOG.infof("Wave redirect success (mobile), ref=%s", ref);
        if (ref != null && !ref.isBlank()) {
            applyCompletion(ref);
        }
        String location = buildDeepLink("success", ref);
        return Response.seeOther(URI.create(location)).build();
    }

    /**
     * Endpoint de redirection Wave pour le flux web QR code.
     * Appelé par Wave sur le téléphone du membre après paiement confirmé.
     * Marque la cotisation PAYEE et affiche une page HTML de confirmation.
     */
    @GET
    @Path("/web-success")
    @Produces(MediaType.TEXT_HTML)
    @Transactional
    public Response webSuccess(@QueryParam("ref") String ref) {
        LOG.infof("Wave redirect web-success, ref=%s", ref);
        if (ref != null && !ref.isBlank()) {
            applyCompletion(ref);
        }
        String html = """
            <!DOCTYPE html>
            <html lang="fr">
            <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
            <title>Paiement confirmé</title>
            <style>
              body{font-family:sans-serif;display:flex;flex-direction:column;align-items:center;
                   justify-content:center;min-height:100vh;margin:0;background:#f0fdf4;}
              .card{background:#fff;border-radius:16px;padding:2rem 2.5rem;text-align:center;
                    box-shadow:0 4px 24px #0001;max-width:360px;}
              .icon{font-size:3.5rem;margin-bottom:1rem;}
              h2{color:#16a34a;margin:.5rem 0;}
              p{color:#555;margin:.5rem 0;}
            </style>
            </head>
            <body>
              <div class="card">
                <div class="icon">✅</div>
                <h2>Paiement confirmé !</h2>
                <p>Votre cotisation a été enregistrée avec succès.</p>
                <p style="font-size:.85rem;color:#888;margin-top:1rem;">
                  Vous pouvez fermer cette page et revenir sur UnionFlow.
                </p>
              </div>
            </body>
            </html>
            """;
        return Response.ok(html).build();
    }

    @GET
    @Path("/error")
    public Response error(@QueryParam("ref") String ref) {
        LOG.infof("Wave redirect error, ref=%s", ref);
        String location = buildDeepLink("error", ref);
        return Response.seeOther(URI.create(location)).build();
    }

    /**
     * Test uniquement (wave.mock.enabled=true) : simule la validation Wave puis redirige.
     * Appelle la même logique que /success en mock (applyMockCompletion).
     */
    @GET
    @Path("/mock-complete")
    @Transactional
    public Response mockComplete(@QueryParam("ref") String ref) {
        if (!mockEnabled) {
            LOG.warn("mock-complete ignoré (wave.mock.enabled=false)");
            return Response.seeOther(URI.create(buildDeepLink("error", ref))).build();
        }
        if (ref == null || ref.isBlank()) {
            return Response.status(Response.Status.BAD_REQUEST).entity("ref requis").build();
        }
        applyCompletion(ref);
        return Response.seeOther(URI.create(buildDeepLink("success", ref))).build();
    }

    /**
     * Marque l'intention comme complétée et réconcilie les cotisations/dépôts liés.
     * Délègue au PaiementService pour les cotisations ; gère les dépôts épargne localement.
     */
    private void applyCompletion(String ref) {
        try {
            UUID intentionId = UUID.fromString(ref.trim());
            IntentionPaiement intention = intentionPaiementRepository.findById(intentionId);
            if (intention == null) {
                LOG.warnf("Intention non trouvée: %s", ref);
                return;
            }

            // Gérer les dépôts épargne (non couverts par PaiementService)
            String objetsCibles = intention.getObjetsCibles();
            if (objetsCibles != null && !objetsCibles.isBlank()) {
                JsonNode arr = OBJECT_MAPPER.readTree(objetsCibles);
                if (arr.isArray()) {
                    for (JsonNode node : arr) {
                        if ("DEPOT_EPARGNE".equals(node.path("type").asText())
                                && node.has("compteId") && node.has("montant")) {
                            String compteId = node.get("compteId").asText();
                            BigDecimal montant = new BigDecimal(node.get("montant").asText());
                            TransactionEpargneRequest req = TransactionEpargneRequest.builder()
                                    .compteId(compteId)
                                    .typeTransaction(TypeTransactionEpargne.DEPOT)
                                    .montant(montant)
                                    .motif("Dépôt via Wave (mobile money)")
                                    .build();
                            transactionEpargneService.executerTransaction(req);
                            LOG.infof("Wave: dépôt épargne %s XOF sur compte %s", montant, compteId);
                        }
                    }
                }
            }

            // Déléguer la confirmation cotisations au service
            versementService.confirmerVersementWave(intention, null);
            LOG.infof("Wave: intention %s complétée", ref);
        } catch (Exception e) {
            LOG.errorf(e, "Wave: erreur applyCompletion ref=%s", ref);
        }
    }

    private String buildDeepLink(String result, String ref) {
        StringBuilder sb = new StringBuilder();
        sb.append(deepLinkScheme).append("://payment?result=").append(result);
        if (ref != null && !ref.isBlank()) {
            sb.append("&ref=").append(ref);
        }
        return sb.toString();
    }
}
