package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.client.AdminRoleServiceClient;
import dev.lions.unionflow.server.client.AdminUserServiceClient;
import dev.lions.unionflow.server.client.RoleServiceClient;
import dev.lions.user.manager.dto.role.RoleDTO;
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 jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Service admin pour la gestion des utilisateurs Keycloak (proxy vers lions-user-manager).
 * Réservé aux utilisateurs avec rôle SUPER_ADMIN.
 */
@ApplicationScoped
public class AdminUserService {

    private static final Logger LOG = Logger.getLogger(AdminUserService.class);
    private static final String DEFAULT_REALM = "unionflow";

    @Inject
    @RestClient
    AdminUserServiceClient userServiceClient;

    @Inject
    @RestClient
    AdminRoleServiceClient roleServiceClient;

    public UserSearchResultDTO searchUsers(int page, int size, String searchTerm) {
        UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
            .realmName(DEFAULT_REALM)
            .page(page)
            .pageSize(size)
            .searchTerm(searchTerm != null && !searchTerm.isBlank() ? searchTerm : null)
            .includeRoles(true)
            .sortBy("username")
            .sortOrder("ASC")
            .build();
        return userServiceClient.searchUsers(criteria);
    }

    public UserDTO getUserById(String userId) {
        return userServiceClient.getUserById(userId, DEFAULT_REALM);
    }

    public List<RoleDTO> getRealmRoles() {
        return roleServiceClient.getRealmRoles(DEFAULT_REALM);
    }

    public List<RoleDTO> getUserRoles(String userId) {
        return roleServiceClient.getUserRealmRoles(userId, DEFAULT_REALM);
    }

    /**
     * Crée un nouvel utilisateur dans le realm (proxy vers lions-user-manager).
     */
    public UserDTO createUser(UserDTO user) {
        return userServiceClient.createUser(user, DEFAULT_REALM);
    }

    /**
     * Met à jour un utilisateur (proxy vers lions-user-manager).
     */
    public UserDTO updateUser(String userId, UserDTO user) {
        return userServiceClient.updateUser(userId, user, DEFAULT_REALM);
    }

    /**
     * Active ou désactive un utilisateur (met à jour uniquement le champ enabled).
     */
    public UserDTO updateUserEnabled(String userId, boolean enabled) {
        UserDTO existing = userServiceClient.getUserById(userId, DEFAULT_REALM);
        if (existing == null) {
            throw new IllegalArgumentException("Utilisateur non trouvé: " + userId);
        }
        existing.setEnabled(enabled);
        return userServiceClient.updateUser(userId, existing, DEFAULT_REALM);
    }

    /**
     * Met à jour les rôles realm d'un utilisateur : assigne les nouveaux, révoque les retirés.
     */
    public void setUserRoles(String userId, List<String> targetRoleNames) {
        List<String> currentNames = getUserRoles(userId).stream()
            .map(RoleDTO::getName)
            .collect(Collectors.toList());
        List<String> toAssign = new ArrayList<>(targetRoleNames != null ? targetRoleNames : List.of());
        toAssign.removeAll(currentNames);
        List<String> toRevoke = new ArrayList<>(currentNames);
        toRevoke.removeAll(targetRoleNames == null ? List.of() : targetRoleNames);

        if (!toAssign.isEmpty()) {
            roleServiceClient.assignRealmRoles(userId, DEFAULT_REALM,
                new RoleServiceClient.RoleNamesRequest(toAssign));
        }
        if (!toRevoke.isEmpty()) {
            roleServiceClient.revokeRealmRoles(userId, DEFAULT_REALM,
                new RoleServiceClient.RoleNamesRequest(toRevoke));
        }
    }
}
