using Asp.Versioning;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MembershipService.API.Application.Commands;
using MembershipService.API.Application.Queries;
using Swashbuckle.AspNetCore.Annotations;
namespace MembershipService.API.Controllers;
///
/// EN: Controller for managing members.
/// VI: Controller để quản lý members.
///
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
[Authorize]
[SwaggerTag("Member management endpoints")]
public class MembersController : ControllerBase
{
private readonly IMediator _mediator;
private readonly ILogger _logger;
public MembersController(IMediator mediator, ILogger logger)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
///
/// EN: Get member by ID.
/// VI: Lấy member theo ID.
///
[HttpGet("{id:guid}")]
[SwaggerOperation(Summary = "Get member by ID", Description = "Retrieves a member by their unique identifier")]
[SwaggerResponse(200, "Member found", typeof(MemberDto))]
[SwaggerResponse(404, "Member not found")]
[SwaggerResponse(401, "Unauthorized")]
public async Task> GetById(Guid id)
{
var member = await _mediator.Send(new GetMemberByIdQuery(id));
if (member == null)
{
return NotFound(new { message = $"Member {id} not found" });
}
return Ok(member);
}
///
/// EN: Get current user's member profile.
/// VI: Lấy profile member của user hiện tại.
///
[HttpGet("me")]
[SwaggerOperation(Summary = "Get my member profile", Description = "Retrieves the member profile for the authenticated user")]
[SwaggerResponse(200, "Member found", typeof(MemberDto))]
[SwaggerResponse(404, "Member not found")]
[SwaggerResponse(401, "Unauthorized")]
public async Task> GetMe()
{
var userId = GetCurrentUserId();
if (userId == null)
{
return Unauthorized();
}
var member = await _mediator.Send(new GetMemberByIdQuery(userId.Value));
if (member == null)
{
return NotFound(new { message = "Member profile not found" });
}
return Ok(member);
}
///
/// EN: Get paginated list of members.
/// VI: Lấy danh sách members phân trang.
///
[HttpGet]
[SwaggerOperation(Summary = "Get members list", Description = "Retrieves a paginated list of members")]
[SwaggerResponse(200, "Members retrieved", typeof(GetMembersResult))]
[SwaggerResponse(401, "Unauthorized")]
public async Task> GetAll(
[FromQuery] int pageIndex = 0,
[FromQuery] int pageSize = 10,
[FromQuery] string? search = null)
{
var result = await _mediator.Send(new GetMembersQuery
{
PageIndex = pageIndex,
PageSize = pageSize,
SearchTerm = search
});
return Ok(result);
}
///
/// EN: Create a new member.
/// VI: Tạo member mới.
///
[HttpPost]
[SwaggerOperation(Summary = "Create member", Description = "Creates a new member profile")]
[SwaggerResponse(201, "Member created", typeof(CreateMemberResult))]
[SwaggerResponse(400, "Invalid request")]
[SwaggerResponse(409, "Member already exists")]
[SwaggerResponse(401, "Unauthorized")]
public async Task> Create([FromBody] CreateMemberCommand command)
{
try
{
var result = await _mediator.Send(command);
return CreatedAtAction(nameof(GetById), new { id = result.MemberId }, result);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("already exists"))
{
return Conflict(new { message = ex.Message });
}
}
///
/// EN: Update member profile.
/// VI: Cập nhật profile member.
///
[HttpPut("{id:guid}")]
[SwaggerOperation(Summary = "Update member profile", Description = "Updates a member's profile information")]
[SwaggerResponse(200, "Member updated", typeof(UpdateMemberProfileResult))]
[SwaggerResponse(400, "Invalid request")]
[SwaggerResponse(404, "Member not found")]
[SwaggerResponse(401, "Unauthorized")]
public async Task> UpdateProfile(
Guid id,
[FromBody] UpdateMemberProfileCommand command)
{
command.MemberId = id;
try
{
var result = await _mediator.Send(command);
return Ok(result);
}
catch (KeyNotFoundException ex)
{
return NotFound(new { message = ex.Message });
}
}
///
/// EN: Add experience points to a member.
/// VI: Thêm điểm kinh nghiệm cho member.
///
[HttpPost("{id:guid}/experience")]
[SwaggerOperation(Summary = "Add experience points", Description = "Adds experience points to a member")]
[SwaggerResponse(200, "Experience added", typeof(AddExperienceResult))]
[SwaggerResponse(400, "Invalid request")]
[SwaggerResponse(404, "Member not found")]
[SwaggerResponse(401, "Unauthorized")]
public async Task> AddExperience(
Guid id,
[FromBody] AddExperienceCommand command)
{
command.MemberId = id;
try
{
var result = await _mediator.Send(command);
return Ok(result);
}
catch (KeyNotFoundException ex)
{
return NotFound(new { message = ex.Message });
}
catch (ArgumentException ex)
{
return BadRequest(new { message = ex.Message });
}
}
///
/// EN: Get member's level progress.
/// VI: Lấy tiến độ level của member.
///
[HttpGet("{id:guid}/progress")]
[SwaggerOperation(Summary = "Get level progress", Description = "Retrieves member's level progress")]
[SwaggerResponse(200, "Progress retrieved", typeof(MemberProgressDto))]
[SwaggerResponse(404, "Member not found")]
[SwaggerResponse(401, "Unauthorized")]
public async Task> GetProgress(Guid id)
{
var progress = await _mediator.Send(new GetMemberProgressQuery(id));
if (progress == null)
{
return NotFound(new { message = $"Member {id} not found" });
}
return Ok(progress);
}
///
/// EN: Get member's experience history.
/// VI: Lấy lịch sử EXP của member.
///
[HttpGet("{id:guid}/experience")]
[SwaggerOperation(Summary = "Get experience history", Description = "Retrieves member's experience transaction history")]
[SwaggerResponse(200, "History retrieved", typeof(ExperienceHistoryResult))]
[SwaggerResponse(401, "Unauthorized")]
public async Task> GetExperienceHistory(
Guid id,
[FromQuery] int pageIndex = 0,
[FromQuery] int pageSize = 20)
{
var result = await _mediator.Send(new GetExperienceHistoryQuery(id, pageIndex, pageSize));
return Ok(result);
}
private Guid? GetCurrentUserId()
{
var userIdClaim = User.FindFirst("sub")?.Value ?? User.FindFirst("id")?.Value;
if (Guid.TryParse(userIdClaim, out var userId))
{
return userId;
}
return null;
}
}