package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.versement.request.DeclarerVersementManuelRequest;
import dev.lions.unionflow.server.api.dto.versement.request.InitierDepotEpargneRequest;
import dev.lions.unionflow.server.api.dto.versement.request.InitierVersementWaveRequest;
import dev.lions.unionflow.server.api.dto.versement.response.VersementGatewayResponse;
import dev.lions.unionflow.server.api.dto.versement.response.VersementResponse;
import dev.lions.unionflow.server.api.dto.versement.response.VersementStatutResponse;
import dev.lions.unionflow.server.api.dto.versement.response.VersementSummaryResponse;
import dev.lions.unionflow.server.service.VersementService;
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 versements.
 *
 * <p>Endpoints principaux :
 * <ul>
 *   <li>{@code POST /api/versements/initier-wave} — démarre le flux Wave deep link</li>
 *   <li>{@code GET  /api/versements/statut/{intentionId}} — retour deep link / polling</li>
 *   <li>{@code POST /api/versements/declarer-manuel} — déclaration espèces/virement/chèque</li>
 *   <li>{@code GET  /api/versements/mes-versements} — historique du membre connecté</li>
 * </ul>
 *
 * @author UnionFlow Team
 * @version 4.0
 * @since 2026-04-13
 */
@Path("/api/versements")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RolesAllowed({"ADMIN", "ADMIN_ORGANISATION", "MEMBRE", "USER"})
@Tag(name = "Versements", description = "Versements de cotisations — Wave et manuel")
public class VersementResource {

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

    @Inject
    VersementService versementService;

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

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

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

    @GET
    @Path("/membre/{membreId}")
    public Response listerParMembre(@PathParam("membreId") UUID membreId) {
        LOG.infof("GET /api/versements/membre/%s", membreId);
        List<VersementSummaryResponse> result = versementService.listerParMembre(membreId);
        return Response.ok(result).build();
    }

    @GET
    @Path("/mes-versements")
    @RolesAllowed({"MEMBRE", "ADMIN", "ADMIN_ORGANISATION"})
    public Response getMesVersements(
            @QueryParam("limit") @DefaultValue("20") int limit) {
        LOG.infof("GET /api/versements/mes-versements?limit=%d", limit);
        List<VersementSummaryResponse> result = versementService.getMesVersements(limit);
        return Response.ok(result).build();
    }

    // ── Validation / Annulation ───────────────────────────────────────────────

    @POST
    @Path("/{id}/valider")
    @RolesAllowed({"ADMIN", "ADMIN_ORGANISATION"})
    public Response validerVersement(@PathParam("id") UUID id) {
        LOG.infof("POST /api/versements/%s/valider", id);
        VersementResponse result = versementService.validerVersement(id);
        return Response.ok(result).build();
    }

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

    // ── Flux Wave ─────────────────────────────────────────────────────────────

    /**
     * Initie un versement Wave.
     *
     * <p>Le mobile appelle cet endpoint puis ouvre le {@code waveLaunchUrl} retourné
     * avec {@code url_launcher}. Wave s'ouvre avec le montant et le numéro pré-remplis.
     * Après confirmation, Wave redirige vers
     * {@code unionflow://payment?result=success&ref={clientReference}}.
     */
    @POST
    @Path("/initier-wave")
    @RolesAllowed({"MEMBRE", "MEMBRE_ACTIF", "ADMIN", "ADMIN_ORGANISATION", "USER"})
    public Response initierVersementWave(@Valid InitierVersementWaveRequest request) {
        LOG.infof("POST /api/versements/initier-wave — cotisation: %s", request.cotisationId());
        VersementGatewayResponse result = versementService.initierVersementWave(request);
        return Response.status(Response.Status.CREATED).entity(result).build();
    }

    /**
     * Retour deep link / polling du statut d'un versement Wave.
     *
     * <p>Appelé par le mobile au retour du deep link
     * {@code unionflow://payment?result=success&ref={intentionId}}
     * pour confirmer que le paiement est bien enregistré côté UnionFlow.
     * Également utilisé par le web en polling toutes les 3 secondes.
     */
    @GET
    @Path("/statut/{intentionId}")
    @RolesAllowed({"MEMBRE", "MEMBRE_ACTIF", "ADMIN", "ADMIN_ORGANISATION", "USER"})
    public Response getStatutVersement(@PathParam("intentionId") UUID intentionId) {
        LOG.infof("GET /api/versements/statut/%s", intentionId);
        VersementStatutResponse result = versementService.verifierStatutVersement(intentionId);
        return Response.ok(result).build();
    }

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

    /**
     * Déclare un versement manuel (espèces, virement, chèque).
     * Le versement est créé avec le statut EN_ATTENTE_VALIDATION.
     * Le trésorier devra le valider via la page admin.
     */
    @POST
    @Path("/declarer-manuel")
    @RolesAllowed({"MEMBRE", "ADMIN", "ADMIN_ORGANISATION"})
    public Response declarerVersementManuel(@Valid DeclarerVersementManuelRequest request) {
        LOG.infof("POST /api/versements/declarer-manuel — cotisation: %s, méthode: %s",
            request.cotisationId(), request.methodePaiement());
        VersementResponse result = versementService.declarerVersementManuel(request);
        return Response.status(Response.Status.CREATED).entity(result).build();
    }

    // ── Dépôt épargne ─────────────────────────────────────────────────────────

    @POST
    @Path("/initier-depot-epargne")
    @RolesAllowed({"MEMBRE", "MEMBRE_ACTIF", "ADMIN", "ADMIN_ORGANISATION", "USER"})
    public Response initierDepotEpargne(@Valid InitierDepotEpargneRequest request) {
        LOG.infof("POST /api/versements/initier-depot-epargne — compte: %s, montant: %s",
            request.compteId(), request.montant());
        VersementGatewayResponse result = versementService.initierDepotEpargneEnLigne(request);
        return Response.status(Response.Status.CREATED).entity(result).build();
    }
}
