package dev.lions.user.manager.service;

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.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import java.util.List;
import java.util.Optional;

/**
 * Service de gestion des utilisateurs Keycloak
 * Utilise uniquement l'API Admin Keycloak (AUCUN accès direct à la DB)
 */
public interface UserService {

    /**
     * Recherche des utilisateurs selon des critères
     * @param criteria critères de recherche
     * @return résultat paginé
     */
    UserSearchResultDTO searchUsers(@Valid @NotNull UserSearchCriteriaDTO criteria);

    /**
     * Récupère un utilisateur par son ID
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @return utilisateur ou Optional vide
     */
    Optional<UserDTO> getUserById(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Récupère un utilisateur par son username
     * @param username username
     * @param realmName nom du realm
     * @return utilisateur ou Optional vide
     */
    Optional<UserDTO> getUserByUsername(@NotBlank String username, @NotBlank String realmName);

    /**
     * Récupère un utilisateur par son email
     * @param email email
     * @param realmName nom du realm
     * @return utilisateur ou Optional vide
     */
    Optional<UserDTO> getUserByEmail(@NotBlank String email, @NotBlank String realmName);

    /**
     * Crée un nouvel utilisateur
     * @param user données de l'utilisateur
     * @param realmName nom du realm
     * @return utilisateur créé avec son ID
     */
    UserDTO createUser(@Valid @NotNull UserDTO user, @NotBlank String realmName);

    /**
     * Met à jour un utilisateur existant
     * @param userId ID de l'utilisateur
     * @param user données modifiées
     * @param realmName nom du realm
     * @return utilisateur mis à jour
     */
    UserDTO updateUser(@NotBlank String userId, @Valid @NotNull UserDTO user, @NotBlank String realmName);

    /**
     * Supprime un utilisateur (soft ou hard delete selon configuration)
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @param hardDelete true pour suppression définitive, false pour soft delete
     */
    void deleteUser(@NotBlank String userId, @NotBlank String realmName, boolean hardDelete);

    /**
     * Active un utilisateur
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     */
    void activateUser(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Désactive un utilisateur
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @param raison raison de la désactivation
     */
    void deactivateUser(@NotBlank String userId, @NotBlank String realmName, String raison);

    /**
     * Suspend un utilisateur
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @param raison raison de la suspension
     * @param duree durée de la suspension en jours (0 = indéfinie)
     */
    void suspendUser(@NotBlank String userId, @NotBlank String realmName, String raison, int duree);

    /**
     * Déverrouille un utilisateur
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     */
    void unlockUser(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Réinitialise le mot de passe d'un utilisateur
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @param temporaryPassword mot de passe temporaire
     * @param temporary true si le mot de passe doit être changé à la prochaine connexion
     */
    void resetPassword(@NotBlank String userId, @NotBlank String realmName,
                      @NotBlank String temporaryPassword, boolean temporary);

    /**
     * Envoie un email de vérification
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     */
    void sendVerificationEmail(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Force la déconnexion de toutes les sessions d'un utilisateur
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @return nombre de sessions révoquées
     */
    int logoutAllSessions(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Récupère les sessions actives d'un utilisateur
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @return liste des informations de session
     */
    List<String> getActiveSessions(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Compte le nombre d'utilisateurs selon des critères
     * @param criteria critères de recherche
     * @return nombre d'utilisateurs
     */
    long countUsers(@NotNull UserSearchCriteriaDTO criteria);

    /**
     * Récupère tous les utilisateurs d'un realm (avec pagination)
     * @param realmName nom du realm
     * @param page numéro de page
     * @param pageSize taille de la page
     * @return liste paginée d'utilisateurs
     */
    UserSearchResultDTO getAllUsers(@NotBlank String realmName, int page, int pageSize);

    /**
     * Vérifie si un username existe déjà
     * @param username username à vérifier
     * @param realmName nom du realm
     * @return true si existe
     */
    boolean usernameExists(@NotBlank String username, @NotBlank String realmName);

    /**
     * Vérifie si un email existe déjà
     * @param email email à vérifier
     * @param realmName nom du realm
     * @return true si existe
     */
    boolean emailExists(@NotBlank String email, @NotBlank String realmName);

    /**
     * Exporte les utilisateurs au format CSV
     * @param criteria critères de recherche
     * @return contenu CSV
     */
    String exportUsersToCSV(@NotNull UserSearchCriteriaDTO criteria);

    /**
     * Importe des utilisateurs depuis un CSV
     * @param csvContent contenu CSV
     * @param realmName nom du realm
     * @return nombre d'utilisateurs importés
     */
    int importUsersFromCSV(@NotBlank String csvContent, @NotBlank String realmName);
}
