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; } }