package dev.lions.user.manager.api;

import dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO;
import dev.lions.user.manager.dto.role.RoleDTO;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;

import java.util.List;

/**
 * Interface JAX-RS pour la gestion des rôles Keycloak.
 */
@Path("/api/roles")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Roles", description = "Gestion des rôles Keycloak (realm et client)")
public interface RoleResourceApi {

    // ==================== Endpoints Realm Roles ====================

    @POST
    @Path("/realm")
    @Operation(summary = "Créer un rôle realm", description = "Crée un nouveau rôle au niveau du realm")
    @APIResponses({
            @APIResponse(responseCode = "201", description = "Rôle créé", content = @Content(schema = @Schema(implementation = RoleDTO.class)))
    })
    Response createRealmRole(
            @Valid @NotNull RoleDTO roleDTO,
            @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);

    @GET
    @Path("/realm/{roleName}")
    @Operation(summary = "Récupérer un rôle realm par nom", description = "Récupère les détails d'un rôle realm")
    RoleDTO getRealmRole(
            @Parameter(description = "Nom du rôle") @PathParam("roleName") String roleName,
            @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);

    @GET
    @Path("/realm")
    @Operation(summary = "Lister tous les rôles realm", description = "Liste tous les rôles du realm")
    List<RoleDTO> getAllRealmRoles(
            @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);

    @PUT
    @Path("/realm/{roleName}")
    @Operation(summary = "Mettre à jour un rôle realm", description = "Met à jour les informations d'un rôle realm")
    RoleDTO updateRealmRole(
            @PathParam("roleName") String roleName,
            @Valid @NotNull RoleDTO roleDTO,
            @QueryParam("realm") String realmName);

    @DELETE
    @Path("/realm/{roleName}")
    @Operation(summary = "Supprimer un rôle realm", description = "Supprime un rôle realm")
    void deleteRealmRole(
            @PathParam("roleName") String roleName,
            @QueryParam("realm") String realmName);

    // ==================== Endpoints Client Roles ====================

    @POST
    @Path("/client/{clientId}")
    @Operation(summary = "Créer un rôle client", description = "Crée un nouveau rôle pour un client spécifique")
    @APIResponses({
            @APIResponse(responseCode = "201", description = "Rôle créé", content = @Content(schema = @Schema(implementation = RoleDTO.class)))
    })
    Response createClientRole(
            @PathParam("clientId") String clientId,
            @Valid @NotNull RoleDTO roleDTO,
            @QueryParam("realm") String realmName);

    @GET
    @Path("/client/{clientId}/{roleName}")
    @Operation(summary = "Récupérer un rôle client par nom", description = "Récupère les détails d'un rôle client")
    RoleDTO getClientRole(
            @PathParam("clientId") String clientId,
            @PathParam("roleName") String roleName,
            @QueryParam("realm") String realmName);

    @GET
    @Path("/client/{clientId}")
    @Operation(summary = "Lister tous les rôles d'un client", description = "Liste tous les rôles d'un client spécifique")
    List<RoleDTO> getAllClientRoles(
            @PathParam("clientId") String clientId,
            @QueryParam("realm") String realmName);

    @DELETE
    @Path("/client/{clientId}/{roleName}")
    @Operation(summary = "Supprimer un rôle client", description = "Supprime un rôle d'un client")
    void deleteClientRole(
            @PathParam("clientId") String clientId,
            @PathParam("roleName") String roleName,
            @QueryParam("realm") String realmName);

    // ==================== Endpoints Attribution de rôles ====================

    @POST
    @Path("/assign/realm/{userId}")
    @Operation(summary = "Attribuer des rôles realm à un utilisateur", description = "Assigne un ou plusieurs rôles realm à un utilisateur")
    void assignRealmRoles(
            @PathParam("userId") String userId,
            @QueryParam("realm") String realmName,
            @NotNull RoleAssignmentRequestDTO request);

    @POST
    @Path("/revoke/realm/{userId}")
    @Operation(summary = "Révoquer des rôles realm d'un utilisateur", description = "Révoque un ou plusieurs rôles realm d'un utilisateur")
    void revokeRealmRoles(
            @PathParam("userId") String userId,
            @QueryParam("realm") String realmName,
            @NotNull RoleAssignmentRequestDTO request);

    @POST
    @Path("/assign/client/{clientId}/{userId}")
    @Operation(summary = "Attribuer des rôles client à un utilisateur", description = "Assigne un ou plusieurs rôles client à un utilisateur")
    void assignClientRoles(
            @PathParam("clientId") String clientId,
            @PathParam("userId") String userId,
            @QueryParam("realm") String realmName,
            @NotNull RoleAssignmentRequestDTO request);

    @GET
    @Path("/user/realm/{userId}")
    @Operation(summary = "Récupérer les rôles realm d'un utilisateur", description = "Liste tous les rôles realm d'un utilisateur")
    List<RoleDTO> getUserRealmRoles(
            @PathParam("userId") String userId,
            @QueryParam("realm") String realmName);

    @GET
    @Path("/user/client/{clientId}/{userId}")
    @Operation(summary = "Récupérer les rôles client d'un utilisateur", description = "Liste tous les rôles client d'un utilisateur")
    List<RoleDTO> getUserClientRoles(
            @PathParam("clientId") String clientId,
            @PathParam("userId") String userId,
            @QueryParam("realm") String realmName);

    // ==================== Endpoints Rôles composites ====================

    @POST
    @Path("/composite/{roleName}/add")
    @Operation(summary = "Ajouter des rôles composites", description = "Ajoute des rôles composites à un rôle")
    void addComposites(
            @PathParam("roleName") String roleName,
            @QueryParam("realm") String realmName,
            @NotNull RoleAssignmentRequestDTO request);

    @GET
    @Path("/composite/{roleName}")
    @Operation(summary = "Récupérer les rôles composites", description = "Liste tous les rôles composites d'un rôle")
    List<RoleDTO> getComposites(
            @PathParam("roleName") String roleName,
            @QueryParam("realm") String realmName);
}
