using MediatR;
using IamService.Domain.AggregatesModel.GroupAggregate;
using IamService.Domain.Exceptions;

namespace IamService.API.Application.Commands.Groups;

/// <summary>
/// EN: Handler for AddGroupMemberCommand.
/// VI: Handler cho AddGroupMemberCommand.
/// </summary>
public class AddGroupMemberCommandHandler : IRequestHandler<AddGroupMemberCommand, AddGroupMemberCommandResult>
{
    private readonly IGroupRepository _groupRepository;
    private readonly ILogger<AddGroupMemberCommandHandler> _logger;

    public AddGroupMemberCommandHandler(
        IGroupRepository groupRepository,
        ILogger<AddGroupMemberCommandHandler> logger)
    {
        _groupRepository = groupRepository;
        _logger = logger;
    }

    public async Task<AddGroupMemberCommandResult> Handle(
        AddGroupMemberCommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Adding user {UserId} to group {GroupId}", 
            request.UserId, request.GroupId);

        var group = await _groupRepository.GetByIdWithMembersAsync(request.GroupId, cancellationToken);

        if (group == null)
        {
            throw new DomainException($"Group with ID '{request.GroupId}' not found.");
        }

        // EN: Get role by ID or use default (Member)
        // VI: Lấy vai trò theo ID hoặc dùng mặc định (Member)
        GroupRole? role = null;
        if (request.RoleId.HasValue)
        {
            role = GroupRole.FromId(request.RoleId.Value);
        }

        var member = group.AddMember(request.UserId, role, request.AddedByUserId);

        _groupRepository.Update(group);

        await _groupRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "User {UserId} added to group {GroupId} with role {Role}",
            request.UserId,
            request.GroupId,
            member.Role.Name);

        return new AddGroupMemberCommandResult(
            group.Id,
            member.UserId,
            member.Role.Name,
            member.JoinedAt);
    }
}
