package enseirb.myinpulse.service;

import static org.springframework.http.MediaType.APPLICATION_JSON;

import enseirb.myinpulse.exception.UserNotFoundException;
import enseirb.myinpulse.model.RoleRepresentation;
import enseirb.myinpulse.model.UserRepresentation;

import org.springframework.web.client.RestClient;

import javax.management.relation.RoleNotFoundException;

public class KeycloakApi {

    static final String keycloakUrl;
    static final String realmName;

    static {
        if (System.getenv("VITE_KEYCLOAK_URL") == null) {
            System.exit(-1);
        }
        keycloakUrl = System.getenv("VITE_KEYCLOAK_URL");
    }

    static {
        if (System.getenv("VITE_KEYCLOAK_REALM") == null) {
            System.exit(-1);
        }
        realmName = System.getenv("VITE_KEYCLOAK_REALM");
    }

    /**
     * Uses Keycloak API to retrieve a role representation of a role by its name
     *
     * @param roleName name of the role
     * @param bearer authorization header used by the client to authenticate to keycloak
     */
    public static RoleRepresentation getRoleRepresentationByName(String roleName, String bearer)
            throws RoleNotFoundException {
        RoleRepresentation[] response =
                RestClient.builder()
                        .baseUrl(keycloakUrl)
                        .defaultHeader("Authorization", bearer)
                        .build()
                        .get()
                        .uri("/admin/realms/{realmName}/roles/{roleName}", realmName, roleName)
                        .retrieve()
                        .body(RoleRepresentation[].class);

        if (response == null || response.length == 0) {
            throw new RoleNotFoundException("Role not found");
        }
        return response[0];
    }

    /**
     * Use keycloak API to to retreive a userID via his name or email.
     *
     * @param username username or mail of the user
     * @param bearer bearer of the user, allowing access to database
     * @return the userid, as a String
     * @throws UserNotFoundException
     */
    public static String getUserIdByName(String username, String bearer)
            throws UserNotFoundException {
        UserRepresentation[] response =
                RestClient.builder()
                        .baseUrl(keycloakUrl)
                        .defaultHeader("Authorization", bearer)
                        .build()
                        .get()
                        .uri(
                                "/admin/realms/{realmName}/users?username={username}",
                                realmName,
                                username)
                        .retrieve()
                        .body(UserRepresentation[].class);

        if (response == null || response.length == 0) {
            throw new UserNotFoundException("User not found");
        }
        return response[0].id;
    }

    /**
     * TODO: check for error
     *
     * <p>Set a keycloak role to a keycloak user.
     *
     * <p>Usual roles should be `MyINPulse-admin` and `MyINPulse-entrepreneur`
     *
     * @param username
     * @param roleName
     * @param bearer
     * @throws RoleNotFoundException
     * @throws UserNotFoundException
     */
    public static void setRoleToUser(String username, String roleName, String bearer)
            throws RoleNotFoundException, UserNotFoundException {
        RoleRepresentation roleRepresentation = getRoleRepresentationByName(roleName, bearer);
        String userId = getUserIdByName(username, bearer);

        RestClient.builder()
                .baseUrl(keycloakUrl)
                .defaultHeader("Authorization", bearer)
                .build()
                .post()
                .uri(
                        "/admin/realms/${realmName}/users/${userId}/role-mappings/realm",
                        realmName,
                        userId)
                .body(roleRepresentation)
                .contentType(APPLICATION_JSON)
                .retrieve();
    }

    /**
     * Delete a user from Keycloak database. TODO: check the bearer permission.
     *
     * @param username
     * @param bearer
     * @throws UserNotFoundException
     */
    public static void deleteUser(String username, String bearer) throws UserNotFoundException {
        String userId = getUserIdByName(username, bearer);

        RestClient.builder()
                .baseUrl(keycloakUrl)
                .defaultHeader("Authorization", bearer)
                .build()
                .delete()
                .uri("/admin/realms/${realmName}/users/${userId}", realmName, userId)
                .retrieve();
    }
}