GameController.java

package com.archiweb.api;

import com.archiweb.dto.HistoryParticipationDTO;
import com.archiweb.model.Code;
import com.archiweb.model.Participation;
import com.archiweb.model.User;
import com.archiweb.model.Win;
import com.archiweb.repository.CodeRepository;
import com.archiweb.repository.ParticipationRepository;
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 org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@RestController
@RequestMapping("/api/game")
@Tag(
        name = "Jeu concours",
        description = """
        Module principal de gestion du **jeu concours Thé Tip Top**.  
        Ce contrôleur permet :
        - La **participation** des utilisateurs via un code valide.  
        - La **consultation de l’historique des gains** de l’utilisateur connecté.  
        - La **vérification du statut d’un code** (valide, utilisé ou inexistant).  
        Tous les endpoints nécessitent un utilisateur connecté et un code valide pour participer.
        """
)
public class GameController {

    private final CodeRepository codeRepository;
    private final WinRepository winRepository;
    private final UserRepository userRepository;
    private final ParticipationRepository participationRepository;

    public GameController(CodeRepository codeRepository,
                          WinRepository winRepository,
                          UserRepository userRepository,ParticipationRepository participationRepository) {
        this.codeRepository = codeRepository;
        this.winRepository = winRepository;
        this.userRepository = userRepository;
        this.participationRepository = participationRepository;
    }

    // =========================================================
    // 1️⃣ Participation au jeu concours
    // =========================================================
    @Operation(
            summary = "Participer au jeu concours",
            description = """
            Permet à un utilisateur authentifié de **participer au jeu concours** en saisissant un code unique.  
            Si le code est valide, non expiré et non encore utilisé, un **gain** lui est automatiquement attribué.  
            Le code est alors marqué comme “utilisé” pour empêcher toute réutilisation ultérieure.
            """,
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "Participation validée et gain enregistré",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = """
                                            {
                                              "status": "success",
                                              "message": "Participation enregistrée.",
                                              "gainAttribue": "INFUSEUR",
                                              "timestamp": "2025-10-27T15:05:22"
                                            }
                                            """
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "400",
                            description = "Code invalide ou déjà utilisé",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(value = "{ \"error\": \"Code invalide ou déjà utilisé.\" }")
                            )
                    ),
                    @ApiResponse(
                            responseCode = "401",
                            description = "Utilisateur non authentifié",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(value = "{ \"error\": \"Utilisateur non connecté.\" }")
                            )
                    )
            }
    )
    @PostMapping("/participate")
    public ResponseEntity<?> participate(@RequestParam String codeValue, Authentication authentication) {
        String email = authentication.getName();
        Optional<User> optionalUser = userRepository.findByEmail(email);
        if (optionalUser.isEmpty()) {
            return ResponseEntity.status(401).body("Utilisateur non trouvé.");
        }

        Optional<Code> optionalCode = codeRepository.findByValeur(codeValue);
        if (optionalCode.isEmpty()) {
            return ResponseEntity.badRequest().body("Code invalide.");
        }

        Code code = optionalCode.get();
        if (code.isUsed()) {
            return ResponseEntity.badRequest().body("Code déjà utilisé.");
        }

        code.setUsed(true);
        code.setUsedAt(LocalDateTime.now());
        codeRepository.save(code);

        Win win = new Win();
        win.setUser(optionalUser.get());
        win.setPrizeName(code.getPrizeType().name());
        win.setClaimed(false);
        winRepository.save(win);

        return ResponseEntity.ok("Participation enregistrée. Gain attribué : " + code.getPrizeType().name());
    }

    // =========================================================
    // 2️⃣ Historique des participations et gains
    // =========================================================
    @Operation(
            summary = "Obtenir l’historique des participations",
            description = """
            Retourne la **liste complète des gains** associés à l’utilisateur actuellement connecté.  
            Permet à chaque participant de consulter son historique de participations et de gains enregistrés.
            """,
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "Historique récupéré avec succès",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = """
                                            [
                                              {
                                                "id": 1,
                                                "prizeName": "INFUSEUR",
                                                "claimed": false,
                                                "createdAt": "2025-10-21T14:22:11"
                                              },
                                              {
                                                "id": 2,
                                                "prizeName": "COFFRET_39",
                                                "claimed": true,
                                                "claimedAt": "2025-10-24T10:08:05"
                                              }
                                            ]
                                            """
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "401",
                            description = "Utilisateur non authentifié",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(value = "{ \"error\": \"Utilisateur non connecté.\" }")
                            )
                    )
            }
    )
    @GetMapping("/history")
    public ResponseEntity<List<HistoryParticipationDTO>> getMyHistory(Authentication authentication) {

        String email = authentication.getName();
        Optional<User> opt = userRepository.findByEmail(email);

        if (opt.isEmpty()) {
            return ResponseEntity.status(401).build();
        }

        List<Participation> list = participationRepository.findByUserId(opt.get().getId());

        List<HistoryParticipationDTO> dto = list.stream()
                .map(p -> new HistoryParticipationDTO(
                        p.getId(),
                        p.getCode().getPrizeType().name(),    // 🟢 juste le prize type
                        p.getDateParticipation()
                ))
                .toList();


        return ResponseEntity.ok(dto);
    }



    // =========================================================
    // 3️⃣ Vérification du statut d’un code
    // =========================================================
    @Operation(
            summary = "Vérifier le statut d’un code",
            description = """
            Permet de vérifier si un code saisi est **valide**, **déjà utilisé** ou **inexistant**.  
            Utilisé principalement pour informer le joueur avant la soumission de sa participation.
            """,
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "Statut du code renvoyé avec succès",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = """
                                            {
                                              "status": "valid",
                                              "message": "Code valide",
                                              "prizeType": "COFFRET_99"
                                            }
                                            """
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "400",
                            description = "Code invalide ou inexistant",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(value = "Code invalide ou inexistant.")
                            )
                    )
            }
    )
    @GetMapping("/status/{codeValue}")
    public ResponseEntity<?> getCodeStatus(@PathVariable String codeValue) {
        Optional<Code> optionalCode = codeRepository.findByValeur(codeValue);

        // Code introuvable
        if (optionalCode.isEmpty()) {
            return ResponseEntity.badRequest().body(Map.of(
                    "status", "error",
                    "message", "Code invalide ou inexistant.",
                    "valid", false
            ));
        }

        Code code = optionalCode.get();

        // Code déjà utilisé
        if (code.isUsed()) {
            return ResponseEntity.ok(Map.of(
                    "status", "used",
                    "message", "Code déjà utilisé.",
                    "valid", false
            ));
        }

        // Code valide
        Map<String, Object> response = new HashMap<>();
        response.put("status", "valid");
        response.put("message", "Code valide");
        response.put("valid", true);
        response.put("prizeType", code.getPrizeType() != null ? code.getPrizeType().name() : null);
        return ResponseEntity.ok(response);
    }


}