using Distribution.Features.Auth; using Distribution.Infra.UoW; namespace Distribution.Features.User; public class UserService(IUserRepository repo, IUnitOfWork uow, IAuthHexClient authHex) { private static UserResponse ToResponse(Models.User u) => new(u.Id, u.Username, u.FullName, u.FK_RoleId, u.Role?.Name ?? string.Empty, u.FK_ReportsToUserId, u.IsActive, u.CreatedAt, u.UpdatedAt); public async Task> GetAllAsync() => (await repo.GetAllAsync()) .Where(u => u.IsActive) .Select(ToResponse) .ToList(); public async Task GetByIdAsync(Guid id) { var user = await repo.GetByIdAsync(id); if (user is null || !user.IsActive) return null; return ToResponse(user); } public async Task CreateAsync(CreateUserRequest request, CancellationToken ct = default) { var user = new Models.User { Username = request.Username, FullName = request.FullName, FK_RoleId = request.RoleId, FK_ReportsToUserId = request.ReportsToUserId }; await uow.BeginAsync(ct); try { await repo.AddAsync(user); var authResult = await authHex.CallAsync("registerUser", new { userId = user.Id, userName = request.Username, email = request.Username, fullname = request.FullName, password = request.Password, roleId = request.RoleId.ToString(), userTypeId = "00000001-0000-0000-0000-200000000000", sendCredentialsEmail = false }, reference: user.Id.ToString(), ct: ct); if (!authResult.Success) { await uow.RollbackAsync(ct); throw new InvalidOperationException($"AuthHex registration failed: {authResult.Message}"); } await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return ToResponse(user); } public async Task UpdateAsync(Guid id, UpdateUserRequest request, CancellationToken ct = default) { var user = await repo.GetByIdAsync(id); if (user is null || !user.IsActive) return null; user.FullName = request.FullName; if (!string.IsNullOrWhiteSpace(request.Username)) user.Username = request.Username; if (request.RoleId.HasValue) user.FK_RoleId = request.RoleId.Value; user.UpdatedAt = DateTime.Now; await uow.BeginAsync(ct); try { repo.Update(user); var hasUsernameChange = !string.IsNullOrWhiteSpace(request.Username); var hasRoleChange = request.RoleId.HasValue; if (hasUsernameChange || hasRoleChange) { var payload = new Dictionary { ["userId"] = user.Id.ToString() }; if (hasUsernameChange) payload["userName"] = request.Username!; if (hasRoleChange) payload["roleCode"] = request.RoleId!.Value.ToString(); var authResult = await authHex.CallAsync("UpdateUser", payload, reference: user.Id.ToString(), ct: ct); if (!authResult.Success) { await uow.RollbackAsync(ct); throw new InvalidOperationException($"AuthHex update failed: {authResult.Message}"); } } if (!string.IsNullOrWhiteSpace(request.CurrentPassword) && !string.IsNullOrWhiteSpace(request.NewPassword)) { var authResult = await authHex.CallAsync("ChangeUserPassword", new { userId = user.Id.ToString(), currentPassword = request.CurrentPassword, newPassword = request.NewPassword }, reference: user.Id.ToString(), ct: ct); if (!authResult.Success) { await uow.RollbackAsync(ct); throw new InvalidOperationException($"AuthHex password change failed: {authResult.Message}"); } } await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return ToResponse(user); } public async Task AssignRoleAsync(Guid id, AssignUserRoleRequest request, CancellationToken ct = default) { return await UpdateAsync(id, new UpdateUserRequest( FullName: (await repo.GetByIdAsync(id))?.FullName ?? string.Empty, RoleId: request.RoleId), ct); } public async Task AssignScopeAsync(Guid id, AssignUserScopeRequest request, CancellationToken ct = default) { var user = await repo.GetByIdAsync(id); if (user is null || !user.IsActive) return false; await uow.BeginAsync(ct); try { await repo.ReplaceRegionScopesAsync(id, request.RegionIds); await repo.ReplaceRouteScopesAsync(id, request.RouteIds); await repo.ReplaceStoreScopesAsync(id, request.StoreIds); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return true; } public async Task DeactivateAsync(Guid id, CancellationToken ct = default) { var user = await repo.GetByIdAsync(id); if (user is null || !user.IsActive) return false; await uow.BeginAsync(ct); try { repo.Remove(user); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return true; } }