Clear        


                
                    using CORE.APP.Models;
using CORE.APP.Services;
using MediatR;
using Users.APP.Domain;

namespace Users.APP.Features.Groups
{
    /// <summary>
    /// Represents a MediatR request for querying groups.
    /// Inherits from <see cref="Request"/> and specifies the expected response type as 
    /// <see cref="IQueryable{GroupQueryResponse}"/> to be presented as a list or a single item in APIs.
    /// </summary>
    public class GroupQueryRequest : Request, IRequest<IQueryable<GroupQueryResponse>>
    {
    }

    /// <summary>
    /// Represents the response model (DTO: Data Trasfer Object) for querying Group entities.
    /// The properties of a model are generally copied from the related entity properties 
    /// which are not navigation properties or which have the columns in the related database table.
    /// Inherits from <see cref="Response"/> to include common identifier properties (Id and Guid).
    /// </summary>
    public class GroupQueryResponse : Response
    {
        /// <summary>
        /// Gets or sets the title of the group.
        /// </summary>
        public string Title { get; set; }
    }

    /// <summary>
    /// Handles group query requests by retrieving group data from the database and projecting it into group response model.
    /// Inherits from <see cref="ServiceBase"/> to manage culture and use success / error command response helpers.
    /// Implements <see cref="IRequestHandler{GroupQueryRequest, IQueryable{GroupQueryResponse}}"/> for MediatR integration.
    /// </summary>
    public class GroupQueryHandler : ServiceBase, IRequestHandler<GroupQueryRequest, IQueryable<GroupQueryResponse>>
    {
        /// <summary>
        /// Gets the database context for accessing user-related entities and performing data operations.
        /// </summary>
        /// <remarks>
        /// The <see cref="UsersDb"/> context is injected via constructor dependency injection.
        /// It provides access to the application's data layer, including groups and other entities.
        /// </remarks>
        private readonly UsersDb _db; // readonly field that can only be assigned at this line or through the constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="GroupQueryHandler"/> class.
        /// </summary>
        /// <param name="db">
        /// The <see cref="UsersDb"/> context used for database operations.
        /// This is typically provided by the dependency injection container.
        /// </param>
        public GroupQueryHandler(UsersDb db)
        {
            _db = db;
        }

        /// <summary>
        /// Handles the <see cref="GroupQueryRequest"/> by querying the Groups table and projecting each group entity object
        /// into a <see cref="GroupQueryResponse"/> response object.
        /// </summary>
        /// <param name="request">The group query request.</param>
        /// <param name="cancellationToken">A token to observe while waiting for the task to complete.</param>
        /// <returns>
        /// An <see cref="IQueryable{GroupQueryResponse}"/> representing the projected group data.
        /// The query is not executed until enumerated, in other words methods like ToList or SingleOrDefault methods are invoked,
        /// allowing for further composition or deferred execution.
        /// </returns>
        public Task<IQueryable<GroupQueryResponse>> Handle(GroupQueryRequest request, CancellationToken cancellationToken)
        {
            // Query the Groups DbSet and project each group entity to a GroupQueryResponse response.
            // Here, projection means mapping the values of the entity properties to the corresponding properties of the response model.

            // Way 1: types can be used with variables for declarations
            //IQueryable<GroupQueryResponse> query = Db.Groups.Select(groupEntity => new GroupQueryResponse()
            // Way 2: var can also be used therefore the type of the variable (IQueryable<GroupQueryResponse>)
            // will be known dynamically if an assignment is provided, if no assignment, types must be used
            var query = _db.Groups.Select(groupEntity => new GroupQueryResponse()
            {
                Id = groupEntity.Id,         // Maps the entity's integer ID.
                Guid = groupEntity.Guid,     // Maps the entity's GUID.
                Title = groupEntity.Title    // Maps the entity's title to the response.
            });

            // Return the query as a Task result for MediatR compatibility.
            return Task.FromResult(query);
        }
    }
}