using System.Security.Claims; using FluentResults; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using NexusReader.Application.DTOs.User; using NexusReader.Data.Persistence; using NexusReader.Domain.Entities; using NexusReader.UI.Shared.Services; namespace NexusReader.Web.New.Services; public class ServerIdentityService : IIdentityService { private readonly UserManager _userManager; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IDbContextFactory _dbContextFactory; public event Func? OnStateInvalidated; public ServerIdentityService( UserManager userManager, IHttpContextAccessor httpContextAccessor, IDbContextFactory dbContextFactory) { _userManager = userManager; _httpContextAccessor = httpContextAccessor; _dbContextFactory = dbContextFactory; } public Task LoginAsync(string email, string password, bool rememberMe = false) => throw new NotSupportedException("Use standard Identity endpoints for login on server."); public Task LogoutAsync() => throw new NotSupportedException("Use standard Identity endpoints for logout on server."); public Task RegisterAsync(string email, string password) => throw new NotSupportedException("Use standard Identity endpoints for registration on server."); public Task RefreshTokenAsync() => Task.FromResult(Result.Ok()); public async Task> GetProfileAsync() { var user = _httpContextAccessor.HttpContext?.User; if (user == null || !user.Identity?.IsAuthenticated == true) return Result.Fail("Not authenticated."); var userId = user.FindFirstValue(ClaimTypes.NameIdentifier); if (userId == null) return Result.Fail("User ID not found."); using var dbContext = await _dbContextFactory.CreateDbContextAsync(); var profile = await dbContext.Users .Where(u => u.Id == userId) .Select(u => new UserProfile( u.Email ?? string.Empty, u.AITokensUsed, u.TenantId != null && u.TenantId.Length == 36 ? new Guid(u.TenantId) : Guid.Empty, u.SubscriptionPlan != null ? new SubscriptionPlanDto { Id = u.SubscriptionPlan.Id, Name = u.SubscriptionPlan.PlanName, AITokenLimit = u.SubscriptionPlan.AITokenLimit, MonthlyPrice = u.SubscriptionPlan.MonthlyPrice } : new SubscriptionPlanDto(), u.QuizResults.Any(q => q.TotalQuestions > 0) ? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100) : 0, u.Ebooks.OrderByDescending(e => e.LastReadDate).Select(e => new LastReadBookDto { Id = e.Id, Title = e.Title, Author = new AuthorDto { Id = e.Author.Id, Name = e.Author.Name }, CoverUrl = e.CoverUrl, Progress = 65, // Hardcoded for now as per design requirements, will link to real segments later LastChapter = "Chapter 4: Renaissance in Italy" }).FirstOrDefault() )) .FirstOrDefaultAsync(); return profile != null ? Result.Ok(profile) : Result.Fail("Profile not found."); } }