using System.Security.Claims; using HelpDesk.Data.Repositories; using HelpDesk.Models.DTOs; using HelpDesk.Models.Entities; using HelpDesk.Models.Enums; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace HelpDesk.API.Controllers; [ApiController] [Route("api/[controller]")] [Authorize] public class UsersController : ControllerBase { private readonly IUserRepository _userRepository; public UsersController(IUserRepository userRepository) { _userRepository = userRepository; } [HttpGet] [Authorize(Policy = "Admin")] public async Task>> GetUsers() { var users = await _userRepository.GetAllAsync(); return Ok(users.Select(MapToDto)); } [HttpGet("agents")] public async Task>> GetAgents() { var agents = await _userRepository.GetByRoleAsync(UserRole.Agent); return Ok(agents.Select(MapToDto)); } [HttpGet("{id}")] public async Task> GetUser(Guid id) { var user = await _userRepository.GetByIdAsync(id); if (user == null) return NotFound(new { error = "User not found." }); return Ok(MapToDto(user)); } [HttpPut("{id}")] public async Task> UpdateUser(Guid id, [FromBody] UpdateUserRequest request) { var currentUserId = GetUserId(); if (currentUserId == null) return Unauthorized(); var currentUser = await _userRepository.GetByIdAsync(currentUserId.Value); if (currentUser == null) return Unauthorized(); // Users can update themselves; Admins/SuperAdmins can update others if (currentUserId.Value != id && currentUser.Role < UserRole.Admin) return Forbid(); var user = await _userRepository.GetByIdAsync(id); if (user == null) return NotFound(new { error = "User not found." }); if (request.FirstName != null) user.FirstName = request.FirstName; if (request.LastName != null) user.LastName = request.LastName; if (request.Email != null) user.Email = request.Email; if (request.PhoneNumber != null) user.PhoneNumber = request.PhoneNumber; if (request.AvatarUrl != null) user.AvatarUrl = request.AvatarUrl; // Only admins can change role and active status if (currentUser.Role >= UserRole.Admin) { if (request.Role.HasValue) user.Role = request.Role.Value; if (request.IsActive.HasValue) user.IsActive = request.IsActive.Value; } var updated = await _userRepository.UpdateAsync(user); if (updated == null) return StatusCode(500, new { error = "Failed to update user." }); return Ok(MapToDto(updated)); } private Guid? GetUserId() { var claim = User.FindFirst("userId") ?? User.FindFirst(ClaimTypes.NameIdentifier); return claim != null && Guid.TryParse(claim.Value, out var id) ? id : null; } private static UserDto MapToDto(User u) => new() { Id = u.Id, Email = u.Email, FirstName = u.FirstName, LastName = u.LastName, Role = u.Role, IsActive = u.IsActive, CreatedAt = u.CreatedAt, PhoneNumber = u.PhoneNumber, AvatarUrl = u.AvatarUrl }; }