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

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.view.ViewScoped;
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.util.ArrayList;
import java.util.List;
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;

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

    // Propriétés pour la recherche
    private UserSearchCriteriaDTO searchCriteria = UserSearchCriteriaDTO.builder().build();
    private String searchText;
    private String realmName = "master";
    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<>();

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

    /**
     * Charger la liste des utilisateurs
     */
    public void loadUsers() {
        try {
            UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
                .realmName(realmName)
                .page(currentPage)
                .pageSize(pageSize)
                .build();

            UserSearchResultDTO result = userServiceClient.searchUsers(criteria);
            this.users = result.getUsers() != null ? result.getUsers() : new ArrayList<>();
            this.totalRecords = result.getTotalCount() != null ? result.getTotalCount() : 0;
            this.totalPages = (int) Math.ceil((double) totalRecords / pageSize);

            LOGGER.info("Chargement de " + users.size() + " utilisateurs");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des utilisateurs: " + e.getMessage());
            addErrorMessage("Erreur lors du chargement des utilisateurs: " + e.getMessage());
        }
    }

    /**
     * Rechercher des utilisateurs
     */
    public void search() {
        try {
            currentPage = 0; // Réinitialiser à la première page

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

            UserSearchResultDTO result = userServiceClient.searchUsers(criteria);
            this.users = result.getUsers() != null ? result.getUsers() : new ArrayList<>();
            this.totalRecords = result.getTotalCount() != null ? result.getTotalCount() : 0;
            this.totalPages = (int) Math.ceil((double) totalRecords / pageSize);

            addSuccessMessage("Recherche effectuée: " + totalRecords + " résultat(s) trouvé(s)");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de la recherche: " + e.getMessage());
            addErrorMessage("Erreur lors de la recherche: " + e.getMessage());
        }
    }

    /**
     * Réinitialiser la recherche
     */
    public void resetSearch() {
        searchText = null;
        selectedStatut = null;
        currentPage = 0;
        loadUsers();
    }

    /**
     * Activer un utilisateur
     */
    public void activateUser(String userId) {
        try {
            userServiceClient.activateUser(userId, realmName);
            addSuccessMessage("Utilisateur activé avec succès");
            loadUsers();
        } 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);
            addSuccessMessage("Utilisateur désactivé avec succès");
            loadUsers();
        } 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);
            addSuccessMessage("Utilisateur supprimé avec succès");
            loadUsers();
        } 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() {
        if (users == null || users.isEmpty()) {
            return 0;
        }
        return users.stream()
            .filter(user -> user.getEnabled() != null && user.getEnabled())
            .count();
    }

    /**
     * Obtenir le nombre d'utilisateurs désactivés
     */
    public long getDisabledUsersCount() {
        if (users == null || users.isEmpty()) {
            return 0;
        }
        return users.stream()
            .filter(user -> user.getEnabled() != null && !user.getEnabled())
            .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);
    }

    /**
     * Charger les realms disponibles
     */
    private void loadRealms() {
        // TODO: Implémenter la récupération des realms depuis Keycloak
        availableRealms = List.of("master", "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));
    }
}

