package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.paiement.request.CreatePaiementRequest;
import dev.lions.unionflow.server.api.dto.paiement.request.DeclarerPaiementManuelRequest;
import dev.lions.unionflow.server.api.dto.paiement.request.InitierPaiementEnLigneRequest;
import dev.lions.unionflow.server.api.dto.paiement.response.IntentionStatutResponse;
import dev.lions.unionflow.server.api.dto.paiement.response.PaiementGatewayResponse;
import dev.lions.unionflow.server.api.dto.paiement.response.PaiementResponse;
import dev.lions.unionflow.server.api.dto.paiement.response.PaiementSummaryResponse;
import dev.lions.unionflow.server.service.PaiementService;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;

/**
 * Resource REST pour la gestion des paiements (Wave Checkout et paiements manuels).
 *
 * <p>Endpoints principaux :
 * <ul>
 *   <li>{@code POST /api/paiements/initier-paiement-en-ligne} — démarre le flux Wave QR code</li>
 *   <li>{@code GET  /api/paiements/statut-intention/{intentionId}} — polling du statut Wave</li>
 *   <li>{@code POST /api/paiements/declarer-manuel} — paiement manuel (espèces/virement)</li>
 *   <li>{@code GET  /api/paiements/mon-historique} — historique du membre connecté</li>
 * </ul>
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2026-04-13
 */
@Path("/api/paiements")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RolesAllowed({"ADMIN", "ADMIN_ORGANISATION", "MEMBRE", "USER"})
@Tag(name = "Paiements", description = "Paiements de cotisations — Wave Checkout et manuel")
public class PaiementResource {

    private static final Logger LOG = Logger.getLogger(PaiementResource.class);

    @Inject
    PaiementService paiementService;

    // ── Lecture ───────────────────────────────────────────────────────────────

    @GET
    @Path("/{id}")
    public Response trouverParId(@PathParam("id") UUID id) {
        LOG.infof("GET /api/paiements/%s", id);
        PaiementResponse result = paiementService.trouverParId(id);
        return Response.ok(result).build();
    }

    @GET
    @Path("/reference/{numeroReference}")
    public Response trouverParNumeroReference(
            @PathParam("numeroReference") String numeroReference) {
        LOG.infof("GET /api/paiements/reference/%s", numeroReference);
        PaiementResponse result = paiementService.trouverParNumeroReference(numeroReference);
        return Response.ok(result).build();
    }

    @GET
    @Path("/membre/{membreId}")
    @RolesAllowed({"ADMIN", "ADMIN_ORGANISATION"})
    public Response listerParMembre(@PathParam("membreId") UUID membreId) {
        LOG.infof("GET /api/paiements/membre/%s", membreId);
        List<PaiementSummaryResponse> result = paiementService.listerParMembre(membreId);
        return Response.ok(result).build();
    }

    @GET
    @Path("/mon-historique")
    @RolesAllowed({"MEMBRE", "ADMIN", "ADMIN_ORGANISATION"})
    public Response getMonHistoriquePaiements(
            @QueryParam("limit") @DefaultValue("20") int limit) {
        LOG.infof("GET /api/paiements/mon-historique?limit=%d", limit);
        List<PaiementSummaryResponse> result = paiementService.getMonHistoriquePaiements(limit);
        return Response.ok(result).build();
    }

    // ── Administration ────────────────────────────────────────────────────────

    @POST
    @RolesAllowed({"ADMIN", "ADMIN_ORGANISATION"})
    public Response creerPaiement(@Valid CreatePaiementRequest request) {
        LOG.infof("POST /api/paiements — référence: %s", request.numeroReference());
        PaiementResponse result = paiementService.creerPaiement(request);
        return Response.status(Response.Status.CREATED).entity(result).build();
    }

    @POST
    @Path("/{id}/valider")
    @RolesAllowed({"ADMIN", "ADMIN_ORGANISATION"})
    public Response validerPaiement(@PathParam("id") UUID id) {
        LOG.infof("POST /api/paiements/%s/valider", id);
        PaiementResponse result = paiementService.validerPaiement(id);
        return Response.ok(result).build();
    }

    @POST
    @Path("/{id}/annuler")
    @RolesAllowed({"ADMIN", "ADMIN_ORGANISATION", "MEMBRE"})
    public Response annulerPaiement(@PathParam("id") UUID id) {
        LOG.infof("POST /api/paiements/%s/annuler", id);
        PaiementResponse result = paiementService.annulerPaiement(id);
        return Response.ok(result).build();
    }

    // ── Flux Wave Checkout (QR code web) ──────────────────────────────────────

    /**
     * Initie un paiement Wave via Checkout QR code.
     * Le web encode le {@code waveLaunchUrl} en QR code, l'utilisateur le scanne
     * depuis l'app Wave. Après confirmation, Wave redirige vers la success URL.
     */
    @POST
    @Path("/initier-paiement-en-ligne")
    @RolesAllowed({"MEMBRE", "ADMIN", "ADMIN_ORGANISATION", "USER"})
    public Response initierPaiementEnLigne(@Valid InitierPaiementEnLigneRequest request) {
        LOG.infof("POST /api/paiements/initier-paiement-en-ligne — cotisation: %s, méthode: %s",
            request.cotisationId(), request.methodePaiement());
        PaiementGatewayResponse result = paiementService.initierPaiementEnLigne(request);
        return Response.status(Response.Status.CREATED).entity(result).build();
    }

    /**
     * Polling du statut d'une intention de paiement Wave.
     * Appelé toutes les 3 secondes par le web pendant que l'utilisateur scanne le QR code.
     * Retourne {@code confirme=true} dès que Wave confirme le paiement.
     */
    @GET
    @Path("/statut-intention/{intentionId}")
    @RolesAllowed({"MEMBRE", "ADMIN", "ADMIN_ORGANISATION", "USER"})
    public Response getStatutIntention(@PathParam("intentionId") UUID intentionId) {
        LOG.infof("GET /api/paiements/statut-intention/%s", intentionId);
        IntentionStatutResponse result = paiementService.getStatutIntention(intentionId);
        return Response.ok(result).build();
    }

    // ── Flux manuel ───────────────────────────────────────────────────────────

    @POST
    @Path("/declarer-manuel")
    @RolesAllowed({"MEMBRE", "ADMIN", "ADMIN_ORGANISATION"})
    public Response declarerPaiementManuel(@Valid DeclarerPaiementManuelRequest request) {
        LOG.infof("POST /api/paiements/declarer-manuel — cotisation: %s, méthode: %s",
            request.cotisationId(), request.methodePaiement());
        PaiementResponse result = paiementService.declarerPaiementManuel(request);
        return Response.status(Response.Status.CREATED).entity(result).build();
    }
}
