using CORE.APP.Models;
using CORE.APP.Services;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using Users.APP.Domain;
namespace Users.APP.Features.Groups
{
/// <summary>
/// Represents a request model (DTO: Data Trasfer Object) to update an existing Group entity.
/// Inherits from <see cref="Request"/> and implements <see cref="IRequest{CommandResponse}"/> for MediatR integration.
/// </summary>
public class GroupUpdateRequest : Request, IRequest<CommandResponse>
{
/// <summary>
/// The new title for the group.
/// This property is required and limited to 100 characters.
/// Data annotations ensure validation at the model binding level.
/// </summary>
[Required, StringLength(100)]
public string Title { get; set; }
}
/// <summary>
/// Handles the update operation for an existing group if any group excluding the current updated one doesn't exist.
/// Inherits from <see cref="ServiceBase"/> to utilize common service functionality such as
/// culture management and returning success / error command responses.
/// Implements <see cref="IRequestHandler{GroupUpdateRequest, CommandResponse}"/> for MediatR request handling.
/// </summary>
public class GroupUpdateHandler : ServiceBase, IRequestHandler<GroupUpdateRequest, CommandResponse>
{
private readonly UsersDb _db;
/// <summary>
/// Initializes a new instance of the <see cref="GroupUpdateHandler"/> class.
/// </summary>
/// <param name="db">The database context for accessing group entity data.</param>
public GroupUpdateHandler(UsersDb db)
{
_db = db;
}
/// <summary>
/// Handles the update logic for an existing group.
/// Checks for duplicate group titles (case-sensitive, trimmed), ensures the group with same title
/// excluding the current updated one doesn't exist, and updates its title.
/// Returns a <see cref="CommandResponse"/> indicating success or error with a result message and optionally entity ID.
/// </summary>
/// <param name="request">The group update request containing the group ID and new title.</param>
/// <param name="cancellationToken">Token for cancelling the async operation.</param>
/// <returns>A <see cref="CommandResponse"/> with the result of the operation.</returns>
public async Task<CommandResponse> Handle(GroupUpdateRequest request, CancellationToken cancellationToken)
{
// If any other group (excluding the current one) already has the same title (case-sensitive, trimmed), don't update.
// This prevents duplicate group names in the database.
if (await _db.Groups.AnyAsync(groupEntity => groupEntity.Id != request.Id
&& groupEntity.Title == request.Title.Trim(), cancellationToken))
return Error("Group with the same title exists!");
// Attempt to find the group entity by its ID, if not found return error command response with message.
var entity = await _db.Groups.FindAsync(request.Id, cancellationToken);
if (entity is null)
return Error("Group not found!");
// Update the group's title with the new value (trimmed for consistency).
entity.Title = request.Title.Trim(); // since request.Title has required data annotation and can't be null, assign request.Title's trimmed value
// Mark the entity as modified in the context.
_db.Groups.Update(entity); // _db.Update(entity); can also be written
// Persist the changes to the database asynchronously by using Unit of Work (all changes made to the DbSets will be commited to the database once).
await _db.SaveChangesAsync(cancellationToken);
// Return a success response indicating the group was updated, including the entity's ID.
return Success("Group updated successfully.", entity.Id);
}
}
}