using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using LingAdmin.API.Data; using LingAdmin.API.Models; using LingAdmin.API.DTOs; using LingAdmin.API.Services; using Dapr.Client; namespace LingAdmin.API.Controllers; [ApiController] [Route("api/[controller]")] public class UsersController : ControllerBase { private readonly AppDbContext _context; private readonly DaprClient _daprClient; private readonly IPasswordHasher _passwordHasher; private readonly ILogger _logger; public UsersController( AppDbContext context, DaprClient daprClient, IPasswordHasher passwordHasher, ILogger logger) { _context = context; _daprClient = daprClient; _passwordHasher = passwordHasher; _logger = logger; } [HttpGet] public async Task>>> GetUsers() { try { var users = await _context.Users .Select(u => new UserDto { Id = u.Id, Name = u.Name, Email = u.Email, Role = u.Role, Status = u.Status, CreatedAt = u.CreatedAt, LastLoginAt = u.LastLoginAt }) .ToListAsync(); return Ok(ApiResponse>.Success(users)); } catch (Exception ex) { _logger.LogError(ex, "Error retrieving users"); return StatusCode(500, ApiResponse>.Error("Internal server error", 500)); } } [HttpGet("{id}")] public async Task>> GetUser(int id) { try { var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.Error("User not found", 404)); } var userDto = new UserDto { Id = user.Id, Name = user.Name, Email = user.Email, Role = user.Role, Status = user.Status, CreatedAt = user.CreatedAt, LastLoginAt = user.LastLoginAt }; return Ok(ApiResponse.Success(userDto)); } catch (Exception ex) { _logger.LogError(ex, "Error retrieving user {Id}", id); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPut("{id}")] public async Task>> UpdateUser(int id, UpdateUserDto updateDto) { try { var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.Error("User not found", 404)); } // Update only provided fields if (!string.IsNullOrWhiteSpace(updateDto.Name)) user.Name = updateDto.Name; if (!string.IsNullOrWhiteSpace(updateDto.Email)) { // Check if email is already in use if (await _context.Users.AnyAsync(u => u.Email == updateDto.Email && u.Id != id)) { return BadRequest(ApiResponse.Error("Email already in use", 400)); } user.Email = updateDto.Email; } if (!string.IsNullOrWhiteSpace(updateDto.Role)) user.Role = updateDto.Role; if (!string.IsNullOrWhiteSpace(updateDto.Status)) user.Status = updateDto.Status; await _context.SaveChangesAsync(); // Publish update event await _daprClient.PublishEventAsync("pubsub", "user-updated", new { userId = user.Id, email = user.Email, timestamp = DateTime.UtcNow }); var userDto = new UserDto { Id = user.Id, Name = user.Name, Email = user.Email, Role = user.Role, Status = user.Status, CreatedAt = user.CreatedAt, LastLoginAt = user.LastLoginAt }; return Ok(ApiResponse.Success(userDto)); } catch (Exception ex) { _logger.LogError(ex, "Error updating user {Id}", id); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpDelete("{id}")] public async Task>> DeleteUser(int id) { try { var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.Error("User not found", 404)); } _context.Users.Remove(user); await _context.SaveChangesAsync(); // Publish delete event await _daprClient.PublishEventAsync("pubsub", "user-deleted", new { userId = id, email = user.Email, timestamp = DateTime.UtcNow }); return Ok(ApiResponse.Success(new { message = "User deleted successfully" })); } catch (Exception ex) { _logger.LogError(ex, "Error deleting user {Id}", id); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } }