using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using StickyBoard.Api.Common; using StickyBoard.Core.DTOs.Common; using StickyBoard.Core.DTOs.UsersAndAuth; using StickyBoard.Core.Models; using StickyBoard.Core.Services.UsersAndAuth; namespace StickyBoard.Api.Controllers; [ApiController] [Route("api/[controller]")] [Authorize] public sealed class UsersController : ControllerBase { private readonly UserService _users; public UsersController(UserService users) { _users = users; } // ------------------------------------------------------------ // GET CURRENT USER // ------------------------------------------------------------ [HttpGet("me")] public async Task>> GetMe(CancellationToken ct) { var userId = User.GetUserId(); if (userId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); var me = await _users.GetSelfAsync(userId, ct); return me is not null ? Ok(ApiResponseDto.Ok(me)) : NotFound(ApiResponseDto.Fail("User not found.")); } // ------------------------------------------------------------ // UPDATE PROFILE (self) // ------------------------------------------------------------ [HttpPut("me")] public async Task>> UpdateProfile([FromBody] UserUpdateDto dto, CancellationToken ct) { var userId = User.GetUserId(); if (userId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); var ok = await _users.UpdateProfileAsync(userId, dto, ct); return ok ? Ok(ApiResponseDto.Ok(new { success = true })) : NotFound(ApiResponseDto.Fail("User not found.")); } // ------------------------------------------------------------ // CHANGE PASSWORD (self) // ------------------------------------------------------------ [HttpPut("me/password")] public async Task>> ChangePassword([FromBody] ChangePasswordDto dto, CancellationToken ct) { var userId = User.GetUserId(); if (userId == Guid.Empty) return Unauthorized(ApiResponseDto.Fail("Invalid or missing token.")); await _users.ChangePasswordAsync(userId, dto, ct); return Ok(ApiResponseDto.Ok(new { success = true })); } // ------------------------------------------------------------ // SEARCH USERS (display name) // ------------------------------------------------------------ [HttpGet("search")] public async Task>>> Search([FromQuery] string q, CancellationToken ct) { if (string.IsNullOrWhiteSpace(q)) return BadRequest(ApiResponseDto>.Fail("Query parameter 'q' is required.")); var list = await _users.SearchAsync(q, ct); return Ok(ApiResponseDto>.Ok(list)); } // ------------------------------------------------------------ // ADMIN: GET USER BY ID // ------------------------------------------------------------ [HttpGet("{id:guid}")] [Authorize(Roles = "admin")] public async Task>> GetById(Guid id, CancellationToken ct) { var u = await _users.GetAsync(id, ct); return u is not null ? Ok(ApiResponseDto.Ok(u)) : NotFound(ApiResponseDto.Fail("User not found.")); } // ------------------------------------------------------------ // ADMIN: UPDATE ROLE // ------------------------------------------------------------ [HttpPut("{id:guid}/role")] [Authorize(Roles = "admin")] public async Task>> UpdateRole(Guid id, [FromQuery] UserRole role, CancellationToken ct) { var ok = await _users.UpdateRoleAsync(id, role, ct); return ok ? Ok(ApiResponseDto.Ok(new { success = true })) : NotFound(ApiResponseDto.Fail("User not found.")); } // ------------------------------------------------------------ // ADMIN: DELETE USER // ------------------------------------------------------------ [HttpDelete("{id:guid}")] [Authorize(Roles = "admin")] public async Task>> Delete(Guid id, CancellationToken ct) { var ok = await _users.DeleteAsync(id, ct); return ok ? Ok(ApiResponseDto.Ok(new { success = true })) : NotFound(ApiResponseDto.Fail("User not found.")); } }