package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.dto.WaveBalanceDTO;
import dev.lions.unionflow.client.dto.WaveCheckoutSessionDTO;
import dev.lions.unionflow.client.service.WaveService;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
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 LOGGER = Logger.getLogger(WaveBean.class);
  private static final long serialVersionUID = 1L;

  @Inject @org.eclipse.microprofile.rest.client.inject.RestClient WaveService waveService;

  // 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() {
    LOGGER.info("Initialisation de WaveBean");
    chargerSolde();
  }

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

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

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

      sessionEnCours =
          waveService.creerSessionPaiement(
              montantPaiement,
              devisePaiement,
              successUrl,
              errorUrl,
              referenceUnionFlow,
              descriptionPaiement,
              organisationId,
              membreId);

      LOGGER.infof("Session créée: %s", sessionEnCours != null ? sessionEnCours.getWaveSessionId() : "null");
      ajouterMessage(
          FacesMessage.SEVERITY_INFO,
          "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.getCurrentInstance()
            .getExternalContext()
            .redirect(sessionEnCours.getWaveUrl());
      }

    } catch (Exception e) {
      LOGGER.errorf(e, "Erreur lors de la création de la session: %s", e.getMessage());
      ajouterMessage(
          FacesMessage.SEVERITY_ERROR,
          "Erreur",
          "Erreur lors de la création de la session: " + e.getMessage());
    }
  }

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

    } catch (Exception e) {
      LOGGER.errorf(e, "Erreur lors de la vérification du statut: %s", e.getMessage());
      ajouterMessage(
          FacesMessage.SEVERITY_ERROR,
          "Erreur",
          "Erreur lors de la vérification du statut: " + e.getMessage());
    }
  }

  /**
   * Charge le solde Wave
   */
  public void chargerSolde() {
    try {
      LOGGER.info("Chargement du solde Wave");
      solde = waveService.consulterSolde();

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

  /**
   * Teste la connexion à l'API Wave
   */
  public void testerConnexion() {
    try {
      LOGGER.info("Test de connexion à l'API Wave");
      resultatTest = waveService.testerConnexion();

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

    } catch (Exception e) {
      LOGGER.errorf(e, "Erreur lors du test de connexion: %s", e.getMessage());
      ajouterMessage(
          FacesMessage.SEVERITY_ERROR,
          "Erreur",
          "Erreur lors du test de connexion: " + e.getMessage());
    }
  }

  /**
   * 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

  private void ajouterMessage(
      jakarta.faces.application.FacesMessage.Severity severity, String resume, String detail) {
    FacesContext.getCurrentInstance()
        .addMessage(null, new FacesMessage(severity, resume, detail));
  }

  /**
   * 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;
  }
}

