package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.service.AdminUserService;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
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.tags.Tag;
import org.jboss.logging.Logger;

import java.util.List;
import java.util.Map;

/**
 * API admin pour la gestion des utilisateurs Keycloak (proxy vers lions-user-manager).
 * Réservé au rôle SUPER_ADMIN — la vérification est faite par @RolesAllowed au niveau classe.
 */
@Path("/api/admin/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Admin - Utilisateurs", description = "Gestion des utilisateurs Keycloak (SUPER_ADMIN)")
@RolesAllowed("SUPER_ADMIN")
public class AdminUserResource {

    private static final Logger LOG = Logger.getLogger(AdminUserResource.class);

    @Inject
    AdminUserService adminUserService;

    @GET
    @Operation(summary = "Lister les utilisateurs", description = "Liste paginée des utilisateurs du realm")
    public Response list(
        @QueryParam("page") @DefaultValue("0") int page,
        @QueryParam("size") @DefaultValue("20") int size,
        @QueryParam("search") String search
    ) {
        try {
            UserSearchResultDTO result = adminUserService.searchUsers(page, size, search);
            return Response.ok(result).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur liste utilisateurs: %s", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(Map.of("error", "Erreur serveur", "message", e.getMessage()))
                .build();
        }
    }

    @GET
    @Path("/{id}")
    @Operation(summary = "Détail utilisateur")
    public Response getById(@PathParam("id") String id) {
        try {
            UserDTO user = adminUserService.getUserById(id);
            if (user == null) {
                return Response.status(Response.Status.NOT_FOUND).build();
            }
            return Response.ok(user).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur détail utilisateur %s: %s", id, e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(Map.of("error", "Erreur serveur", "message", e.getMessage()))
                .build();
        }
    }

    @GET
    @Path("/roles")
    @Operation(summary = "Liste des rôles realm")
    public Response listRoles() {
        try {
            List<RoleDTO> roles = adminUserService.getRealmRoles();
            return Response.ok(roles).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur liste rôles: %s", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(Map.of("error", "Erreur serveur", "message", e.getMessage()))
                .build();
        }
    }

    @GET
    @Path("/{id}/roles")
    @Operation(summary = "Rôles d'un utilisateur")
    public Response getUserRoles(@PathParam("id") String id) {
        try {
            List<RoleDTO> roles = adminUserService.getUserRoles(id);
            return Response.ok(roles).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur rôles utilisateur %s: %s", id, e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(Map.of("error", "Erreur serveur", "message", e.getMessage()))
                .build();
        }
    }

    @PUT
    @Path("/{id}/roles")
    @Operation(summary = "Mettre à jour les rôles d'un utilisateur")
    public Response setUserRoles(@PathParam("id") String id, List<String> roleNames) {
        try {
            adminUserService.setUserRoles(id, roleNames);
            return Response.ok(Map.of("success", true, "userId", id)).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur mise à jour rôles %s: %s", id, e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(Map.of("error", "Erreur serveur", "message", e.getMessage()))
                .build();
        }
    }

    @POST
    @Operation(summary = "Créer un utilisateur", description = "Crée un nouvel utilisateur Keycloak (proxy lions-user-manager)")
    public Response createUser(UserDTO user) {
        try {
            UserDTO created = adminUserService.createUser(user);
            return Response.status(Response.Status.CREATED).entity(created).build();
        } catch (IllegalArgumentException e) {
            LOG.warnf("Création utilisateur refusée: %s", e.getMessage());
            return Response.status(Response.Status.CONFLICT)
                .entity(Map.of("error", "Conflit", "message", e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur création utilisateur: %s", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(Map.of("error", "Erreur serveur", "message", e.getMessage()))
                .build();
        }
    }

    @PUT
    @Path("/{id}")
    @Operation(summary = "Mettre à jour un utilisateur", description = "Met à jour un utilisateur (au minimum enabled)")
    public Response updateUser(@PathParam("id") String id, UserDTO user) {
        try {
            if (user.getEnabled() != null) {
                UserDTO updated = adminUserService.updateUserEnabled(id, user.getEnabled());
                return Response.ok(updated).build();
            }
            UserDTO updated = adminUserService.updateUser(id, user);
            return Response.ok(updated).build();
        } catch (IllegalArgumentException e) {
            if (e.getMessage() != null && e.getMessage().contains("non trouvé")) {
                return Response.status(Response.Status.NOT_FOUND)
                    .entity(Map.of("error", "Non trouvé", "message", e.getMessage()))
                    .build();
            }
            return Response.status(Response.Status.BAD_REQUEST)
                .entity(Map.of("error", "Requête invalide", "message", e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur mise à jour utilisateur %s: %s", id, e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(Map.of("error", "Erreur serveur", "message", e.getMessage()))
                .build();
        }
    }
}
