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

namespace IamService.API.Application.Queries.Groups;

/// <summary>
/// EN: Handler for GetGroupByIdQuery.
/// VI: Handler cho GetGroupByIdQuery.
/// </summary>
public class GetGroupByIdQueryHandler : IRequestHandler<GetGroupByIdQuery, GroupDto?>
{
    private readonly IGroupRepository _groupRepository;

    public GetGroupByIdQueryHandler(IGroupRepository groupRepository)
    {
        _groupRepository = groupRepository;
    }

    public async Task<GroupDto?> Handle(GetGroupByIdQuery request, CancellationToken cancellationToken)
    {
        var group = await _groupRepository.GetByIdAsync(request.Id, cancellationToken);

        return group == null ? null : MapToDto(group);
    }

    private static GroupDto MapToDto(Group g) => new(
        g.Id,
        g.Name,
        g.Description,
        g.OrganizationId,
        g.Members.Count,
        g.CreatedAt,
        g.UpdatedAt);
}

/// <summary>
/// EN: Handler for GetGroupsByOrganizationQuery.
/// VI: Handler cho GetGroupsByOrganizationQuery.
/// </summary>
public class GetGroupsByOrganizationQueryHandler : IRequestHandler<GetGroupsByOrganizationQuery, IEnumerable<GroupDto>>
{
    private readonly IGroupRepository _groupRepository;

    public GetGroupsByOrganizationQueryHandler(IGroupRepository groupRepository)
    {
        _groupRepository = groupRepository;
    }

    public async Task<IEnumerable<GroupDto>> Handle(
        GetGroupsByOrganizationQuery request,
        CancellationToken cancellationToken)
    {
        var groups = await _groupRepository.GetByOrganizationIdAsync(request.OrganizationId, cancellationToken);

        return groups.Select(MapToDto);
    }

    private static GroupDto MapToDto(Group g) => new(
        g.Id,
        g.Name,
        g.Description,
        g.OrganizationId,
        g.Members.Count,
        g.CreatedAt,
        g.UpdatedAt);
}

/// <summary>
/// EN: Handler for GetGroupsByUserQuery.
/// VI: Handler cho GetGroupsByUserQuery.
/// </summary>
public class GetGroupsByUserQueryHandler : IRequestHandler<GetGroupsByUserQuery, IEnumerable<GroupDto>>
{
    private readonly IGroupRepository _groupRepository;

    public GetGroupsByUserQueryHandler(IGroupRepository groupRepository)
    {
        _groupRepository = groupRepository;
    }

    public async Task<IEnumerable<GroupDto>> Handle(GetGroupsByUserQuery request, CancellationToken cancellationToken)
    {
        var groups = await _groupRepository.GetByUserIdAsync(request.UserId, cancellationToken);

        return groups.Select(MapToDto);
    }

    private static GroupDto MapToDto(Group g) => new(
        g.Id,
        g.Name,
        g.Description,
        g.OrganizationId,
        g.Members.Count,
        g.CreatedAt,
        g.UpdatedAt);
}
