package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.souscription.FormuleAbonnementResponse;
import dev.lions.unionflow.server.api.dto.souscription.SouscriptionDemandeRequest;
import dev.lions.unionflow.server.api.dto.souscription.SouscriptionStatutResponse;
import dev.lions.unionflow.server.service.SouscriptionService;
import dev.lions.unionflow.server.service.support.SecuriteHelper;
import io.quarkus.security.Authenticated;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.jboss.logging.Logger;

import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Ressource REST pour le workflow de souscription/onboarding UnionFlow.
 *
 * <p>Endpoints publics :
 * <ul>
 *   <li>{@code GET /api/souscriptions/formules} — catalogue des formules (PermitAll)</li>
 *   <li>{@code POST /api/souscriptions/confirmer-paiement} — callback deep link Wave (PermitAll)</li>
 * </ul>
 *
 * <p>Endpoints ADMIN_ORGANISATION :
 * <ul>
 *   <li>{@code GET /api/souscriptions/ma-souscription}</li>
 *   <li>{@code POST /api/souscriptions/demande}</li>
 *   <li>{@code POST /api/souscriptions/{id}/initier-paiement}</li>
 * </ul>
 *
 * <p>Endpoints SUPER_ADMIN :
 * <ul>
 *   <li>{@code GET /api/souscriptions/admin/en-attente}</li>
 *   <li>{@code POST /api/souscriptions/admin/{id}/approuver}</li>
 *   <li>{@code POST /api/souscriptions/admin/{id}/rejeter}</li>
 * </ul>
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-30
 */
@Path("/api/souscriptions")
@ApplicationScoped
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class SouscriptionResource {

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

    @Inject
    SouscriptionService souscriptionService;

    @Inject
    SecuriteHelper securiteHelper;

    // ── Catalogue (public) ────────────────────────────────────────────────────

    /**
     * Retourne le catalogue complet des formules d'abonnement.
     *
     * <p>Endpoint public — PermitAll. Utilisé par l'écran d'onboarding mobile
     * avant authentification.
     */
    @GET
    @Path("/formules")
    @PermitAll
    public Response getFormules() {
        LOG.debug("GET /api/souscriptions/formules");
        List<FormuleAbonnementResponse> formules = souscriptionService.getFormules();
        return Response.ok(formules).build();
    }

    // ── ADMIN_ORGANISATION ────────────────────────────────────────────────────

    /**
     * Retourne la souscription de l'organisation du membre connecté.
     */
    @GET
    @Path("/ma-souscription")
    @Authenticated
    public Response getMaSouscription() {
        LOG.debug("GET /api/souscriptions/ma-souscription");
        SouscriptionStatutResponse response = souscriptionService.getMaSouscription();
        return Response.ok(response).build();
    }

    /**
     * Crée une demande de souscription.
     *
     * <p>Le corps de la requête doit contenir les champs :
     * {@code typeFormule}, {@code plageMembres}, {@code typePeriode},
     * {@code typeOrganisation}, {@code organisationId}.
     */
    @POST
    @Path("/demande")
    @Authenticated
    public Response creerDemande(@Valid SouscriptionDemandeRequest request) {
        LOG.infof("POST /api/souscriptions/demande — formule=%s plage=%s",
                request.getTypeFormule(), request.getPlageMembres());
        SouscriptionStatutResponse response = souscriptionService.creerDemande(request);
        return Response.status(Response.Status.CREATED).entity(response).build();
    }

    /**
     * Initie une session de paiement Wave pour la souscription identifiée.
     *
     * <p>Retourne le {@code waveLaunchUrl} à ouvrir dans le navigateur ou WebView.
     *
     * @param id UUID de la souscription
     */
    @POST
    @Path("/{id}/initier-paiement")
    @Authenticated
    public Response initierPaiement(@PathParam("id") UUID id) {
        LOG.infof("POST /api/souscriptions/%s/initier-paiement", id);
        SouscriptionStatutResponse response = souscriptionService.initierPaiementWave(id);
        return Response.ok(response).build();
    }

    // ── Callback Wave (public) ────────────────────────────────────────────────

    /**
     * Confirme le paiement Wave (appelé depuis le deep link ou un webhook).
     *
     * <p>Endpoint public car appelé par le système Wave en dehors de toute session
     * utilisateur. La souscription est identifiée par son UUID.
     *
     * @param id     UUID de la souscription (query param {@code id})
     * @param waveId identifiant de la transaction Wave (query param {@code wave_id})
     */
    @POST
    @Path("/confirmer-paiement")
    @PermitAll
    public Response confirmerPaiement(@QueryParam("id") UUID id,
                                       @QueryParam("wave_id") String waveId) {
        if (id == null) {
            throw new BadRequestException("Le paramètre 'id' est obligatoire");
        }
        LOG.infof("POST /api/souscriptions/confirmer-paiement — id=%s waveId=%s", id, waveId);
        souscriptionService.confirmerPaiement(id, waveId);
        return Response.ok(Map.of("message", "Paiement confirmé — compte activé")).build();
    }

    // ── SuperAdmin ────────────────────────────────────────────────────────────

    /**
     * Liste toutes les souscriptions (SuperAdmin dashboard), avec filtre optionnel par org.
     */
    @GET
    @Path("/admin/toutes")
    @RolesAllowed({"SUPER_ADMIN"})
    public Response getSouscriptionsToutes(
            @QueryParam("organisationId") UUID organisationId,
            @QueryParam("page") @DefaultValue("0") int page,
            @QueryParam("size") @DefaultValue("1000") int size) {
        LOG.debug("GET /api/souscriptions/admin/toutes");
        List<SouscriptionStatutResponse> liste = souscriptionService.listerToutes(organisationId, page, size);
        return Response.ok(liste).build();
    }

    /**
     * Retourne la souscription active d'une organisation (SuperAdmin).
     */
    @GET
    @Path("/admin/organisation/{organisationId}/active")
    @RolesAllowed({"SUPER_ADMIN"})
    public Response getActiveParOrganisation(@PathParam("organisationId") UUID organisationId) {
        LOG.debugf("GET /api/souscriptions/admin/organisation/%s/active", organisationId);
        SouscriptionStatutResponse resp = souscriptionService.obtenirActiveParOrganisation(organisationId);
        if (resp == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        return Response.ok(resp).build();
    }

    /**
     * Liste les souscriptions en attente de validation SuperAdmin (statut PAIEMENT_CONFIRME).
     */
    @GET
    @Path("/admin/en-attente")
    @RolesAllowed({"SUPER_ADMIN"})
    public Response getSouscriptionsEnAttente() {
        LOG.debug("GET /api/souscriptions/admin/en-attente");
        List<SouscriptionStatutResponse> liste = souscriptionService.getSouscriptionsEnAttenteValidation();
        return Response.ok(liste).build();
    }

    /**
     * Approuve une souscription et active le compte de l'administrateur d'organisation.
     *
     * @param id UUID de la souscription
     */
    @POST
    @Path("/admin/{id}/approuver")
    @RolesAllowed({"SUPER_ADMIN"})
    public Response approuver(@PathParam("id") UUID id) {
        LOG.infof("POST /api/souscriptions/admin/%s/approuver", id);
        UUID superAdminId = securiteHelper.resolveMembreId();
        souscriptionService.approuver(id, superAdminId);
        return Response.ok(Map.of("message", "Souscription approuvée — compte activé")).build();
    }

    /**
     * Rejette une souscription avec un commentaire obligatoire.
     *
     * <p>Le corps de la requête doit contenir {@code {"commentaire": "..."}}.
     *
     * @param id   UUID de la souscription
     * @param body JSON avec le champ {@code commentaire}
     */
    @POST
    @Path("/admin/{id}/rejeter")
    @RolesAllowed({"SUPER_ADMIN"})
    public Response rejeter(@PathParam("id") UUID id, Map<String, String> body) {
        LOG.infof("POST /api/souscriptions/admin/%s/rejeter", id);
        String commentaire = body != null ? body.get("commentaire") : null;
        if (commentaire == null || commentaire.isBlank()) {
            throw new BadRequestException("Le champ 'commentaire' est obligatoire pour un rejet");
        }
        UUID superAdminId = securiteHelper.resolveMembreId();
        souscriptionService.rejeter(id, superAdminId, commentaire);
        return Response.ok(Map.of("message", "Souscription rejetée")).build();
    }
}
