using System.ComponentModel.DataAnnotations;
using APIMappers;
using Dto;
using Dto.Tiny;
using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
using HeartTrackAPI.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Model.Manager;
using Model.Repository;
using Shared;
namespace HeartTrackAPI.Controllers;
///
/// Contrôle les actions liées aux utilisateurs dans l'application HeartTrack.
/// Gère les opérations CRUD sur les utilisateurs, leurs amis, et leurs activités.
///
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[Authorize]
public class UsersController : Controller
{
private readonly ILogger _logger;
private readonly IActivityRepository _activityService;
private readonly IUserRepository _userService;
public UsersController(ILogger logger, IDataManager dataManager)
{
_logger = logger;
_userService = dataManager.UserRepo;
_activityService = dataManager.ActivityRepo;
}
///
/// Récupère une page d'utilisateurs en fonction des critères de pagination et de tri fournis.
///
/// Les critères de pagination et de tri pour les utilisateurs. Met None par defaut et/ou si le critère n'est pas correct
/// Une page de données utilisateur selon les critères spécifiés.
/// Retourne la page demandée d'utilisateurs.
/// La demande de pagination est invalide.
/// Erreur interne du serveur.
[HttpGet]
[ProducesResponseType(typeof(PageResponse), 200)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task>> Get([FromQuery] PageRequest request)
{
try
{
var totalCount = await _userService.GetNbItems();
if (request.Count * request.Index >= totalCount)
{
_logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
return BadRequest("To many object is asked the max is : " + totalCount);
}
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), null);
var athletes = await _userService.GetUsersTiny(request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false);
var pageResponse = new PageResponse(request.Index, request.Count, totalCount, athletes);
return Ok(pageResponse);
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting all athletes");
return Problem();
}
}
///
/// Récupère un utilisateur spécifique par son identifiant.
///
/// L'identifiant de l'utilisateur à récupérer.
/// L'utilisateur correspondant à l'identifiant spécifié.
/// Retourne l'utilisateur demandé.
/// Aucun utilisateur trouvé pour l'identifiant spécifié.
/// Erreur interne du serveur.
[HttpGet("{id}")]
[ProducesResponseType(typeof(ResponseUserDto), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task> GetById([Range(0,int.MaxValue)]int id)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetById), id);
var athlete = await _userService.GetUserById(id);
if (athlete == null)
{
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
return Ok(athlete);
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting athlete by id {id}", id);
return Problem();
}
}
///
/// Obtient le nombre total d'utilisateurs.
///
/// Le nombre total d'utilisateurs.
/// Retourne le nombre total d'utilisateurs.
/// Erreur interne du serveur.
[HttpGet("count")]
[ProducesResponseType(typeof(int), 200)]
[ProducesResponseType(500)]
public async Task> Count()
{
try
{
_logger.LogInformation("Executing {Action}", nameof(Count));
var nbUsers = await _userService.GetNbItems();
return Ok(nbUsers);
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
return Problem();
}
}
///
/// Met à jour les informations d'un utilisateur spécifique.
///
/// L'identifiant de l'utilisateur à mettre à jour.
/// Les données de l'utilisateur pour la mise à jour.
/// L'utilisateur mis à jour.
/// Retourne l'utilisateur mis à jour.
/// Utilisateur non trouvé.
/// Erreur interne du serveur.
[HttpPut("{id}")]
[ProducesResponseType(typeof(UserTinyDto), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task> Update(int id, [FromBody] UserTinyDto user)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Update), user,id);
var athlete = await _userService.GetUserById(id);
if (athlete == null)
{
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
var updatedAthlete = await _userService.UpdateUser(id, user);
if(updatedAthlete == null)
{
_logger.LogError("Error while updating athlete with id {id}", id);
return Problem();
}
return Ok(updatedAthlete);
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
return Problem();
}
}
///
/// Supprime un utilisateur spécifique.
///
/// L'identifiant de l'utilisateur à supprimer.
/// Action result.
/// Utilisateur supprimé avec succès.
/// Utilisateur non trouvé.
/// Erreur interne du serveur.
[HttpDelete("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task Delete(int id)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Delete), null,id);
var athlete = await _userService.GetUserById(id);
if (athlete == null)
{
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
var isDeleted = await _userService.DeleteItem(id);
if(!isDeleted)
{
_logger.LogError("Error while deleting athlete with id {id}", id);
return Problem();
}
return Ok();
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
return Problem();
}
}
///
/// Obtient la liste des amis d'un utilisateur spécifique.
///
/// L'identifiant de l'utilisateur.
/// Les critères de pagination et de tri.
/// La liste paginée des amis.
/// Retourne la liste paginée des amis de l'utilisateur.
/// Utilisateur non trouvé.
/// Erreur interne du serveur.
[HttpGet("{id}/friends")]
[ProducesResponseType(typeof(PageResponse), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task>> GetFriends(int id, [FromQuery] PageRequest request)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(GetFriends), null,id);
var totalCount = await _userService.GetNbFriends(id);
if (request.Count * request.Index >= totalCount)
{
_logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
return BadRequest("To many object is asked the max is : " + totalCount);
}
var friends = await _userService.GetFriends(id, request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false);
if (friends == null) return NotFound();
var pageResponse = new PageResponse(request.Index, request.Count, totalCount, friends);
return Ok(pageResponse);
}
catch(ModelNotFoundException e)
{
_logger.LogError(e, "Error while adding a friend to an athlete");
return BadRequest(e.Message);
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
return Problem();
}
}
///
/// Ajoute un ami à un utilisateur spécifique.
///
/// L'identifiant de l'utilisateur.
/// L'identifiant de l'ami à ajouter.
/// Action result.
/// Ami ajouté avec succès.
/// Utilisateur ou ami non trouvé.
/// Erreur interne du serveur.
[HttpPost("{id}/friend/{friendId}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task AddFollowing(int id, int friendId)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(AddFollowing), friendId,id);
var isAdded = await _userService.AddFollowing(id, friendId);
if(!isAdded)
{
_logger.LogError("Error while adding friend with id {friendId} to athlete with id {id}", friendId, id);
return Problem();
}
return Ok();
}
catch(FriendShipException e)
{
_logger.LogError(e, "Error while adding a friend to an athlete");
return BadRequest(e.Message);
}
catch (Exception e)
{
_logger.LogError(e, "Error while attempting to follow a user");
return Problem();
}
}
///
/// Supprime un ami d'un utilisateur spécifique.
///
/// L'identifiant de l'utilisateur.
/// L'identifiant de l'ami à supprimer.
/// Action result.
/// Ami supprimé avec succès.
/// Utilisateur ou ami non trouvé.
/// Erreur interne du serveur.
[HttpDelete("{id}/friend/{friendId}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task RemoveFriend(int id, int friendId)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(RemoveFriend), friendId,id);
var isRemoved = await _userService.RemoveFollowing(id, friendId);
if(!isRemoved)
{
_logger.LogError("Error while removing friend with id {friendId} to athlete with id {id}", friendId, id);
return Problem();
}
return Ok();
}
catch(FriendShipException e)
{
_logger.LogError(e, "Error while removing a friend to an athlete");
return BadRequest(e.Message);
}
catch (Exception e)
{
_logger.LogError(e, "Error while attempting to unfollow a user");
return Problem();
}
}
/*
///
/// Obtient la liste des activités d'un utilisateur spécifique.
///
/// L'identifiant de l'utilisateur.
/// Les critères de pagination et de tri.
/// La liste paginée des activités de l'utilisateur.
/// Retourne la liste paginée des activités.
/// Aucune activité trouvée.
/// Erreur interne du serveur.
[HttpGet("{userId}/activities")]
// should be tiny DTOActivity returned with only the necessary information (will be used in the list of activities of a user)
public async Task>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest)
{
try
{
var totalCount = await _activityService.GetNbActivitiesByUser(userId);
if (pageRequest.Count * pageRequest.Index >= totalCount)
{
_logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
return BadRequest("To many object is asked the max is : " + totalCount);
}
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetActivitiesByUser), pageRequest);
var activities = await _activityService.GetActivitiesByUser(userId, pageRequest.Index, pageRequest.Count, Enum.TryParse(pageRequest.OrderingPropertyName, out ActivityOrderCriteria result) ? result : ActivityOrderCriteria.None, pageRequest.Descending ?? false);
if(activities == null)
{
return NotFound("No activities found");
}
var pageResponse = new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
return Ok(pageResponse);
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting all activities");
return Problem();
}
}*/
}