package dev.lions.unionflow.client.view;

import dev.lions.unionflow.server.api.dto.paiement.WaveBalanceDTO;
import dev.lions.unionflow.server.api.dto.paiement.WaveCheckoutSessionDTO;
import dev.lions.unionflow.client.service.WaveService;
import jakarta.annotation.PostConstruct;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.RetryService;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.jboss.logging.Logger;

/**
 * Bean JSF pour la gestion des paiements Wave Money
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-17
 */
@Named
@ViewScoped
public class WaveBean implements Serializable {

  private static final Logger LOG = Logger.getLogger(WaveBean.class);
  private static final long serialVersionUID = 1L;

  @Inject @org.eclipse.microprofile.rest.client.inject.RestClient WaveService waveService;
  
  @Inject
  ErrorHandlerService errorHandler;
  
  @Inject
  RetryService retryService;

  // Session de paiement en cours
  private WaveCheckoutSessionDTO sessionEnCours;
  private WaveBalanceDTO solde;

  // Données pour créer une session
  private BigDecimal montantPaiement;
  private String devisePaiement = "XOF";
  private String descriptionPaiement;
  private String typePaiement = "COTISATION";
  private UUID organisationId;
  private UUID membreId;
  private String referenceUnionFlow;

  // Résultat du test de connexion
  private Map<String, Object> resultatTest;

  @PostConstruct
  public void init() {
    LOG.info("Initialisation de WaveBean");
    chargerSolde();
  }

  /**
   * Crée une session de paiement Wave
   */
  public void creerSessionPaiement() {
    try {
      LOG.infof("Création d'une session Wave: montant=%s", montantPaiement);

      if (montantPaiement == null || montantPaiement.compareTo(BigDecimal.ZERO) <= 0) {
        errorHandler.showWarning("Erreur", "Le montant doit être supérieur à zéro");
        return;
      }

      // Construire les URLs de redirection
      jakarta.faces.context.FacesContext facesContext = jakarta.faces.context.FacesContext.getCurrentInstance();
      String baseUrl = facesContext.getExternalContext().getRequestContextPath();
      String successUrl = baseUrl + "/pages/secure/wave/success.xhtml";
      String errorUrl = baseUrl + "/pages/secure/wave/error.xhtml";

      sessionEnCours = retryService.executeWithRetrySupplier(
          () -> waveService.creerSessionPaiement(
              montantPaiement,
              devisePaiement,
              successUrl,
              errorUrl,
              referenceUnionFlow,
              descriptionPaiement,
              organisationId,
              membreId),
          "création d'une session de paiement Wave"
      );

      LOG.infof("Session créée: %s", sessionEnCours != null ? sessionEnCours.getWaveSessionId() : "null");
      errorHandler.showSuccess("Succès", "Session de paiement créée avec succès. Redirection vers Wave...");

      // Rediriger vers l'URL Wave
      if (sessionEnCours != null && sessionEnCours.getWaveUrl() != null) {
        facesContext.getExternalContext().redirect(sessionEnCours.getWaveUrl());
      }

    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la création de la session");
      errorHandler.handleException(e, "lors de la création d'une session de paiement Wave", null);
    }
  }

  /**
   * Vérifie le statut d'une session
   */
  public void verifierStatutSession(String sessionId) {
    try {
      LOG.infof("Vérification du statut de la session: %s", sessionId);
      sessionEnCours = retryService.executeWithRetrySupplier(
          () -> waveService.verifierStatutSession(sessionId),
          "vérification du statut d'une session Wave"
      );

    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la vérification du statut");
      errorHandler.handleException(e, "lors de la vérification du statut d'une session Wave", null);
    }
  }

  /**
   * Charge le solde Wave
   */
  public void chargerSolde() {
    try {
      LOG.info("Chargement du solde Wave");
      solde = retryService.executeWithRetrySupplier(
          () -> waveService.consulterSolde(),
          "chargement du solde Wave"
      );

    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors du chargement du solde");
      // Ne pas afficher d'erreur si Wave n'est pas configuré
      solde = null;
    }
  }

  /**
   * Teste la connexion à l'API Wave
   */
  public void testerConnexion() {
    try {
      LOG.info("Test de connexion à l'API Wave");
      resultatTest = retryService.executeWithRetrySupplier(
          () -> waveService.testerConnexion(),
          "test de connexion à l'API Wave"
      );

      if (resultatTest != null && "OK".equals(resultatTest.get("statut"))) {
        errorHandler.showSuccess("Succès", "Connexion à l'API Wave réussie: " + resultatTest.get("message"));
      } else {
        errorHandler.showWarning("Attention",
            resultatTest != null
                ? resultatTest.get("message").toString()
                : "Erreur lors du test de connexion");
      }

    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors du test de connexion");
      errorHandler.handleException(e, "lors du test de connexion à l'API Wave", null);
    }
  }

  /**
   * Réinitialise les données du formulaire
   */
  public void reinitialiserFormulaire() {
    montantPaiement = null;
    devisePaiement = "XOF";
    descriptionPaiement = null;
    typePaiement = "COTISATION";
    referenceUnionFlow = null;
    sessionEnCours = null;
  }

  // Méthodes utilitaires


  /**
   * Vérifie si Wave est disponible
   */
  public boolean isWaveDisponible() {
    return solde != null && solde.isWalletActif();
  }

  // Getters et Setters
  public WaveCheckoutSessionDTO getSessionEnCours() {
    return sessionEnCours;
  }

  public void setSessionEnCours(WaveCheckoutSessionDTO sessionEnCours) {
    this.sessionEnCours = sessionEnCours;
  }

  public WaveBalanceDTO getSolde() {
    return solde;
  }

  public void setSolde(WaveBalanceDTO solde) {
    this.solde = solde;
  }

  public BigDecimal getMontantPaiement() {
    return montantPaiement;
  }

  public void setMontantPaiement(BigDecimal montantPaiement) {
    this.montantPaiement = montantPaiement;
  }

  public String getDevisePaiement() {
    return devisePaiement;
  }

  public void setDevisePaiement(String devisePaiement) {
    this.devisePaiement = devisePaiement;
  }

  public String getDescriptionPaiement() {
    return descriptionPaiement;
  }

  public void setDescriptionPaiement(String descriptionPaiement) {
    this.descriptionPaiement = descriptionPaiement;
  }

  public String getTypePaiement() {
    return typePaiement;
  }

  public void setTypePaiement(String typePaiement) {
    this.typePaiement = typePaiement;
  }

  public UUID getOrganisationId() {
    return organisationId;
  }

  public void setOrganisationId(UUID organisationId) {
    this.organisationId = organisationId;
  }

  public UUID getMembreId() {
    return membreId;
  }

  public void setMembreId(UUID membreId) {
    this.membreId = membreId;
  }

  public String getReferenceUnionFlow() {
    return referenceUnionFlow;
  }

  public void setReferenceUnionFlow(String referenceUnionFlow) {
    this.referenceUnionFlow = referenceUnionFlow;
  }

  public Map<String, Object> getResultatTest() {
    return resultatTest;
  }

  public void setResultatTest(Map<String, Object> resultatTest) {
    this.resultatTest = resultatTest;
  }
}

