using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Haoliang.Core.Services; using Haoliang.Models.User; using Haoliang.Models.Common; namespace Haoliang.Api.Controllers { [ApiController] [Route("api/v1/[controller]")] public class AuthController : ControllerBase { private readonly IAuthService _authService; private readonly IUserService _userService; private readonly IPermissionService _permissionService; private readonly ILoggingService _loggingService; public AuthController( IAuthService authService, IUserService userService, IPermissionService permissionService, ILoggingService loggingService) { _authService = authService; _userService = userService; _permissionService = permissionService; _loggingService = loggingService; } [HttpPost("login")] public async Task Login([FromBody] LoginRequest request) { try { if (!ModelState.IsValid) { return BadRequest(ApiResponse.Error("Invalid request data", 400)); } var result = await _authService.LoginAsync(request); if (result.Success) { await _loggingService.LogInformationAsync($"User {request.Username} logged in successfully"); return Ok(ApiResponse.Success(result)); } else { await _loggingService.LogWarningAsync($"Failed login attempt for user {request.Username}"); return Unauthorized(ApiResponse.Error("Invalid username or password", 401)); } } catch (Exception ex) { await _loggingService.LogErrorAsync($"Login error for user {request.Username}: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPost("logout")] public async Task Logout([FromBody] LogoutRequest request) { try { if (request?.UserId == null) { return BadRequest(ApiResponse.Error("User ID is required", 400)); } var success = await _authService.LogoutAsync(request.UserId.Value); if (success) { await _loggingService.LogInformationAsync($"User {request.UserId} logged out successfully"); return Ok(ApiResponse.Success(true)); } else { return BadRequest(ApiResponse.Error("Logout failed", 400)); } } catch (Exception ex) { await _loggingService.LogErrorAsync($"Logout error: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPost("refresh")] public async Task RefreshToken([FromBody] RefreshTokenRequest request) { try { if (!ModelState.IsValid) { return BadRequest(ApiResponse.Error("Invalid request data", 400)); } var result = await _authService.RefreshTokenAsync(request.RefreshToken); if (result.Success) { return Ok(ApiResponse.Success(result)); } else { return Unauthorized(ApiResponse.Error("Invalid refresh token", 401)); } } catch (Exception ex) { await _loggingService.LogErrorAsync($"Token refresh error: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPost("register")] public async Task Register([FromBody] RegisterRequest request) { try { if (!ModelState.IsValid) { return BadRequest(ApiResponse.Error("Invalid request data", 400)); } // Check if username already exists var usernameExists = await _authService.UsernameExistsAsync(request.Username); if (usernameExists) { return BadRequest(ApiResponse.Error("Username already exists", 400)); } // Check if email already exists var emailExists = await _authService.EmailExistsAsync(request.Email); if (emailExists) { return BadRequest(ApiResponse.Error("Email already exists", 400)); } // Create user var user = new User { Username = request.Username, Email = request.Email, PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password), FirstName = request.FirstName, LastName = request.LastName, Department = request.Department, IsActive = true, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now }; var userViewModel = await _userService.CreateUserAsync(user); await _loggingService.LogInformationAsync($"New user registered: {request.Username}"); return Ok(ApiResponse.Success(userViewModel)); } catch (Exception ex) { await _loggingService.LogErrorAsync($"Registration error for user {request.Username}: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpGet("profile")] public async Task GetProfile() { try { // Get user ID from claims (in real implementation, use JWT token validation) var userId = GetCurrentUserId(); if (userId == null) { return Unauthorized(ApiResponse.Error("Not authenticated", 401)); } var user = await _userService.GetUserByIdAsync(userId.Value); if (user == null) { return NotFound(ApiResponse.Error("User not found", 404)); } return Ok(ApiResponse.Success(user)); } catch (Exception ex) { await _loggingService.LogErrorAsync($"Profile fetch error: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPut("profile")] public async Task UpdateProfile([FromBody] UpdateUserProfileRequest request) { try { if (!ModelState.IsValid) { return BadRequest(ApiResponse.Error("Invalid request data", 400)); } var userId = GetCurrentUserId(); if (userId == null) { return Unauthorized(ApiResponse.Error("Not authenticated", 401)); } var user = new User { Username = request.Username, Email = request.Email, FirstName = request.FirstName, LastName = request.LastName, Department = request.Department, UpdatedAt = DateTime.Now }; var updatedUser = await _userService.UpdateUserAsync(userId.Value, user); await _loggingService.LogInformationAsync($"User profile updated: {request.Username}"); return Ok(ApiResponse.Success(updatedUser)); } catch (Exception ex) { await _loggingService.LogErrorAsync($"Profile update error: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPost("change-password")] public async Task ChangePassword([FromBody] ChangePasswordRequest request) { try { if (!ModelState.IsValid) { return BadRequest(ApiResponse.Error("Invalid request data", 400)); } var userId = GetCurrentUserId(); if (userId == null) { return Unauthorized(ApiResponse.Error("Not authenticated", 401)); } var success = await _userService.ChangePasswordAsync( userId.Value, request.OldPassword, request.NewPassword); if (success) { await _loggingService.LogInformationAsync($"Password changed for user: {userId}"); return Ok(ApiResponse.Success(true)); } else { return BadRequest(ApiResponse.Error("Invalid old password", 400)); } } catch (Exception ex) { await _loggingService.LogErrorAsync($"Password change error: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpGet("permissions")] public async Task GetUserPermissions() { try { var userId = GetCurrentUserId(); if (userId == null) { return Unauthorized(ApiResponse>.Error("Not authenticated", 401)); } var permissions = await _permissionService.GetUserPermissionsAsync(userId.Value); return Ok(ApiResponse>.Success(permissions)); } catch (Exception ex) { await _loggingService.LogErrorAsync($"Permission fetch error: {ex.Message}", ex); return StatusCode(500, ApiResponse>.Error("Internal server error", 500)); } } [HttpGet("users")] [ProducesResponseType(typeof(PaginatedResponse), 200)] public async Task GetAllUsers([FromQuery] UserFilter filter) { try { var users = await _userService.GetAllUsersAsync(); // Apply filters if (!string.IsNullOrEmpty(filter.Role)) { users = users.Where(u => u.Role == filter.Role); } if (!string.IsNullOrEmpty(filter.Department)) { users = users.Where(u => u.Department == filter.Department); } if (filter.IsActive.HasValue) { users = users.Where(u => u.IsActive == filter.IsActive.Value); } var totalCount = users.Count(); // Apply pagination var pagedUsers = users .Skip((filter.PageNumber - 1) * filter.PageSize) .Take(filter.PageSize) .ToList(); var response = new PaginatedResponse { Items = pagedUsers, TotalCount = totalCount, PageNumber = filter.PageNumber, PageSize = filter.PageSize, TotalPages = (int)Math.Ceiling((double)totalCount / filter.PageSize), HasPreviousPage = filter.PageNumber > 1, HasNextPage = filter.PageNumber < (int)Math.Ceiling((double)totalCount / filter.PageSize) }; return Ok(response); } catch (Exception ex) { await _loggingService.LogErrorAsync($"Users fetch error: {ex.Message}", ex); return StatusCode(500, ApiResponse>.Error("Internal server error", 500)); } } [HttpGet("users/{id}")] public async Task GetUserById(int id) { try { var user = await _userService.GetUserByIdAsync(id); if (user == null) { return NotFound(ApiResponse.Error("User not found", 404)); } return Ok(ApiResponse.Success(user)); } catch (Exception ex) { await _loggingService.LogErrorAsync($"User fetch error for ID {id}: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPost("users/{id}/activate")] public async Task ActivateUser(int id) { try { var success = await _userService.ActivateUserAsync(id); if (success) { await _loggingService.LogInformationAsync($"User activated: {id}"); return Ok(ApiResponse.Success(true)); } else { return BadRequest(ApiResponse.Error("Failed to activate user", 400)); } } catch (Exception ex) { await _loggingService.LogErrorAsync($"User activation error for ID {id}: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } [HttpPost("users/{id}/deactivate")] public async Task DeactivateUser(int id) { try { var success = await _userService.DeactivateUserAsync(id); if (success) { await _loggingService.LogInformationAsync($"User deactivated: {id}"); return Ok(ApiResponse.Success(true)); } else { return BadRequest(ApiResponse.Error("Failed to deactivate user", 400)); } } catch (Exception ex) { await _loggingService.LogErrorAsync($"User deactivation error for ID {id}: {ex.Message}", ex); return StatusCode(500, ApiResponse.Error("Internal server error", 500)); } } private int? GetCurrentUserId() { // In a real implementation, extract user ID from JWT token claims // For now, return null (would be implemented in JWT middleware) return null; } } // Supporting request and response models public class LoginRequest { public string Username { get; set; } public string Password { get; set; } public bool RememberMe { get; set; } } public class LogoutRequest { public int UserId { get; set; } } public class RefreshTokenRequest { public string RefreshToken { get; set; } } public class RegisterRequest { public string Username { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Department { get; set; } } public class UpdateUserProfileRequest { public string Username { get; set; } public string Email { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Department { get; set; } } public class ChangePasswordRequest { public string OldPassword { get; set; } public string NewPassword { get; set; } public string ConfirmPassword { get; set; } } public class UserFilter { public int PageNumber { get; set; } = 1; public int PageSize { get; set; } = 10; public string Role { get; set; } public string Department { get; set; } public bool? IsActive { get; set; } } }