package dev.lions.user.manager.resource;

import dev.lions.user.manager.api.RealmAssignmentResourceApi;
import dev.lions.user.manager.dto.realm.AuthorizedRealmsDTO;
import dev.lions.user.manager.dto.realm.RealmAccessCheckDTO;
import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
import dev.lions.user.manager.service.RealmAuthorizationService;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * REST Resource pour la gestion des affectations de realms aux utilisateurs
 * Implémente l'interface API commune.
 */
@Slf4j
@jakarta.enterprise.context.ApplicationScoped
@jakarta.ws.rs.Path("/api/realm-assignments")
public class RealmAssignmentResource implements RealmAssignmentResourceApi {

    @Inject
    RealmAuthorizationService realmAuthorizationService;

    @Context
    SecurityContext securityContext;

    @Override
    @RolesAllowed({ "admin" })
    public List<RealmAssignmentDTO> getAllAssignments() {
        log.info("GET /api/realm-assignments - Récupération de toutes les affectations");
        return realmAuthorizationService.getAllAssignments();
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public List<RealmAssignmentDTO> getAssignmentsByUser(String userId) {
        log.info("GET /api/realm-assignments/user/{}", userId);
        return realmAuthorizationService.getAssignmentsByUser(userId);
    }

    @Override
    @RolesAllowed({ "admin" })
    public List<RealmAssignmentDTO> getAssignmentsByRealm(String realmName) {
        log.info("GET /api/realm-assignments/realm/{}", realmName);
        return realmAuthorizationService.getAssignmentsByRealm(realmName);
    }

    @Override
    @RolesAllowed({ "admin" })
    public RealmAssignmentDTO getAssignmentById(String assignmentId) {
        log.info("GET /api/realm-assignments/{}", assignmentId);
        return realmAuthorizationService.getAssignmentById(assignmentId)
                .orElseThrow(() -> new RuntimeException("Affectation non trouvée")); // ExceptionMapper should
                                                                                     // handle/map to 404
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public RealmAccessCheckDTO canManageRealm(String userId, String realmName) {
        log.info("GET /api/realm-assignments/check - userId: {}, realmName: {}", userId, realmName);
        boolean canManage = realmAuthorizationService.canManageRealm(userId, realmName);
        return new RealmAccessCheckDTO(canManage, userId, realmName);
    }

    @Override
    @RolesAllowed({ "admin", "user_manager" })
    public AuthorizedRealmsDTO getAuthorizedRealms(String userId) {
        log.info("GET /api/realm-assignments/authorized-realms/{}", userId);
        List<String> realms = realmAuthorizationService.getAuthorizedRealms(userId);
        boolean isSuperAdmin = realmAuthorizationService.isSuperAdmin(userId);
        return new AuthorizedRealmsDTO(realms, isSuperAdmin);
    }

    @Override
    @RolesAllowed({ "admin" })
    public Response assignRealmToUser(@Valid @NotNull RealmAssignmentDTO assignment) {
        log.info("POST /api/realm-assignments - Assignation du realm {} à l'utilisateur {}",
                assignment.getRealmName(), assignment.getUserId());

        try {
            // Ajouter l'utilisateur qui fait l'assignation
            if (securityContext.getUserPrincipal() != null) {
                assignment.setAssignedBy(securityContext.getUserPrincipal().getName());
            }

            RealmAssignmentDTO createdAssignment = realmAuthorizationService.assignRealmToUser(assignment);
            return Response.status(Response.Status.CREATED).entity(createdAssignment).build();
        } catch (IllegalArgumentException e) {
            log.warn("Données invalides lors de l'assignation: {}", e.getMessage());
            // Need to return 409 or 400 manually since this method returns Response
            return Response.status(Response.Status.CONFLICT)
                    .entity(new dev.lions.user.manager.dto.common.ApiErrorDTO(e.getMessage()))
                    .build();
        } catch (Exception e) {
            log.error("Erreur lors de l'assignation du realm", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    @RolesAllowed({ "admin" })
    public void revokeRealmFromUser(String userId, String realmName) {
        log.info("DELETE /api/realm-assignments/user/{}/realm/{}", userId, realmName);
        realmAuthorizationService.revokeRealmFromUser(userId, realmName);
    }

    @Override
    @RolesAllowed({ "admin" })
    public void revokeAllRealmsFromUser(String userId) {
        log.info("DELETE /api/realm-assignments/user/{}", userId);
        realmAuthorizationService.revokeAllRealmsFromUser(userId);
    }

    @Override
    @RolesAllowed({ "admin" })
    public void deactivateAssignment(String assignmentId) {
        log.info("PUT /api/realm-assignments/{}/deactivate", assignmentId);
        realmAuthorizationService.deactivateAssignment(assignmentId);
    }

    @Override
    @RolesAllowed({ "admin" })
    public void activateAssignment(String assignmentId) {
        log.info("PUT /api/realm-assignments/{}/activate", assignmentId);
        realmAuthorizationService.activateAssignment(assignmentId);
    }

    @Override
    @RolesAllowed({ "admin" })
    public void setSuperAdmin(String userId, @NotNull Boolean superAdmin) {
        log.info("PUT /api/realm-assignments/super-admin/{} - superAdmin: {}", userId, superAdmin);
        realmAuthorizationService.setSuperAdmin(userId, superAdmin);
    }
}
