package dev.lions.user.manager.client.view;

import dev.lions.user.manager.client.service.RealmServiceClient;
import dev.lions.user.manager.client.service.UserServiceClient;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import dev.lions.user.manager.enums.user.StatutUser;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.event.ActionEvent;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import lombok.Data;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.primefaces.PrimeFaces;
import org.primefaces.event.data.PageEvent;
import org.primefaces.model.FilterMeta;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortMeta;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

/**
 * Bean JSF pour la liste et la recherche d'utilisateurs
 * 
 * @author Lions User Manager
 * @version 1.0.0
 */
@Named("userListBean")
@ViewScoped
@Data
public class UserListBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = Logger.getLogger(UserListBean.class.getName());

    // Constantes de navigation outcomes (WOU/DRY - réutilisables)
    private static final String OUTCOME_USER_PROFILE = "userProfilePage";
    private static final String OUTCOME_USER_EDIT = "userEditPage";
    private static final String OUTCOME_USER_CREATE = "userCreatePage";

    @Inject
    @RestClient
    private UserServiceClient userServiceClient;

    @Inject
    @RestClient
    private RealmServiceClient realmServiceClient;

    // Propriétés pour la liste
    private LazyDataModel<UserDTO> users;
    private UserDTO selectedUser;
    private List<UserDTO> selectedUsers = new ArrayList<>();

    // Propriétés pour la recherche
    private UserSearchCriteriaDTO searchCriteria = UserSearchCriteriaDTO.builder().build();
    private String searchText;
    // Par défaut, utiliser le realm lions-user-manager où les utilisateurs sont
    // configurés
    private String realmName = "lions-user-manager";
    private StatutUser selectedStatut;

    // Propriétés pour la pagination
    private int currentPage = 0;
    private int pageSize = 20;
    private long totalRecords = 0;
    private int totalPages = 0;

    // Options pour les selects
    private List<StatutUser> statutOptions = List.of(StatutUser.values());
    private List<String> availableRealms = new ArrayList<>();

    // Champs pour réinitialisation mot de passe
    private String newPassword;
    private String newPasswordConfirm;

    @PostConstruct
    public void init() {
        LOGGER.info("Initialisation de UserListBean");
        loadRealms();

        users = new LazyDataModel<UserDTO>() {
            @Override
            public String getRowKey(UserDTO user) {
                return user.getId();
            }

            @Override
            public UserDTO getRowData(String rowKey) {
                List<UserDTO> list = (List<UserDTO>) getWrappedData();
                if (list != null) {
                    for (UserDTO user : list) {
                        if (user.getId().equals(rowKey)) {
                            return user;
                        }
                    }
                }
                return null;
            }

            @Override
            public int count(Map<String, FilterMeta> filterBy) {
                return (int) totalRecords;
            }

            @Override
            public List<UserDTO> load(int first, int pageSize, Map<String, SortMeta> sortBy,
                    Map<String, FilterMeta> filterBy) {
                try {
                    int page = first / pageSize;

                    UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
                            .realmName(realmName)
                            .searchTerm(searchText)
                            .statut(selectedStatut)
                            .page(page)
                            .pageSize(pageSize)
                            .build();

                    UserSearchResultDTO result = userServiceClient.searchUsers(criteria);
                    List<UserDTO> data = result.getUsers() != null ? result.getUsers() : new ArrayList<>();

                    long total = result.getTotalCount() != null ? result.getTotalCount() : 0;
                    this.setRowCount((int) total);
                    totalRecords = total;

                    return data;
                } catch (Exception e) {
                    LOGGER.severe("Erreur loading: " + e.getMessage());
                    return new ArrayList<>();
                }
            }
        };
    }

    /**
     * Charger la liste des utilisateurs
     * (Deprecated: Utiliser LazyDataModel)
     */
    public void loadUsers() {
        // La méthode load du LazyDataModel est appelée automatiquement par le composant
    }

    /**
     * Rechercher des utilisateurs
     */
    public void search() {
        currentPage = 0;
        if (PrimeFaces.current().isAjaxRequest()) {
            PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);");
        }
    }

    /**
     * Réinitialiser la recherche
     */
    public void resetSearch() {
        searchText = null;
        selectedStatut = null;
        currentPage = 0;
        if (PrimeFaces.current().isAjaxRequest()) {
            PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);");
        }
    }

    /**
     * Réinitialiser le mot de passe
     */
    public void resetPassword(String userId) {
        if (newPassword != null && !newPassword.isEmpty() && newPassword.equals(newPasswordConfirm)) {
            try {
                // Utilisation du DTO pour la demande de réinitialisation
                dev.lions.user.manager.dto.user.PasswordResetRequestDTO request = new dev.lions.user.manager.dto.user.PasswordResetRequestDTO(
                        newPassword, false);
                userServiceClient.resetPassword(userId, realmName, request);
                addSuccessMessage("Mot de passe réinitialisé avec succès");
                // Clear fields
                newPassword = null;
                newPasswordConfirm = null;
            } catch (Exception e) {
                LOGGER.severe("Erreur lors de la réinitialisation du mot de passe: " + e.getMessage());
                addErrorMessage("Erreur lors de la réinitialisation: " + e.getMessage());
            }
        } else {
            addErrorMessage("Les mots de passe sont invalides ou ne correspondent pas");
        }
    }

    /**
     * Action pour activer un utilisateur (utilisé par le composant composite)
     */
    public void activateUserAction(ActionEvent event) {
        String userId = (String) event.getComponent().getAttributes().get("userId");
        if (userId != null) {
            activateUser(userId);
        }
    }

    /**
     * Action pour désactiver un utilisateur (utilisé par le composant composite)
     */
    public void deactivateUserAction(ActionEvent event) {
        String userId = (String) event.getComponent().getAttributes().get("userId");
        if (userId != null) {
            deactivateUser(userId);
        }
    }

    /**
     * Action pour supprimer un utilisateur (utilisé par le composant composite)
     */
    public void deleteUserAction(ActionEvent event) {
        String userId = (String) event.getComponent().getAttributes().get("userId");
        if (userId != null) {
            deleteUser(userId);
        }
    }

    /**
     * Activer un utilisateur
     */
    public void activateUser(String userId) {
        try {
            userServiceClient.activateUser(userId, realmName);
            addSuccessMessage("Utilisateur activé avec succès");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de l'activation: " + e.getMessage());
            addErrorMessage("Erreur lors de l'activation: " + e.getMessage());
        }
    }

    /**
     * Désactiver un utilisateur
     */
    public void deactivateUser(String userId) {
        try {
            userServiceClient.deactivateUser(userId, realmName, "Désactivé par l'administrateur");
            addSuccessMessage("Utilisateur désactivé avec succès");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de la désactivation: " + e.getMessage());
            addErrorMessage("Erreur lors de la désactivation: " + e.getMessage());
        }
    }

    /**
     * Supprimer un utilisateur
     */
    public void deleteUser(String userId) {
        try {
            userServiceClient.deleteUser(userId, realmName, false);
            addSuccessMessage("Utilisateur supprimé avec succès");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de la suppression: " + e.getMessage());
            addErrorMessage("Erreur lors de la suppression: " + e.getMessage());
        }
    }

    /**
     * Déconnecter toutes les sessions d'un utilisateur
     */
    public void logoutAllSessions(String userId) {
        try {
            userServiceClient.logoutAllSessions(userId, realmName);
            addSuccessMessage("Toutes les sessions ont été déconnectées");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage());
            addErrorMessage("Erreur lors de la déconnexion: " + e.getMessage());
        }
    }

    /**
     * Obtenir le nombre d'utilisateurs actifs
     */
    public long getActiveUsersCount() {
        return calculateStatusCount(true);
    }

    /**
     * Obtenir le nombre d'utilisateurs désactivés
     */
    public long getDisabledUsersCount() {
        return calculateStatusCount(false);
    }

    // Helper for counts
    private long calculateStatusCount(boolean enabled) {
        if (users == null)
            return 0;
        List<UserDTO> list = (List<UserDTO>) users.getWrappedData();
        if (list == null || list.isEmpty()) {
            return 0;
        }
        return list.stream()
                .filter(user -> user.getEnabled() != null && user.getEnabled() == enabled)
                .count();
    }

    /**
     * Obtenir le pourcentage d'utilisateurs actifs
     */
    public int getActiveUsersPercentage() {
        if (totalRecords == 0) {
            return 0;
        }
        return (int) Math.round((double) getActiveUsersCount() / totalRecords * 100);
    }

    /**
     * Obtenir le pourcentage d'utilisateurs désactivés
     */
    public int getDisabledUsersPercentage() {
        if (totalRecords == 0) {
            return 0;
        }
        return (int) Math.round((double) getDisabledUsersCount() / totalRecords * 100);
    }

    /**
     * Rafraîchir les données
     */
    public void refreshData() {
        loadUsers();
        addSuccessMessage("Données rafraîchies");
    }

    /**
     * Exporter vers CSV (placeholder)
     */
    public void exportToCSV() {
        addSuccessMessage("Fonctionnalité d'export en cours de développement");
    }

    /**
     * Importer des utilisateurs (placeholder)
     */
    public void importUsers() {
        addSuccessMessage("Fonctionnalité d'import en cours de développement");
    }

    /**
     * Charger les realms disponibles
     */
    /**
     * Charger les realms disponibles depuis Keycloak
     */
    private void loadRealms() {
        try {
            availableRealms = realmServiceClient.getAllRealms();
            LOGGER.info("Realms chargés: " + availableRealms);
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage());
            // Fallback en cas d'erreur
            availableRealms = List.of("master", "lions-user-manager", "btpxpress", "unionflow");
        }
    }

    /**
     * Navigation vers le profil utilisateur
     */
    public String goToUserProfile() {
        return OUTCOME_USER_PROFILE;
    }

    /**
     * Navigation vers l'édition utilisateur
     */
    public String goToUserEdit() {
        return OUTCOME_USER_EDIT;
    }

    /**
     * Navigation vers la création utilisateur
     */
    public String goToUserCreate() {
        return OUTCOME_USER_CREATE;
    }

    // Méthodes utilitaires pour les messages
    private void addSuccessMessage(String message) {
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message));
    }

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