package dev.lions.user.manager.resource;

import dev.lions.user.manager.api.UserResourceApi;
import dev.lions.user.manager.dto.common.ApiErrorDTO;
import dev.lions.user.manager.dto.importexport.ImportResultDTO;
import dev.lions.user.manager.dto.user.*;
import dev.lions.user.manager.service.UserService;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * REST Resource pour la gestion des utilisateurs
 * Implémente l'interface API commune.
 */
@Slf4j
@jakarta.enterprise.context.ApplicationScoped
@jakarta.ws.rs.Path("/api/users")
public class UserResource implements UserResourceApi {

    @Inject
    UserService userService;

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public UserSearchResultDTO searchUsers(@Valid @NotNull UserSearchCriteriaDTO criteria) {
        log.info("POST /api/users/search - Recherche d'utilisateurs");
        return userService.searchUsers(criteria);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager", "user_viewer" })
    public UserDTO getUserById(String userId, String realmName) {
        log.info("GET /api/users/{} - realm: {}", userId, realmName);
        return userService.getUserById(userId, realmName)
                .orElseThrow(() -> new RuntimeException("Utilisateur non trouvé")); // ExceptionMapper should handle/map
                                                                                    // to 404
    }

    @Override
    @RolesAllowed({ "admin", "user_manager", "user_viewer" })
    public UserSearchResultDTO getAllUsers(String realmName, int page, int pageSize) {
        log.info("GET /api/users - realm: {}, page: {}, pageSize: {}", realmName, page, pageSize);
        return userService.getAllUsers(realmName, page, pageSize);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public Response createUser(@Valid @NotNull UserDTO user, String realmName) {
        log.info("POST /api/users - Création d'un utilisateur: {}", user.getUsername());

        try {
            UserDTO createdUser = userService.createUser(user, realmName);
            return Response.status(Response.Status.CREATED).entity(createdUser).build();
        } catch (IllegalArgumentException e) {
            log.warn("Données invalides lors de la création: {}", e.getMessage());
            return Response.status(Response.Status.CONFLICT)
                    .entity(new ApiErrorDTO(e.getMessage()))
                    .build();
        } catch (Exception e) {
            log.error("Erreur lors de la création de l'utilisateur", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public UserDTO updateUser(String userId, @Valid @NotNull UserDTO user, String realmName) {
        log.info("PUT /api/users/{} - Mise à jour", userId);
        return userService.updateUser(userId, user, realmName);
    }

    @Override
    @RolesAllowed({ "admin" })
    public void deleteUser(String userId, String realmName, boolean hardDelete) {
        log.info("DELETE /api/users/{} - realm: {}, hardDelete: {}", userId, realmName, hardDelete);
        userService.deleteUser(userId, realmName, hardDelete);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public void activateUser(String userId, String realmName) {
        log.info("POST /api/users/{}/activate", userId);
        userService.activateUser(userId, realmName);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public void deactivateUser(String userId, String realmName, String raison) {
        log.info("POST /api/users/{}/deactivate - raison: {}", userId, raison);
        userService.deactivateUser(userId, realmName, raison);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public void resetPassword(String userId, String realmName, @NotNull PasswordResetRequestDTO request) {
        log.info("POST /api/users/{}/reset-password - temporary: {}", userId, request.isTemporary());
        userService.resetPassword(userId, realmName, request.getPassword(), request.isTemporary());
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public void sendVerificationEmail(String userId, String realmName) {
        log.info("POST /api/users/{}/send-verification-email", userId);
        userService.sendVerificationEmail(userId, realmName);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public SessionsRevokedDTO logoutAllSessions(String userId, String realmName) {
        log.info("POST /api/users/{}/logout-sessions", userId);
        int count = userService.logoutAllSessions(userId, realmName);
        return new SessionsRevokedDTO(count);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager", "user_viewer" })
    public List<String> getActiveSessions(String userId, String realmName) {
        log.info("GET /api/users/{}/sessions", userId);
        return userService.getActiveSessions(userId, realmName);
    }

    @Override
    @GET
    @jakarta.ws.rs.Path("/export/csv")
    @jakarta.ws.rs.Produces("text/csv")
    @RolesAllowed({ "admin", "user_manager" })
    public Response exportUsersToCSV(@QueryParam("realm") String realmName) {
        log.info("GET /api/users/export/csv - realm: {}", realmName);
        UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
                .realmName(realmName)
                .page(0)
                .pageSize(10_000)
                .build();
        String csv = userService.exportUsersToCSV(criteria);
        return Response.ok(csv)
                .type(MediaType.valueOf("text/csv"))
                .header("Content-Disposition", "attachment; filename=\"users-" + (realmName != null ? realmName : "export") + ".csv\"")
                .build();
    }

    @Override
    @POST
    @jakarta.ws.rs.Path("/import/csv")
    @jakarta.ws.rs.Consumes(MediaType.TEXT_PLAIN)
    @RolesAllowed({ "admin", "user_manager" })
    public ImportResultDTO importUsersFromCSV(@QueryParam("realm") String realmName, String csvContent) {
        log.info("POST /api/users/import/csv - realm: {}", realmName);
        return userService.importUsersFromCSV(csvContent, realmName);
    }
}
