package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.service.ComptabiliteService;
import dev.lions.unionflow.server.api.dto.comptabilite.request.*;
import dev.lions.unionflow.server.api.dto.comptabilite.response.*;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import jakarta.inject.Inject;
import jakarta.annotation.PostConstruct;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.RetryService;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Bean JSF pour la gestion comptable
 * 
 * @author UnionFlow Team
 * @version 1.0
 */
@Named("comptabiliteBean")
@ViewScoped
public class ComptabiliteBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(ComptabiliteBean.class);
    
    @Inject
    @RestClient
    private ComptabiliteService comptabiliteService;
    
    @Inject
    ErrorHandlerService errorHandler;
    
    @Inject
    RetryService retryService;
    
    // Données
    private List<CompteComptableResponse> comptes = new ArrayList<>();
    private List<JournalComptableResponse> journaux = new ArrayList<>();
    private List<EcritureComptableResponse> ecritures = new ArrayList<>();

    // Sélections
    private CompteComptableResponse compteSelectionne;
    private JournalComptableResponse journalSelectionne;
    private EcritureComptableResponse ecritureSelectionnee;

    // Filtres
    private UUID organisationIdFiltre;
    private UUID journalIdFiltre;

    // Nouveaux éléments (pour les formulaires - on utilise les builders)
    private CreateCompteComptableRequest nouveauCompte = CreateCompteComptableRequest.builder().build();
    private CreateJournalComptableRequest nouveauJournal = CreateJournalComptableRequest.builder().build();
    private CreateEcritureComptableRequest nouvelleEcriture = CreateEcritureComptableRequest.builder().build();
    
    // Onglet actif
    private String ongletActif = "comptes";
    
    @PostConstruct
    public void init() {
        chargerComptes();
        chargerJournaux();
    }
    
    public void chargerComptes() {
        try {
            comptes = retryService.executeWithRetrySupplier(
                () -> comptabiliteService.listerComptes(),
                "chargement des comptes comptables"
            );
            LOG.infof("Comptes chargés: %d", comptes.size());
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des comptes");
            errorHandler.handleException(e, "lors du chargement des comptes comptables", null);
            comptes = new ArrayList<>();
        }
    }
    
    public void chargerJournaux() {
        try {
            journaux = retryService.executeWithRetrySupplier(
                () -> comptabiliteService.listerJournaux(),
                "chargement des journaux comptables"
            );
            LOG.infof("Journaux chargés: %d", journaux.size());
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des journaux");
            errorHandler.handleException(e, "lors du chargement des journaux comptables", null);
            journaux = new ArrayList<>();
        }
    }
    
    public void chargerEcritures() {
        try {
            if (journalIdFiltre != null) {
                ecritures = retryService.executeWithRetrySupplier(
                    () -> comptabiliteService.listerEcrituresParJournal(journalIdFiltre),
                    "chargement des écritures par journal"
                );
            } else if (organisationIdFiltre != null) {
                ecritures = retryService.executeWithRetrySupplier(
                    () -> comptabiliteService.listerEcrituresParOrganisation(organisationIdFiltre),
                    "chargement des écritures par organisation"
                );
            } else {
                ecritures = new ArrayList<>();
            }
            LOG.infof("Écritures chargées: %d", ecritures.size());
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des écritures");
            errorHandler.handleException(e, "lors du chargement des écritures comptables", null);
            ecritures = new ArrayList<>();
        }
    }
    
    /**
     * Crée un nouveau compte comptable via le backend (DRY/WOU - réutilise ComptabiliteService)
     */
    public void creerCompte() {
        try {
            CompteComptableResponse compteCree = retryService.executeWithRetrySupplier(
                () -> comptabiliteService.creerCompte(nouveauCompte),
                "création d'un compte comptable"
            );
            // Recharger depuis le backend pour avoir les données complètes (DRY/WOU)
            chargerComptes();
            nouveauCompte = CreateCompteComptableRequest.builder().build();
            LOG.infof("Compte créé: %s", compteCree.getNumeroCompte());
            errorHandler.showSuccess("Succès", "Compte créé avec succès");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la création du compte");
            errorHandler.handleException(e, "lors de la création d'un compte comptable", null);
        }
    }
    
    /**
     * Crée un nouveau journal comptable via le backend (DRY/WOU - réutilise ComptabiliteService)
     */
    public void creerJournal() {
        try {
            JournalComptableResponse journalCree = retryService.executeWithRetrySupplier(
                () -> comptabiliteService.creerJournal(nouveauJournal),
                "création d'un journal comptable"
            );
            // Recharger depuis le backend pour avoir les données complètes (DRY/WOU)
            chargerJournaux();
            nouveauJournal = CreateJournalComptableRequest.builder().build();
            LOG.infof("Journal créé: %s", journalCree.getCode());
            errorHandler.showSuccess("Succès", "Journal créé avec succès");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la création du journal");
            errorHandler.handleException(e, "lors de la création d'un journal comptable", null);
        }
    }
    
    /**
     * Crée une nouvelle écriture comptable via le backend (DRY/WOU - réutilise ComptabiliteService)
     */
    public void creerEcriture() {
        try {
            EcritureComptableResponse ecritureCreee = retryService.executeWithRetrySupplier(
                () -> comptabiliteService.creerEcriture(nouvelleEcriture),
                "création d'une écriture comptable"
            );
            // Recharger depuis le backend pour avoir les données complètes (DRY/WOU)
            chargerEcritures();
            nouvelleEcriture = CreateEcritureComptableRequest.builder().build();
            LOG.infof("Écriture créée: %s", ecritureCreee.getId());
            errorHandler.showSuccess("Succès", "Écriture créée avec succès");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la création de l'écriture");
            errorHandler.handleException(e, "lors de la création d'une écriture comptable", null);
        }
    }
    
    public void voirDetailsCompte() {
        if (compteSelectionne != null) {
            try {
                compteSelectionne = retryService.executeWithRetrySupplier(
                    () -> comptabiliteService.obtenirCompte(compteSelectionne.getId()),
                    "récupération des détails d'un compte"
                );
            } catch (Exception e) {
                LOG.errorf(e, "Erreur lors de la récupération du compte");
                errorHandler.handleException(e, "lors de la récupération d'un compte comptable", null);
            }
        }
    }
    
    public void voirDetailsJournal() {
        if (journalSelectionne != null) {
            try {
                journalSelectionne = retryService.executeWithRetrySupplier(
                    () -> comptabiliteService.obtenirJournal(journalSelectionne.getId()),
                    "récupération des détails d'un journal"
                );
                chargerEcritures();
            } catch (Exception e) {
                LOG.errorf(e, "Erreur lors de la récupération du journal");
                errorHandler.handleException(e, "lors de la récupération d'un journal comptable", null);
            }
        }
    }
    
    // Getters et Setters
    public List<CompteComptableResponse> getComptes() { return comptes; }
    public void setComptes(List<CompteComptableResponse> comptes) { this.comptes = comptes; }
    
    public List<JournalComptableResponse> getJournaux() { return journaux; }
    public void setJournaux(List<JournalComptableResponse> journaux) { this.journaux = journaux; }
    
    public List<EcritureComptableResponse> getEcritures() { return ecritures; }
    public void setEcritures(List<EcritureComptableResponse> ecritures) { this.ecritures = ecritures; }
    
    public CompteComptableResponse getCompteSelectionne() { return compteSelectionne; }
    public void setCompteSelectionne(CompteComptableResponse compteSelectionne) { this.compteSelectionne = compteSelectionne; }
    
    public JournalComptableResponse getJournalSelectionne() { return journalSelectionne; }
    public void setJournalSelectionne(JournalComptableResponse journalSelectionne) { this.journalSelectionne = journalSelectionne; }
    
    public EcritureComptableResponse getEcritureSelectionnee() { return ecritureSelectionnee; }
    public void setEcritureSelectionnee(EcritureComptableResponse ecritureSelectionnee) { this.ecritureSelectionnee = ecritureSelectionnee; }
    
    public UUID getOrganisationIdFiltre() { return organisationIdFiltre; }
    public void setOrganisationIdFiltre(UUID organisationIdFiltre) { 
        this.organisationIdFiltre = organisationIdFiltre;
        chargerEcritures();
    }
    
    public UUID getJournalIdFiltre() { return journalIdFiltre; }
    public void setJournalIdFiltre(UUID journalIdFiltre) { 
        this.journalIdFiltre = journalIdFiltre;
        chargerEcritures();
    }
    
    public CreateCompteComptableRequest getNouveauCompte() { return nouveauCompte; }
    public void setNouveauCompte(CreateCompteComptableRequest nouveauCompte) { this.nouveauCompte = nouveauCompte; }

    public CreateJournalComptableRequest getNouveauJournal() { return nouveauJournal; }
    public void setNouveauJournal(CreateJournalComptableRequest nouveauJournal) { this.nouveauJournal = nouveauJournal; }

    public CreateEcritureComptableRequest getNouvelleEcriture() { return nouvelleEcriture; }
    public void setNouvelleEcriture(CreateEcritureComptableRequest nouvelleEcriture) { this.nouvelleEcriture = nouvelleEcriture; }
    
    public String getOngletActif() { return ongletActif; }
    public void setOngletActif(String ongletActif) { 
        this.ongletActif = ongletActif;
        if ("ecritures".equals(ongletActif)) {
            chargerEcritures();
        }
    }
    
}

