RgpdController.java

package com.archiweb.api;

import com.archiweb.model.User;
import com.archiweb.model.Win;
import com.archiweb.repository.UserRepository;
import com.archiweb.repository.WinRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/rgpd")
@RequiredArgsConstructor
@Tag(
        name = "RGPD / Confidentialité",
        description = """
        Module de gestion des **données personnelles** des utilisateurs conformément au RGPD.  
        Ce contrôleur permet :
        - L’**exportation complète** des données personnelles d’un utilisateur (profil et historique des gains).  
        - La **suppression totale** d’un compte utilisateur et de ses données associées (droit à l’oubli).  
        Accessible aux utilisateurs souhaitant exercer leur droit à la portabilité ou à la suppression de leurs données.
        """
)
public class RgpdController {

    private final UserRepository userRepository;
    private final WinRepository winRepository;

    // =========================================================
    // 1️⃣ Exportation des données personnelles
    // =========================================================
    @Operation(
            summary = "Exporter les données personnelles d’un utilisateur",
            description = """
            Permet à un utilisateur d’obtenir une **copie complète de ses données personnelles** enregistrées dans la base.  
            L’export comprend :
            - Les informations du profil (identité, email, consentement, etc.)  
            - L’historique de ses gains enregistrés dans le système.
            """,
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "Exportation effectuée avec succès",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = """
                                            {
                                              "id": 5,
                                              "username": "karim_aitb",
                                              "email": "karim@example.com",
                                              "firstName": "Karim",
                                              "lastName": "Ait Bouaddi",
                                              "phone": "+33612345678",
                                              "birthDate": "1990-05-20",
                                              "consentGiven": true,
                                              "createdAt": "2024-03-10T10:15:45",
                                              "updatedAt": "2025-10-25T14:12:00",
                                              "wins": [
                                                "INFUSEUR",
                                                "COFFRET_99"
                                              ]
                                            }
                                            """
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "404",
                            description = "Utilisateur introuvable",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(value = "{ \"error\": \"Utilisateur introuvable.\" }")
                            )
                    )
            }
    )
    @GetMapping("/users/{id}/export")
    public ResponseEntity<?> exportUserData(@PathVariable Long id) {
        Optional<User> optionalUser = userRepository.findById(id);
        if (optionalUser.isEmpty()) {
            return ResponseEntity.status(404).body("Utilisateur introuvable.");
        }

        User user = optionalUser.get();
        List<Win> wins = winRepository.findByUserId(id);

        Map<String, Object> export = new LinkedHashMap<>();
        export.put("id", user.getId());
        export.put("username", user.getUsername());
        export.put("email", user.getEmail());
        export.put("firstName", user.getFirstName());
        export.put("lastName", user.getLastName());
        export.put("phone", user.getPhone());
        export.put("birthDate", user.getBirthDate());
        export.put("consentGiven", user.isConsentGiven());
        export.put("createdAt", user.getCreatedAt());
        export.put("updatedAt", user.getUpdatedAt());
        export.put("wins", wins.stream().map(Win::getPrizeName).collect(Collectors.toList()));

        return ResponseEntity.ok(export);
    }

    // =========================================================
    // 2️⃣ Suppression complète du compte utilisateur
    // =========================================================
    @Operation(
            summary = "Supprimer un compte utilisateur et ses données associées",
            description = """
            Permet d’exercer le **droit à l’oubli** : supprime définitivement le compte utilisateur et toutes les données associées (gains, informations personnelles).  
            Une fois cette opération effectuée, aucune restauration n’est possible.
            """,
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "Compte supprimé avec succès",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = """
                                            {
                                              "status": "success",
                                              "message": "Compte utilisateur supprimé avec succès (droit à l’oubli exercé).",
                                              "deletedUser": "karim@example.com"
                                            }
                                            """
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "404",
                            description = "Utilisateur introuvable",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(value = "{ \"error\": \"Utilisateur introuvable.\" }")
                            )
                    )
            }
    )
    @DeleteMapping("/users/{id}/delete")
    public ResponseEntity<?> deleteUserAndData(@PathVariable Long id) {
        Optional<User> optionalUser = userRepository.findById(id);
        if (optionalUser.isEmpty()) {
            return ResponseEntity.status(404).body("Utilisateur introuvable.");
        }

        User user = optionalUser.get();
        List<Win> userWins = winRepository.findByUserId(id);

        if (!userWins.isEmpty()) {
            winRepository.deleteAll(userWins);
        }

        userRepository.delete(user);

        return ResponseEntity.ok(
                Map.of(
                        "status", "success",
                        "message", "Compte utilisateur supprimé avec succès (droit à l’oubli exercé).",
                        "deletedUser", user.getEmail()
                )
        );
    }
}