package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.paiement.PaiementDTO;
import dev.lions.unionflow.server.service.PaiementService;
import jakarta.annotation.security.PermitAll;
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.jboss.logging.Logger;

/**
 * Resource REST pour la gestion des paiements
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Path("/api/paiements")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@PermitAll
public class PaiementResource {

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

  @Inject PaiementService paiementService;

  /**
   * Crée un nouveau paiement
   *
   * @param paiementDTO DTO du paiement à créer
   * @return Paiement créé
   */
  @POST
  public Response creerPaiement(@Valid PaiementDTO paiementDTO) {
    try {
      PaiementDTO result = paiementService.creerPaiement(paiementDTO);
      return Response.status(Response.Status.CREATED).entity(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la création du paiement");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la création du paiement: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Met à jour un paiement
   *
   * @param id ID du paiement
   * @param paiementDTO DTO avec les modifications
   * @return Paiement mis à jour
   */
  @PUT
  @Path("/{id}")
  public Response mettreAJourPaiement(@PathParam("id") UUID id, @Valid PaiementDTO paiementDTO) {
    try {
      PaiementDTO result = paiementService.mettreAJourPaiement(id, paiementDTO);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Paiement non trouvé"))
          .build();
    } catch (IllegalStateException e) {
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse(e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la mise à jour du paiement");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la mise à jour du paiement: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Valide un paiement
   *
   * @param id ID du paiement
   * @return Paiement validé
   */
  @POST
  @Path("/{id}/valider")
  public Response validerPaiement(@PathParam("id") UUID id) {
    try {
      PaiementDTO result = paiementService.validerPaiement(id);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Paiement non trouvé"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la validation du paiement");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la validation du paiement: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Annule un paiement
   *
   * @param id ID du paiement
   * @return Paiement annulé
   */
  @POST
  @Path("/{id}/annuler")
  public Response annulerPaiement(@PathParam("id") UUID id) {
    try {
      PaiementDTO result = paiementService.annulerPaiement(id);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Paiement non trouvé"))
          .build();
    } catch (IllegalStateException e) {
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse(e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de l'annulation du paiement");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de l'annulation du paiement: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Trouve un paiement par son ID
   *
   * @param id ID du paiement
   * @return Paiement
   */
  @GET
  @Path("/{id}")
  public Response trouverParId(@PathParam("id") UUID id) {
    try {
      PaiementDTO result = paiementService.trouverParId(id);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Paiement non trouvé"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la recherche du paiement");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la recherche du paiement: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Trouve un paiement par son numéro de référence
   *
   * @param numeroReference Numéro de référence
   * @return Paiement
   */
  @GET
  @Path("/reference/{numeroReference}")
  public Response trouverParNumeroReference(@PathParam("numeroReference") String numeroReference) {
    try {
      PaiementDTO result = paiementService.trouverParNumeroReference(numeroReference);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Paiement non trouvé"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la recherche du paiement");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la recherche du paiement: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Liste tous les paiements d'un membre
   *
   * @param membreId ID du membre
   * @return Liste des paiements
   */
  @GET
  @Path("/membre/{membreId}")
  public Response listerParMembre(@PathParam("membreId") UUID membreId) {
    try {
      List<PaiementDTO> result = paiementService.listerParMembre(membreId);
      return Response.ok(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la liste des paiements");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la liste des paiements: " + e.getMessage()))
          .build();
    }
  }

  /** Classe interne pour les réponses d'erreur */
  public static class ErrorResponse {
    public String error;

    public ErrorResponse(String error) {
      this.error = error;
    }
  }
}

