DailyChallengeController.java

package com.wavii.controller;

import com.wavii.dto.challenge.CompleteChallengResponseDto;
import com.wavii.dto.challenge.DailyChallengeDto;
import com.wavii.dto.challenge.StatsDto;
import com.wavii.model.User;
import com.wavii.service.DailyChallengeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/challenges")
@RequiredArgsConstructor
@Slf4j
public class DailyChallengeController {

    private final DailyChallengeService challengeService;

    /**
     * GET /api/challenges/today
     * Devuelve los desafios del dia visibles para el usuario segun su nivel.
     * Si aun no se han generado los desafios del dia, los genera en este momento.
     */
    @GetMapping("/today")
    public ResponseEntity<List<DailyChallengeDto>> getTodayChallenges(
            @AuthenticationPrincipal User currentUser) {
        try {
            List<DailyChallengeDto> challenges = challengeService.getTodayChallengesForUser(currentUser);
            return ResponseEntity.ok(challenges);
        } catch (Exception e) {
            log.error("Error fetching today challenges: {}", e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).<List<DailyChallengeDto>>build();
        }
    }

    /**
     * POST /api/challenges/{id}/complete
     * Marca un desafio como completado por el usuario autenticado.
     * Actualiza XP, racha y nivel del usuario y devuelve el nuevo estado.
     */
    @PostMapping("/{id}/complete")
    public ResponseEntity<CompleteChallengResponseDto> completeChallenge(
            @PathVariable Long id,
            @AuthenticationPrincipal User currentUser) {
        try {
            CompleteChallengResponseDto response = challengeService.completeChallenge(id, currentUser);
            return ResponseEntity.ok(response);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.notFound().build();
        } catch (IllegalStateException e) {
            return ResponseEntity.badRequest().build();
        } catch (DataIntegrityViolationException e) {
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * GET /api/challenges/stats
     * Devuelve las estadisticas del usuario: racha, mejor racha, XP, nivel
     * y dias completados del mes actual para el calendario.
     */
    @GetMapping("/stats")
    public ResponseEntity<StatsDto> getStats(
            @AuthenticationPrincipal User currentUser) {
        try {
            StatsDto stats = challengeService.getStats(currentUser);
            return ResponseEntity.ok(stats);
        } catch (Exception e) {
            log.error("Error fetching challenge stats: {}", e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).<StatsDto>build();
        }
    }
}