package dev.lions.user.manager.service;

import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
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 autorisations multi-tenant par realm
 * Permet de contrôler quels utilisateurs peuvent administrer quels realms
 */
public interface RealmAuthorizationService {

    /**
     * Récupère toutes les assignations de realms
     * @return liste de toutes les assignations
     */
    List<RealmAssignmentDTO> getAllAssignments();

    /**
     * Récupère les assignations pour un utilisateur spécifique
     * @param userId ID de l'utilisateur Keycloak
     * @return liste des realms assignés à cet utilisateur
     */
    List<RealmAssignmentDTO> getAssignmentsByUser(@NotBlank String userId);

    /**
     * Récupère les assignations pour un realm spécifique
     * @param realmName nom du realm
     * @return liste des utilisateurs ayant accès à ce realm
     */
    List<RealmAssignmentDTO> getAssignmentsByRealm(@NotBlank String realmName);

    /**
     * Récupère une assignation spécifique
     * @param assignmentId ID de l'assignation
     * @return assignation ou Optional vide
     */
    Optional<RealmAssignmentDTO> getAssignmentById(@NotBlank String assignmentId);

    /**
     * Vérifie si un utilisateur peut administrer un realm donné
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @return true si l'utilisateur peut administrer ce realm
     */
    boolean canManageRealm(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Vérifie si un utilisateur est super admin (peut tout gérer)
     * @param userId ID de l'utilisateur
     * @return true si super admin
     */
    boolean isSuperAdmin(@NotBlank String userId);

    /**
     * Récupère la liste des realms qu'un utilisateur peut administrer
     * @param userId ID de l'utilisateur
     * @return liste des noms de realms, ou liste vide si super admin (peut tout gérer)
     */
    List<String> getAuthorizedRealms(@NotBlank String userId);

    /**
     * Assigne un realm à un utilisateur
     * @param assignment données de l'assignation
     * @return assignation créée
     */
    RealmAssignmentDTO assignRealmToUser(@Valid @NotNull RealmAssignmentDTO assignment);

    /**
     * Retire l'accès d'un utilisateur à un realm
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     */
    void revokeRealmFromUser(@NotBlank String userId, @NotBlank String realmName);

    /**
     * Retire toutes les assignations d'un utilisateur
     * @param userId ID de l'utilisateur
     */
    void revokeAllRealmsFromUser(@NotBlank String userId);

    /**
     * Retire toutes les assignations pour un realm
     * @param realmName nom du realm
     */
    void revokeAllUsersFromRealm(@NotBlank String realmName);

    /**
     * Définit un utilisateur comme super admin
     * @param userId ID de l'utilisateur
     * @param superAdmin true pour définir comme super admin, false pour retirer
     */
    void setSuperAdmin(@NotBlank String userId, boolean superAdmin);

    /**
     * Désactive une assignation (sans la supprimer)
     * @param assignmentId ID de l'assignation
     */
    void deactivateAssignment(@NotBlank String assignmentId);

    /**
     * Réactive une assignation
     * @param assignmentId ID de l'assignation
     */
    void activateAssignment(@NotBlank String assignmentId);

    /**
     * Compte le nombre d'assignations pour un utilisateur
     * @param userId ID de l'utilisateur
     * @return nombre d'assignations actives
     */
    long countAssignmentsByUser(@NotBlank String userId);

    /**
     * Compte le nombre d'utilisateurs ayant accès à un realm
     * @param realmName nom du realm
     * @return nombre d'utilisateurs
     */
    long countUsersByRealm(@NotBlank String realmName);

    /**
     * Vérifie si une assignation existe
     * @param userId ID de l'utilisateur
     * @param realmName nom du realm
     * @return true si l'assignation existe
     */
    boolean assignmentExists(@NotBlank String userId, @NotBlank String realmName);
}
