package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.service.EpargneService;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.CompteEpargneRequest;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.CompteEpargneResponse;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.TransactionEpargneRequest;
import dev.lions.unionflow.server.api.dto.mutuelle.epargne.TransactionEpargneResponse;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne;
import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import lombok.Data;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

@Named("epargneBean")
@SessionScoped
@Data
public class EpargneBean implements Serializable {

    private static final Logger LOGGER = Logger.getLogger(EpargneBean.class.getName());

    @Inject
    @RestClient
    private EpargneService epargneService;

    @Inject
    private UserSession userSession;

    private List<CompteEpargneResponse> mesComptes = new ArrayList<>();
    private List<CompteEpargneResponse> comptesOrganisation = new ArrayList<>();
    private CompteEpargneResponse compteSelectionne;

    private List<TransactionEpargneResponse> transactions = new ArrayList<>();
    private int pageTransactions = 0;
    private int tailleTransactions = 20;
    private boolean plusDeTransactions = true;

    private OuvertureCompte ouvertureCompte = new OuvertureCompte();
    private NouvelleTransaction nouvelleTransaction = new NouvelleTransaction();

    private int pageComptes = 0;
    private int tailleComptes = 20;

    private String getOrgId() {
        return userSession.getEntite() != null && userSession.getEntite().getId() != null
            ? userSession.getEntite().getId().toString() : null;
    }

    @PostConstruct
    public void init() {
        chargerMesComptes();
    }

    public void chargerMesComptes() {
        try {
            mesComptes = epargneService.obtenirMesComptes();
        } catch (Exception e) {
            LOGGER.severe("Erreur chargement comptes épargne: " + e.getMessage());
            mesComptes = new ArrayList<>();
            ajouterMessageErreur("Impossible de charger vos comptes d'épargne.");
        }
    }

    public void chargerComptesOrganisation() {
        try {
            String orgId = getOrgId();
            if (orgId != null) {
                comptesOrganisation = epargneService.obtenirComptesParOrganisation(orgId, pageComptes, tailleComptes);
            }
        } catch (Exception e) {
            LOGGER.severe("Erreur chargement comptes organisation: " + e.getMessage());
            comptesOrganisation = new ArrayList<>();
            ajouterMessageErreur("Impossible de charger les comptes de l'organisation.");
        }
    }

    public void selectionnerCompte(CompteEpargneResponse compte) {
        this.compteSelectionne = compte;
        this.pageTransactions = 0;
        this.transactions = new ArrayList<>();
        chargerTransactions();
    }

    public void chargerTransactions() {
        if (compteSelectionne == null) return;
        try {
            List<TransactionEpargneResponse> nouvelles = epargneService.obtenirTransactions(
                    compteSelectionne.getNumeroCompte(), pageTransactions, tailleTransactions);
            transactions.addAll(nouvelles);
            plusDeTransactions = nouvelles.size() == tailleTransactions;
        } catch (Exception e) {
            LOGGER.severe("Erreur chargement transactions: " + e.getMessage());
            ajouterMessageErreur("Impossible de charger l'historique des transactions.");
        }
    }

    public void chargerPlusDeTransactions() {
        pageTransactions++;
        chargerTransactions();
    }

    public void ouvrirCompte() {
        try {
            CompteEpargneRequest request = CompteEpargneRequest.builder()
                .membreId(ouvertureCompte.membreId)
                .organisationId(getOrgId())
                .typeCompte(TypeCompteEpargne.valueOf(ouvertureCompte.typeCompte))
                .notesOuverture(ouvertureCompte.notes)
                .build();
            CompteEpargneResponse cree = epargneService.ouvrirCompte(request);
            mesComptes.add(0, cree);
            ouvertureCompte = new OuvertureCompte();
            ajouterMessageSucces("Compte d'épargne ouvert : " + cree.getNumeroCompte());
        } catch (Exception e) {
            LOGGER.severe("Erreur ouverture compte: " + e.getMessage());
            ajouterMessageErreur("Impossible d'ouvrir le compte d'épargne.");
        }
    }

    public void executerTransaction() {
        if (compteSelectionne == null) {
            ajouterMessageErreur("Sélectionnez un compte.");
            return;
        }
        if (nouvelleTransaction.montant == null || nouvelleTransaction.montant.compareTo(BigDecimal.ZERO) <= 0) {
            ajouterMessageErreur("Le montant doit être supérieur à 0.");
            return;
        }
        try {
            TransactionEpargneRequest request = TransactionEpargneRequest.builder()
                .compteId(compteSelectionne.getNumeroCompte())
                .typeTransaction(TypeTransactionEpargne.valueOf(nouvelleTransaction.type))
                .montant(nouvelleTransaction.montant)
                .motif(nouvelleTransaction.motif)
                .origineFonds(nouvelleTransaction.origineFonds)
                .build();
            TransactionEpargneResponse result = epargneService.executerTransaction(request);
            transactions.add(0, result);
            compteSelectionne = epargneService.obtenirCompte(compteSelectionne.getNumeroCompte());
            nouvelleTransaction = new NouvelleTransaction();
            ajouterMessageSucces("Transaction effectuée avec succès.");
        } catch (Exception e) {
            LOGGER.severe("Erreur transaction épargne: " + e.getMessage());
            ajouterMessageErreur("Impossible d'effectuer la transaction.");
        }
    }

    public void changerStatutCompte(CompteEpargneResponse compte, String nouveauStatut) {
        try {
            epargneService.changerStatut(compte.getNumeroCompte(), nouveauStatut);
            chargerComptesOrganisation();
            ajouterMessageSucces("Statut mis à jour : " + nouveauStatut);
        } catch (Exception e) {
            ajouterMessageErreur("Impossible de modifier le statut.");
        }
    }

    public void actualiser() {
        chargerMesComptes();
        if (compteSelectionne != null) {
            pageTransactions = 0;
            transactions = new ArrayList<>();
            chargerTransactions();
        }
    }

    public String getStatutSeverity(String statut) {
        if (statut == null) return "info";
        return switch (statut) {
            case "ACTIF" -> "success";
            case "BLOQUE", "EN_CLOTURE" -> "warning";
            case "CLOTURE" -> "danger";
            default -> "info";
        };
    }

    public String getTypeTransactionIcon(String type) {
        if (type == null) return "pi-exchange text-600";
        return switch (type) {
            case "DEPOT", "TRANSFERT_ENTRANT", "LIBERATION_GARANTIE" -> "pi-arrow-down text-green-500";
            case "RETRAIT", "TRANSFERT_SORTANT", "PRELEVEMENT_FRAIS", "RETENUE_GARANTIE" -> "pi-arrow-up text-red-500";
            case "PAIEMENT_INTERETS" -> "pi-percentage text-blue-500";
            case "REMBOURSEMENT_CREDIT" -> "pi-credit-card text-orange-500";
            default -> "pi-exchange text-600";
        };
    }

    public boolean isRequiertOrigineFonds(BigDecimal montant) {
        return montant != null && montant.compareTo(new BigDecimal("500000")) >= 0;
    }

    private void ajouterMessageSucces(String detail) {
        FacesContext.getCurrentInstance().addMessage(null,
            new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", detail));
    }

    private void ajouterMessageErreur(String detail) {
        FacesContext.getCurrentInstance().addMessage(null,
            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", detail));
    }

    @Data
    public static class OuvertureCompte {
        private String membreId;
        private String typeCompte = "EPARGNE_LIBRE";
        private String notes;
    }

    @Data
    public static class NouvelleTransaction {
        private String type = "DEPOT";
        private BigDecimal montant;
        private String motif;
        private String origineFonds;
    }
}
