package dev.lions.user.manager.service.impl;

import dev.lions.user.manager.client.KeycloakAdminClient;
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.mapper.UserMapper;
import dev.lions.user.manager.service.UserService;
import dev.lions.user.manager.service.exception.KeycloakServiceException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;

import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Implémentation du service de gestion des utilisateurs
 * Utilise UNIQUEMENT l'API Admin Keycloak (ZERO accès direct à la DB Keycloak)
 */
@ApplicationScoped
@Slf4j
public class UserServiceImpl implements UserService {

    @Inject
    KeycloakAdminClient keycloakAdminClient;

    @Override
    public UserSearchResultDTO searchUsers(@Valid @NotNull UserSearchCriteriaDTO criteria) {
        log.info("Recherche d'utilisateurs avec critères: {}", criteria);

        try {
            String realmName = criteria.getRealmName();
            UsersResource usersResource = keycloakAdminClient.getUsers(realmName);

            // Construire la requête de recherche
            List<UserRepresentation> users;

            if (criteria.getSearchTerm() != null && !criteria.getSearchTerm().isBlank()) {
                // Recherche globale
                users = usersResource.search(
                        criteria.getSearchTerm(),
                        criteria.getOffset(),
                        criteria.getPageSize());
            } else if (criteria.getUsername() != null) {
                // Recherche par username exact
                users = usersResource.search(
                        criteria.getUsername(),
                        criteria.getOffset(),
                        criteria.getPageSize(),
                        true // exact match
                );
            } else if (criteria.getEmail() != null) {
                // Recherche par email
                users = usersResource.searchByEmail(
                        criteria.getEmail(),
                        true // exact match
                );
            } else {
                // Liste tous les utilisateurs
                users = usersResource.list(
                        criteria.getOffset(),
                        criteria.getPageSize());
            }

            // Filtrer selon les critères supplémentaires
            users = filterUsers(users, criteria);

            // Convertir en DTOs
            List<UserDTO> userDTOs = UserMapper.toDTOList(users, realmName);

            // Compter le total
            long totalCount = usersResource.count();

            // Construire le résultat paginé
            return UserSearchResultDTO.of(userDTOs, criteria, totalCount);

        } catch (Exception e) {
            log.error("Erreur lors de la recherche d'utilisateurs", e);
            handleConnectionException(e, "recherche d'utilisateurs");
            return null; // Ne sera jamais atteint car handleConnectionException lance une exception
        }
    }

    @Override
    public Optional<UserDTO> getUserById(@NotBlank String userId, @NotBlank String realmName) {
        log.info("Récupération de l'utilisateur {} dans le realm {}", userId, realmName);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);
            UserRepresentation userRep = userResource.toRepresentation();
            UserDTO userDTO = UserMapper.toDTO(userRep, realmName);

            // Récupérer les rôles realm de l'utilisateur
            try {
                List<RoleRepresentation> realmRoles = userResource.roles().realmLevel().listAll();
                if (realmRoles != null && !realmRoles.isEmpty()) {
                    List<String> roleNames = realmRoles.stream()
                            .map(RoleRepresentation::getName)
                            .collect(Collectors.toList());
                    userDTO.setRealmRoles(roleNames);
                }
            } catch (Exception e) {
                log.warn("Erreur lors de la récupération des rôles realm pour l'utilisateur {}: {}", userId,
                        e.getMessage());
                // Ne pas échouer si les rôles ne peuvent pas être récupérés
            }

            return Optional.of(userDTO);
        } catch (NotFoundException e) {
            log.warn("Utilisateur {} non trouvé dans le realm {}", userId, realmName);
            return Optional.empty();
        } catch (Exception e) {
            // Vérifier si l'exception contient un message indiquant un 404
            String errorMessage = e.getMessage();
            if (errorMessage != null && (errorMessage.contains("404") ||
                    errorMessage.contains("Server response is: 404") ||
                    errorMessage.contains("Received: 'Server response is: 404'"))) {
                log.warn("Utilisateur {} non trouvé dans le realm {} (404 détecté dans l'exception)", userId,
                        realmName);
                return Optional.empty();
            }
            log.error("Erreur lors de la récupération de l'utilisateur {}", userId, e);
            handleConnectionException(e, "récupération de l'utilisateur " + userId);
            return Optional.empty(); // Ne sera jamais atteint mais nécessaire pour le compilateur
        }
    }

    @Override
    public Optional<UserDTO> getUserByUsername(@NotBlank String username, @NotBlank String realmName) {
        log.info("Récupération de l'utilisateur par username {} dans le realm {}", username, realmName);

        try {
            List<UserRepresentation> users = keycloakAdminClient.getUsers(realmName)
                    .search(username, 0, 1, true);

            if (users == null) {
                log.warn("Liste d'utilisateurs null retournée pour username {} dans le realm {}", username, realmName);
                return Optional.empty();
            }

            if (users.isEmpty()) {
                return Optional.empty();
            }

            return Optional.of(UserMapper.toDTO(users.get(0), realmName));
        } catch (Exception e) {
            log.error("Erreur lors de la récupération de l'utilisateur par username {}", username, e);
            handleConnectionException(e, "récupération de l'utilisateur par username " + username);
            return Optional.empty(); // Ne sera jamais atteint mais nécessaire pour le compilateur
        }
    }

    @Override
    public Optional<UserDTO> getUserByEmail(@NotBlank String email, @NotBlank String realmName) {
        log.info("Récupération de l'utilisateur par email {} dans le realm {}", email, realmName);

        try {
            List<UserRepresentation> users = keycloakAdminClient.getUsers(realmName)
                    .searchByEmail(email, true);

            if (users == null) {
                log.warn("Liste d'utilisateurs null retournée pour email {} dans le realm {}", email, realmName);
                return Optional.empty();
            }

            if (users.isEmpty()) {
                return Optional.empty();
            }

            return Optional.of(UserMapper.toDTO(users.get(0), realmName));
        } catch (Exception e) {
            log.error("Erreur lors de la récupération de l'utilisateur par email {}", email, e);
            handleConnectionException(e, "récupération de l'utilisateur par email " + email);
            return Optional.empty(); // Ne sera jamais atteint mais nécessaire pour le compilateur
        }
    }

    @Override
    public UserDTO createUser(@Valid @NotNull UserDTO user, @NotBlank String realmName) {
        log.info("Création de l'utilisateur {} dans le realm {}", user.getUsername(), realmName);

        try {
            // Vérifier si l'utilisateur existe déjà
            if (usernameExists(user.getUsername(), realmName)) {
                throw new IllegalArgumentException("Le nom d'utilisateur existe déjà: " + user.getUsername());
            }

            if (user.getEmail() != null && emailExists(user.getEmail(), realmName)) {
                throw new IllegalArgumentException("L'email existe déjà: " + user.getEmail());
            }

            // Convertir DTO vers UserRepresentation
            UserRepresentation userRep = UserMapper.toRepresentation(user);

            // Créer l'utilisateur
            UsersResource usersResource = keycloakAdminClient.getUsers(realmName);
            Response response = usersResource.create(userRep);

            // Vérifier si la réponse est null (erreur de connexion)
            if (response == null) {
                log.error("❌ Réponse null lors de la création de l'utilisateur {} - Service Keycloak indisponible", user.getUsername());
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de se connecter au service Keycloak pour créer l'utilisateur: " + user.getUsername());
            }

            // Vérifier le code de statut HTTP
            int status = response.getStatus();
            if (status != Response.Status.CREATED.getStatusCode()) {
                String errorMessage = "Échec de la création de l'utilisateur";
                if (response.getStatusInfo() != null) {
                    errorMessage += ": " + response.getStatusInfo();
                }
                
                // Gérer les différents codes d'erreur HTTP
                if (status == 400) {
                    throw new KeycloakServiceException("Données invalides pour la création de l'utilisateur: " + errorMessage, status);
                } else if (status == 409) {
                    throw new IllegalArgumentException("L'utilisateur existe déjà (conflit détecté par Keycloak)");
                } else if (status == 503 || status == 502) {
                    throw new KeycloakServiceException.ServiceUnavailableException("Service Keycloak indisponible: " + errorMessage);
                } else {
                    throw new KeycloakServiceException(errorMessage, status);
                }
            }

            // Vérifier que la location est présente
            if (response.getLocation() == null) {
                log.error("❌ Location manquante dans la réponse de création pour l'utilisateur {}", user.getUsername());
                throw new KeycloakServiceException("Réponse invalide du service Keycloak: location manquante", status);
            }

            // Récupérer l'ID de l'utilisateur créé
            String userId = response.getLocation().getPath().replaceAll(".*/([^/]+)$", "$1");

            // Définir le mot de passe si fourni
            if (user.getTemporaryPassword() != null) {
                setPassword(userId, realmName, user.getTemporaryPassword(),
                        user.getTemporaryPasswordFlag() != null && user.getTemporaryPasswordFlag());
            }

            // Récupérer l'utilisateur créé
            UserResource userResource = usersResource.get(userId);
            UserRepresentation createdUser = userResource.toRepresentation();

            log.info("✅ Utilisateur créé avec succès: {} (ID: {})", user.getUsername(), userId);
            return UserMapper.toDTO(createdUser, realmName);

        } catch (IllegalArgumentException e) {
            // Répercuter les erreurs de validation
            throw e;
        } catch (KeycloakServiceException e) {
            // Répercuter les erreurs de service
            throw e;
        } catch (Exception e) {
            log.error("❌ Erreur lors de la création de l'utilisateur {}", user.getUsername(), e);
            handleConnectionException(e, "création de l'utilisateur " + user.getUsername());
            return null; // Ne sera jamais atteint car handleConnectionException lance une exception
        }
    }

    @Override
    public UserDTO updateUser(@NotBlank String userId, @Valid @NotNull UserDTO user, @NotBlank String realmName) {
        log.info("Mise à jour de l'utilisateur {} dans le realm {}", userId, realmName);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);

            // Vérifier si userResource est null (peut arriver si la connexion échoue)
            if (userResource == null) {
                log.error("❌ UserResource null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de se connecter au service Keycloak pour mettre à jour l'utilisateur: " + userId);
            }

            // Récupérer l'utilisateur existant
            UserRepresentation existingUser = userResource.toRepresentation();
            
            if (existingUser == null) {
                log.error("❌ UserRepresentation null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de récupérer les données de l'utilisateur depuis Keycloak: " + userId);
            }

            // Mettre à jour les champs
            if (user.getEmail() != null) {
                existingUser.setEmail(user.getEmail());
            }
            if (user.getPrenom() != null) {
                existingUser.setFirstName(user.getPrenom());
            }
            if (user.getNom() != null) {
                existingUser.setLastName(user.getNom());
            }
            if (user.getEnabled() != null) {
                existingUser.setEnabled(user.getEnabled());
            }
            if (user.getEmailVerified() != null) {
                existingUser.setEmailVerified(user.getEmailVerified());
            }
            if (user.getAttributes() != null) {
                existingUser.setAttributes(user.getAttributes());
            }

            // Envoyer la mise à jour
            userResource.update(existingUser);

            // Récupérer l'utilisateur mis à jour
            UserRepresentation updatedUser = userResource.toRepresentation();
            
            if (updatedUser == null) {
                log.error("❌ UserRepresentation null après mise à jour pour l'utilisateur {}", userId);
                throw new KeycloakServiceException("Impossible de récupérer l'utilisateur mis à jour", 500);
            }

            log.info("✅ Utilisateur mis à jour avec succès: {}", userId);
            return UserMapper.toDTO(updatedUser, realmName);

        } catch (NotFoundException e) {
            log.error("❌ Utilisateur {} non trouvé", userId);
            throw new KeycloakServiceException("Utilisateur non trouvé: " + userId, 404, e);
        } catch (KeycloakServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("❌ Erreur lors de la mise à jour de l'utilisateur {}", userId, e);
            handleConnectionException(e, "mise à jour de l'utilisateur " + userId);
            return null; // Ne sera jamais atteint car handleConnectionException lance une exception
        }
    }

    @Override
    public void deleteUser(@NotBlank String userId, @NotBlank String realmName, boolean hardDelete) {
        log.info("Suppression de l'utilisateur {} dans le realm {} (hard: {})", userId, realmName, hardDelete);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);
            
            if (userResource == null) {
                log.error("❌ UserResource null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de se connecter au service Keycloak pour supprimer l'utilisateur: " + userId);
            }

            if (hardDelete) {
                // Suppression définitive
                userResource.remove();
                log.info("✅ Utilisateur supprimé définitivement: {}", userId);
            } else {
                // Soft delete: désactiver l'utilisateur
                UserRepresentation user = userResource.toRepresentation();
                if (user == null) {
                    log.error("❌ UserRepresentation null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                    throw new KeycloakServiceException.ServiceUnavailableException(
                        "Impossible de récupérer les données de l'utilisateur depuis Keycloak: " + userId);
                }
                user.setEnabled(false);
                userResource.update(user);
                log.info("✅ Utilisateur désactivé (soft delete): {}", userId);
            }

        } catch (NotFoundException e) {
            log.error("❌ Utilisateur {} non trouvé", userId);
            throw new KeycloakServiceException("Utilisateur non trouvé: " + userId, 404, e);
        } catch (KeycloakServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("❌ Erreur lors de la suppression de l'utilisateur {}", userId, e);
            handleConnectionException(e, "suppression de l'utilisateur " + userId);
        }
    }

    @Override
    public void activateUser(@NotBlank String userId, @NotBlank String realmName) {
        log.info("Activation de l'utilisateur {} dans le realm {}", userId, realmName);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);
            
            if (userResource == null) {
                log.error("❌ UserResource null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de se connecter au service Keycloak pour activer l'utilisateur: " + userId);
            }
            
            UserRepresentation user = userResource.toRepresentation();
            
            if (user == null) {
                log.error("❌ UserRepresentation null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de récupérer les données de l'utilisateur depuis Keycloak: " + userId);
            }
            
            user.setEnabled(true);
            userResource.update(user);

            log.info("✅ Utilisateur activé: {}", userId);
        } catch (KeycloakServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("❌ Erreur lors de l'activation de l'utilisateur {}", userId, e);
            handleConnectionException(e, "activation de l'utilisateur " + userId);
        }
    }

    @Override
    public void deactivateUser(@NotBlank String userId, @NotBlank String realmName, String raison) {
        log.info("Désactivation de l'utilisateur {} dans le realm {} (raison: {})", userId, realmName, raison);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);
            
            if (userResource == null) {
                log.error("❌ UserResource null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de se connecter au service Keycloak pour désactiver l'utilisateur: " + userId);
            }
            
            UserRepresentation user = userResource.toRepresentation();
            
            if (user == null) {
                log.error("❌ UserRepresentation null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de récupérer les données de l'utilisateur depuis Keycloak: " + userId);
            }
            
            user.setEnabled(false);
            userResource.update(user);

            log.info("✅ Utilisateur désactivé: {}", userId);
        } catch (KeycloakServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("❌ Erreur lors de la désactivation de l'utilisateur {}", userId, e);
            handleConnectionException(e, "désactivation de l'utilisateur " + userId);
        }
    }

    @Override
    public void suspendUser(@NotBlank String userId, @NotBlank String realmName, String raison, int duree) {
        log.info("Suspension de l'utilisateur {} dans le realm {} (raison: {}, durée: {} jours)",
                userId, realmName, raison, duree);

        deactivateUser(userId, realmName, raison);
    }

    @Override
    public void unlockUser(@NotBlank String userId, @NotBlank String realmName) {
        log.info("Déverrouillage de l'utilisateur {} dans le realm {}", userId, realmName);
        activateUser(userId, realmName);
    }

    @Override
    public void resetPassword(@NotBlank String userId, @NotBlank String realmName,
            @NotBlank String temporaryPassword, boolean temporary) {
        log.info("Réinitialisation du mot de passe pour l'utilisateur {} (temporaire: {})", userId, temporary);

        setPassword(userId, realmName, temporaryPassword, temporary);
    }

    @Override
    public void sendVerificationEmail(@NotBlank String userId, @NotBlank String realmName) {
        log.info("Envoi d'un email de vérification à l'utilisateur {}", userId);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);
            
            if (userResource == null) {
                log.error("❌ UserResource null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de se connecter au service Keycloak pour envoyer l'email de vérification: " + userId);
            }
            
            userResource.sendVerifyEmail();

            log.info("✅ Email de vérification envoyé: {}", userId);
        } catch (KeycloakServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("❌ Erreur lors de l'envoi de l'email de vérification pour {}", userId, e);
            handleConnectionException(e, "envoi de l'email de vérification pour l'utilisateur " + userId);
        }
    }

    @Override
    public int logoutAllSessions(@NotBlank String userId, @NotBlank String realmName) {
        log.info("Déconnexion de toutes les sessions pour l'utilisateur {}", userId);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);
            
            if (userResource == null) {
                log.error("❌ UserResource null pour l'utilisateur {} - Service Keycloak indisponible", userId);
                throw new KeycloakServiceException.ServiceUnavailableException(
                    "Impossible de se connecter au service Keycloak pour déconnecter les sessions: " + userId);
            }
            
            int sessionsCount = userResource.getUserSessions() != null ? userResource.getUserSessions().size() : 0;
            userResource.logout();

            log.info("✅ {} sessions révoquées pour l'utilisateur {}", sessionsCount, userId);
            return sessionsCount;
        } catch (KeycloakServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("❌ Erreur lors de la déconnexion des sessions pour {}", userId, e);
            handleConnectionException(e, "déconnexion des sessions pour l'utilisateur " + userId);
            return 0; // Ne sera jamais atteint car handleConnectionException lance une exception
        }
    }

    @Override
    public List<String> getActiveSessions(@NotBlank String userId, @NotBlank String realmName) {
        log.info("Récupération des sessions actives pour l'utilisateur {}", userId);

        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);
            return userResource.getUserSessions().stream()
                    .map(session -> session.getId())
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("❌ Erreur lors de la récupération des sessions pour {}", userId, e);
            return Collections.emptyList();
        }
    }

    @Override
    public long countUsers(@NotNull UserSearchCriteriaDTO criteria) {
        try {
            return keycloakAdminClient.getUsers(criteria.getRealmName()).count();
        } catch (Exception e) {
            log.error("Erreur lors du comptage des utilisateurs", e);
            return 0;
        }
    }

    @Override
    public UserSearchResultDTO getAllUsers(@NotBlank String realmName, int page, int pageSize) {
        UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
                .realmName(realmName)
                .page(page)
                .pageSize(pageSize)
                .build();

        return searchUsers(criteria);
    }

    @Override
    public boolean usernameExists(@NotBlank String username, @NotBlank String realmName) {
        try {
            List<UserRepresentation> users = keycloakAdminClient.getUsers(realmName)
                    .search(username, 0, 1, true);
            return !users.isEmpty();
        } catch (Exception e) {
            log.error("Erreur lors de la vérification de l'existence du username {}", username, e);
            return false;
        }
    }

    @Override
    public boolean emailExists(@NotBlank String email, @NotBlank String realmName) {
        try {
            List<UserRepresentation> users = keycloakAdminClient.getUsers(realmName)
                    .searchByEmail(email, true);
            return !users.isEmpty();
        } catch (Exception e) {
            log.error("Erreur lors de la vérification de l'existence de l'email {}", email, e);
            return false;
        }
    }

    @Override
    public String exportUsersToCSV(@NotNull UserSearchCriteriaDTO criteria) {
        log.info("Export des utilisateurs en CSV pour le realm {}", criteria.getRealmName());

        // Disable pagination for export to get all users
        int originalPageSize = criteria.getPageSize();
        criteria.setPageSize(10000); // Set a large limit or handle pagination loops

        UserSearchResultDTO result = searchUsers(criteria);
        criteria.setPageSize(originalPageSize); // Restore

        StringBuilder csv = new StringBuilder();
        csv.append("username,email,firstName,lastName,enabled\n");

        for (UserDTO user : result.getUsers()) {
            csv.append(escape(user.getUsername())).append(",");
            csv.append(escape(user.getEmail())).append(",");
            csv.append(escape(user.getPrenom())).append(",");
            csv.append(escape(user.getNom())).append(",");
            csv.append(user.getEnabled() != null ? user.getEnabled() : true).append("\n");
        }

        return csv.toString();
    }

    @Override
    public dev.lions.user.manager.dto.importexport.ImportResultDTO importUsersFromCSV(@NotBlank String csvContent, @NotBlank String realmName) {
        log.info("Import des utilisateurs depuis CSV pour le realm {}", realmName);

        dev.lions.user.manager.dto.importexport.ImportResultDTO result = dev.lions.user.manager.dto.importexport.ImportResultDTO.builder()
            .totalLines(0)
            .successCount(0)
            .errorCount(0)
            .errors(new java.util.ArrayList<>())
            .build();

        String[] lines = csvContent.split("\\r?\\n");
        int startIndex = 0;

        // Skip header if present
        if (lines.length > 0 && lines[0].toLowerCase().startsWith("username")) {
            startIndex = 1;
        }

        result.setTotalLines(lines.length - startIndex);

        for (int i = startIndex; i < lines.length; i++) {
            int lineNumber = i + 1;
            String line = lines[i].trim();

            if (line.isEmpty()) {
                continue; // Ignore empty lines
            }

            try {
                // Parse CSV line
                String[] parts = parseCSVLine(line);
                if (parts.length < 5) {
                    result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                        .lineNumber(lineNumber)
                        .lineContent(line)
                        .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.INVALID_FORMAT)
                        .message("Nombre de colonnes insuffisant (attendu: 5, trouvé: " + parts.length + ")")
                        .build());
                    continue;
                }

                String username = CsvValidationHelper.clean(parts[0]);
                String email = CsvValidationHelper.clean(parts[1]);
                String firstName = CsvValidationHelper.clean(parts[2]);
                String lastName = CsvValidationHelper.clean(parts[3]);
                String enabledStr = CsvValidationHelper.clean(parts[4]);

                // Validate username
                String usernameError = CsvValidationHelper.validateUsername(username);
                if (usernameError != null) {
                    result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                        .lineNumber(lineNumber)
                        .lineContent(line)
                        .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.VALIDATION_ERROR)
                        .field("username")
                        .message(usernameError)
                        .build());
                    continue;
                }

                // Validate email
                String emailError = CsvValidationHelper.validateEmail(email);
                if (emailError != null) {
                    result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                        .lineNumber(lineNumber)
                        .lineContent(line)
                        .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.VALIDATION_ERROR)
                        .field("email")
                        .message(emailError)
                        .build());
                    continue;
                }

                // Validate firstName
                String firstNameError = CsvValidationHelper.validateName(firstName, "Prénom");
                if (firstNameError != null) {
                    result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                        .lineNumber(lineNumber)
                        .lineContent(line)
                        .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.VALIDATION_ERROR)
                        .field("firstName")
                        .message(firstNameError)
                        .build());
                    continue;
                }

                // Validate lastName
                String lastNameError = CsvValidationHelper.validateName(lastName, "Nom");
                if (lastNameError != null) {
                    result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                        .lineNumber(lineNumber)
                        .lineContent(line)
                        .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.VALIDATION_ERROR)
                        .field("lastName")
                        .message(lastNameError)
                        .build());
                    continue;
                }

                // Validate enabled
                String enabledError = CsvValidationHelper.validateBoolean(enabledStr);
                if (enabledError != null) {
                    result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                        .lineNumber(lineNumber)
                        .lineContent(line)
                        .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.VALIDATION_ERROR)
                        .field("enabled")
                        .message(enabledError)
                        .build());
                    continue;
                }

                boolean enabled = CsvValidationHelper.parseBoolean(enabledStr);

                // Check if user already exists
                try {
                    java.util.Optional<UserDTO> existingUser = getUserByUsername(username, realmName);
                    if (existingUser.isPresent()) {
                        result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                            .lineNumber(lineNumber)
                            .lineContent(line)
                            .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.DUPLICATE_USER)
                            .field("username")
                            .message("Utilisateur déjà existant: " + username)
                            .build());
                        continue;
                    }
                } catch (Exception e) {
                    // User doesn't exist, continue with creation
                }

                // Create user
                UserDTO userDTO = UserDTO.builder()
                    .username(username)
                    .email(email)
                    .prenom(firstName)
                    .nom(lastName)
                    .enabled(enabled)
                    .build();

                try {
                    createUser(userDTO, realmName);
                    result.setSuccessCount(result.getSuccessCount() + 1);
                    log.debug("✅ Utilisateur créé: {} (ligne {})", username, lineNumber);
                } catch (Exception e) {
                    result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                        .lineNumber(lineNumber)
                        .lineContent(line)
                        .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.CREATION_ERROR)
                        .message("Erreur lors de la création de l'utilisateur")
                        .details(e.getMessage())
                        .build());
                }

            } catch (Exception e) {
                log.error("Erreur inattendue lors du traitement de la ligne {}: {}", lineNumber, e.getMessage(), e);
                result.addError(dev.lions.user.manager.dto.importexport.ImportResultDTO.ImportErrorDTO.builder()
                    .lineNumber(lineNumber)
                    .lineContent(line)
                    .errorType(dev.lions.user.manager.dto.importexport.ImportResultDTO.ErrorType.SYSTEM_ERROR)
                    .message("Erreur système")
                    .details(e.getMessage())
                    .build());
            }
        }

        // Generate summary message
        result.generateMessage();
        log.info(result.getMessage());

        return result;
    }

    private String escape(String data) {
        if (data == null)
            return "";
        String escapedData = data.replaceAll("\"", "\"\"");
        if (escapedData.contains(",") || escapedData.contains("\n") || escapedData.contains("\"")) {
            return "\"" + escapedData + "\"";
        }
        return escapedData;
    }

    private String[] parseCSVLine(String line) {
        // Simple regex to split by comma but ignoring commas inside quotes
        // This regex handles: "value",value,"val,ue"
        String[] tokens = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
        for (int i = 0; i < tokens.length; i++) {
            String token = tokens[i].trim();
            if (token.startsWith("\"") && token.endsWith("\"")) {
                token = token.substring(1, token.length() - 1);
                token = token.replaceAll("\"\"", "\"");
            }
            tokens[i] = token;
        }
        return tokens;
    }

    // ==================== Méthodes privées ====================

    /**
     * Valide une réponse HTTP du service Keycloak.
     * 
     * @param response La réponse à valider
     * @param operation Nom de l'opération (pour les logs)
     * @param expectedStatus Le code de statut HTTP attendu
     * @throws KeycloakServiceException si la réponse est null ou a un code d'erreur
     */
    private void validateResponse(Response response, String operation, int expectedStatus) {
        if (response == null) {
            log.error("❌ Réponse null lors de l'opération {} - Service Keycloak indisponible", operation);
            throw new KeycloakServiceException.ServiceUnavailableException(
                "Impossible de se connecter au service Keycloak pour l'opération: " + operation);
        }

        int status = response.getStatus();
        if (status != expectedStatus) {
            String errorMessage = "Échec de l'opération: " + operation;
            if (response.getStatusInfo() != null) {
                errorMessage += " - " + response.getStatusInfo();
            }

            // Gérer les différents codes d'erreur HTTP
            if (status == 400) {
                throw new KeycloakServiceException("Données invalides: " + errorMessage, status);
            } else if (status == 401) {
                throw new KeycloakServiceException("Non autorisé: " + errorMessage, status);
            } else if (status == 403) {
                throw new KeycloakServiceException("Accès interdit: " + errorMessage, status);
            } else if (status == 404) {
                throw new KeycloakServiceException("Ressource non trouvée: " + errorMessage, status);
            } else if (status == 409) {
                throw new KeycloakServiceException("Conflit: " + errorMessage, status);
            } else if (status == 500) {
                throw new KeycloakServiceException("Erreur serveur interne Keycloak: " + errorMessage, status);
            } else if (status == 502 || status == 503) {
                throw new KeycloakServiceException.ServiceUnavailableException("Service Keycloak indisponible: " + errorMessage);
            } else if (status == 504) {
                throw new KeycloakServiceException.TimeoutException("Timeout lors de l'opération: " + operation);
            } else {
                throw new KeycloakServiceException(errorMessage, status);
            }
        }
    }

    /**
     * Gère les exceptions de connexion et les convertit en KeycloakServiceException appropriée.
     * 
     * @throws KeycloakServiceException toujours (lève une exception)
     */
    private void handleConnectionException(Exception e, String operation) throws KeycloakServiceException {
        String errorMessage = e.getMessage();
        
        if (e instanceof ConnectException || 
            e instanceof SocketTimeoutException ||
            (errorMessage != null && (errorMessage.contains("Connection") || 
                                      errorMessage.contains("timeout") ||
                                      errorMessage.contains("refused") ||
                                      errorMessage.contains("Unable to connect")))) {
            log.error("❌ Erreur de connexion au service Keycloak lors de l'opération {}", operation, e);
            throw new KeycloakServiceException.ServiceUnavailableException(
                "Erreur de connexion au service Keycloak: " + (errorMessage != null ? errorMessage : e.getClass().getSimpleName()), e);
        }
        
        // Pour les autres exceptions, vérifier si c'est une KeycloakServiceException déjà
        if (e instanceof KeycloakServiceException) {
            throw (KeycloakServiceException) e;
        }
        
        // Sinon, encapsuler dans une KeycloakServiceException générique
        throw new KeycloakServiceException("Erreur lors de l'opération " + operation + ": " + 
            (errorMessage != null ? errorMessage : e.getClass().getSimpleName()), e);
    }

    private void setPassword(String userId, String realmName, String password, boolean temporary) throws KeycloakServiceException {
        try {
            UserResource userResource = keycloakAdminClient.getUsers(realmName).get(userId);

            CredentialRepresentation credential = new CredentialRepresentation();
            credential.setType(CredentialRepresentation.PASSWORD);
            credential.setValue(password);
            credential.setTemporary(temporary);

            userResource.resetPassword(credential);

            log.info("✅ Mot de passe défini pour l'utilisateur {} (temporaire: {})", userId, temporary);
        } catch (Exception e) {
            log.error("❌ Erreur lors de la définition du mot de passe pour {}", userId, e);
            handleConnectionException(e, "définition du mot de passe pour l'utilisateur " + userId);
        }
    }

    private List<UserRepresentation> filterUsers(List<UserRepresentation> users, UserSearchCriteriaDTO criteria) {
        return users.stream()
                .filter(user -> {
                    // Filtrer par enabled
                    if (criteria.getEnabled() != null && !criteria.getEnabled().equals(user.isEnabled())) {
                        return false;
                    }

                    // Filtrer par emailVerified
                    if (criteria.getEmailVerified() != null
                            && !criteria.getEmailVerified().equals(user.isEmailVerified())) {
                        return false;
                    }

                    // TODO: Ajouter d'autres filtres selon les besoins

                    return true;
                })
                .collect(Collectors.toList());
    }
}
