package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.wave.CompteWaveDTO;
import dev.lions.unionflow.server.api.dto.wave.TransactionWaveDTO;
import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave;
import dev.lions.unionflow.server.service.WaveService;
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.jboss.logging.Logger;

/**
 * Resource REST pour l'intégration Wave Mobile Money
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Path("/api/wave")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RolesAllowed({"ADMIN", "MEMBRE", "USER"})
public class WaveResource {

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

  @Inject WaveService waveService;

  // ========================================
  // COMPTES WAVE
  // ========================================

  /**
   * Crée un nouveau compte Wave
   *
   * @param compteWaveDTO DTO du compte à créer
   * @return Compte créé
   */
  @POST
  @RolesAllowed({"ADMIN", "MEMBRE"})
  @Path("/comptes")
  public Response creerCompteWave(@Valid CompteWaveDTO compteWaveDTO) {
    try {
      CompteWaveDTO result = waveService.creerCompteWave(compteWaveDTO);
      return Response.status(Response.Status.CREATED).entity(result).build();
    } catch (IllegalArgumentException e) {
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse(e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la création du compte Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la création du compte Wave: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Met à jour un compte Wave
   *
   * @param id ID du compte
   * @param compteWaveDTO DTO avec les modifications
   * @return Compte mis à jour
   */
  @PUT
  @RolesAllowed({"ADMIN", "MEMBRE"})
  @Path("/comptes/{id}")
  public Response mettreAJourCompteWave(@PathParam("id") UUID id, @Valid CompteWaveDTO compteWaveDTO) {
    try {
      CompteWaveDTO result = waveService.mettreAJourCompteWave(id, compteWaveDTO);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Compte Wave non trouvé"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la mise à jour du compte Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la mise à jour du compte Wave: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Vérifie un compte Wave
   *
   * @param id ID du compte
   * @return Compte vérifié
   */
  @POST
  @RolesAllowed({"ADMIN", "MEMBRE"})
  @Path("/comptes/{id}/verifier")
  public Response verifierCompteWave(@PathParam("id") UUID id) {
    try {
      CompteWaveDTO result = waveService.verifierCompteWave(id);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Compte Wave non trouvé"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la vérification du compte Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la vérification du compte Wave: " + e.getMessage()))
          .build();
    }
  }

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

  /**
   * Trouve un compte Wave par numéro de téléphone
   *
   * @param numeroTelephone Numéro de téléphone
   * @return Compte Wave ou null
   */
  @GET
  @Path("/comptes/telephone/{numeroTelephone}")
  public Response trouverCompteWaveParTelephone(@PathParam("numeroTelephone") String numeroTelephone) {
    try {
      CompteWaveDTO result = waveService.trouverCompteWaveParTelephone(numeroTelephone);
      if (result == null) {
        return Response.status(Response.Status.NOT_FOUND)
            .entity(new ErrorResponse("Compte Wave non trouvé"))
            .build();
      }
      return Response.ok(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la recherche du compte Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la recherche du compte Wave: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Liste tous les comptes Wave d'une organisation
   *
   * @param organisationId ID de l'organisation
   * @return Liste des comptes Wave
   */
  @GET
  @Path("/comptes/organisation/{organisationId}")
  public Response listerComptesWaveParOrganisation(@PathParam("organisationId") UUID organisationId) {
    try {
      List<CompteWaveDTO> result = waveService.listerComptesWaveParOrganisation(organisationId);
      return Response.ok(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la liste des comptes Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la liste des comptes Wave: " + e.getMessage()))
          .build();
    }
  }

  // ========================================
  // TRANSACTIONS WAVE
  // ========================================

  /**
   * Crée une nouvelle transaction Wave
   *
   * @param transactionWaveDTO DTO de la transaction à créer
   * @return Transaction créée
   */
  @POST
  @RolesAllowed({"ADMIN", "MEMBRE"})
  @Path("/transactions")
  public Response creerTransactionWave(@Valid TransactionWaveDTO transactionWaveDTO) {
    try {
      TransactionWaveDTO result = waveService.creerTransactionWave(transactionWaveDTO);
      return Response.status(Response.Status.CREATED).entity(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la création de la transaction Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la création de la transaction Wave: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Met à jour le statut d'une transaction Wave
   *
   * @param waveTransactionId Identifiant Wave de la transaction
   * @param statut Nouveau statut
   * @return Transaction mise à jour
   */
  @PUT
  @RolesAllowed({"ADMIN", "MEMBRE"})
  @Path("/transactions/{waveTransactionId}/statut")
  public Response mettreAJourStatutTransaction(
      @PathParam("waveTransactionId") String waveTransactionId, StatutTransactionWave statut) {
    try {
      TransactionWaveDTO result = waveService.mettreAJourStatutTransaction(waveTransactionId, statut);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Transaction Wave non trouvée"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la mise à jour du statut de la transaction Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(
              new ErrorResponse(
                  "Erreur lors de la mise à jour du statut de la transaction Wave: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Trouve une transaction Wave par son identifiant Wave
   *
   * @param waveTransactionId Identifiant Wave
   * @return Transaction Wave
   */
  @GET
  @Path("/transactions/{waveTransactionId}")
  public Response trouverTransactionWaveParId(@PathParam("waveTransactionId") String waveTransactionId) {
    try {
      TransactionWaveDTO result = waveService.trouverTransactionWaveParId(waveTransactionId);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(new ErrorResponse("Transaction Wave non trouvée"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la recherche de la transaction Wave");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(new ErrorResponse("Erreur lors de la recherche de la transaction Wave: " + 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;
    }
  }
}
