StoreController.java

package com.archiweb.api;

import com.archiweb.model.Code;
import com.archiweb.model.Win;
import com.archiweb.repository.CodeRepository;
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.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Optional;

@RestController
@RequestMapping("/api/store")
@Tag(
        name = "Espace Magasin",
        description = """
        Module destiné aux **magasins partenaires** pour la gestion des remises de lots.  
        Ce contrôleur permet :
        - La **vérification** de la validité d’un code client en boutique.  
        - La **confirmation** de la remise d’un lot après validation du code.  
        Ces opérations assurent la traçabilité des récompenses et la conformité du jeu concours en point de vente.
        """
)
public class StoreController {

    private final CodeRepository codeRepository;
    private final WinRepository winRepository;

    public StoreController(CodeRepository codeRepository, WinRepository winRepository) {
        this.codeRepository = codeRepository;
        this.winRepository = winRepository;
    }

    // =========================================================
    // 1️⃣ Vérification d’un code en magasin
    // =========================================================
    @Operation(
            summary = "Vérifier un code en magasin",
            description = """
            Permet à un employé de **vérifier la validité d’un code client saisi ou scanné** en boutique.  
            Retourne le **statut du code** (`valide`, `utilisé`, ou `inexistant`) ainsi que le **type de lot associé**.
            """,
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "Code vérifié avec succès",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = """
                                            {
                                              "status": "success",
                                              "message": "Code valide",
                                              "code": "CODE-XYZ123",
                                              "prizeType": "COFFRET_39"
                                            }
                                            """
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "400",
                            description = "Code invalide ou inexistant",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = "{ \"error\": \"Code invalide ou inexistant.\" }"
                                    )
                            )
                    )
            }
    )
    @GetMapping("/check/{codeValue}")
    public ResponseEntity<?> checkCode(@PathVariable String codeValue) {
        Optional<Code> optionalCode = codeRepository.findByValeur(codeValue);
        if (optionalCode.isEmpty()) {
            return ResponseEntity.badRequest().body("Code invalide ou inexistant.");
        }

        Code code = optionalCode.get();
        String status = code.isUsed() ? "Code déjà utilisé" : "Code valide";

        // Retour texte simple attendu par les tests
        return ResponseEntity.ok(String.format("%s — Lot : %s", status, code.getPrizeType().name()));
    }


    // =========================================================
    // 2️⃣ Confirmation de la remise d’un lot
    // =========================================================
    @Operation(
            summary = "Confirmer la remise d’un lot",
            description = """
            Permet à un magasin de **confirmer la remise d’un lot au client** après vérification du code.  
            Conditions :
            - Le code doit déjà avoir été validé par le joueur (`used = true`).  
            - Un gain non réclamé correspondant au lot doit exister.  
            En cas de succès, le gain est marqué comme `claimé` et daté.
            """,
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "Gain marqué comme remis au client",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = """
                                            {
                                              "status": "success",
                                              "message": "Le gain 'COFFRET_39' a été marqué comme remis au client.",
                                              "claimedAt": "2025-10-27T14:42:00"
                                            }
                                            """
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "400",
                            description = "Code invalide, non validé ou aucun gain correspondant non réclamé",
                            content = @Content(
                                    mediaType = "application/json",
                                    examples = @ExampleObject(
                                            value = "{ \"error\": \"Aucun gain correspondant non réclamé trouvé pour ce code.\" }"
                                    )
                            )
                    )
            }
    )
    @PatchMapping("/confirm/{codeValue}")
    public ResponseEntity<?> confirmPrize(@PathVariable String codeValue) {
        Optional<Code> optionalCode = codeRepository.findByValeur(codeValue);
        if (optionalCode.isEmpty()) {
            return ResponseEntity.badRequest().body("Code invalide ou inexistant.");
        }

        Code code = optionalCode.get();
        if (!code.isUsed()) {
            return ResponseEntity.badRequest().body("Ce code n’a pas encore été validé par un joueur.");
        }

        Optional<Win> optionalWin = winRepository.findFirstByPrizeNameAndClaimedFalse(code.getPrizeType().name());
        if (optionalWin.isEmpty()) {
            return ResponseEntity.badRequest().body("Aucun gain correspondant non réclamé trouvé pour ce code.");
        }

        Win win = optionalWin.get();
        win.setClaimed(true);
        win.setClaimedAt(LocalDateTime.now());
        winRepository.save(win);

        return ResponseEntity.ok(
                String.format(
                        "{\"status\":\"success\",\"message\":\"Le gain '%s' a été marqué comme remis au client.\",\"claimedAt\":\"%s\"}",
                        win.getPrizeName(), LocalDateTime.now()
                )
        );
    }
}