using eprintServer.Data; using eprintServer.Entities; using eprintServer.Requests; using eprintServer.DTOs; // Need this for DynamicValueDto using Microsoft.EntityFrameworkCore; using System.Linq; using System.Collections.Generic; using System.Threading.Tasks; using System; namespace eprintServer.Services; public class BlogService { private readonly DataContext _context; public BlogService(DataContext context) { _context = context; } // Helper method to convert DTOs to Entities for DynamicValues private List ConvertDynamicValueDtosToEntities(List dtos) { return dtos.Select(dv => new DynamicValue { LanguageTag = dv.LanguageTag, Value = dv.Value }).ToList(); } // Includes the Image navigation property AND the DynamicValue lists private IQueryable GetBlogsWithImageAndDynamic() { return _context.Blogs .Include(b => b.Image) // Eager load the new dynamic lists .Include(b => b.TitleDynamic) .Include(b => b.ContentDynamic); } public async Task> GetAllBlogPostsAsync() { return await GetBlogsWithImageAndDynamic().ToListAsync(); } public async Task GetBlogPostByIdAsync(int blogId) { return await GetBlogsWithImageAndDynamic().FirstOrDefaultAsync(b => b.Id == blogId); } public async Task CreateBlogPostAsync(CreateBlogPostRequest request) { var blog = new Blog { // Map dynamic fields from request DTOs TitleDynamic = ConvertDynamicValueDtosToEntities(request.TitleDynamic), ContentDynamic = ConvertDynamicValueDtosToEntities(request.ContentDynamic), Published = request.Published, }; _context.Blogs.Add(blog); await _context.SaveChangesAsync(); // Return the fully loaded blog post return await GetBlogPostByIdAsync(blog.Id) ?? blog; } /// /// Updates an existing Blog Post, applying changes only for non-null request properties. /// public async Task UpdateBlogPostAsync(int blogId, UpdateBlogPostRequest request) { // Load the blog including dynamic values var blog = await GetBlogsWithImageAndDynamic().FirstOrDefaultAsync(b => b.Id == blogId); if (blog == null) { return null; } bool changed = false; // --- Existing Hardcoded Fields Update --- if (request.Author != null) { blog.Author = request.Author; changed = true; } // --- START: Dynamic Localized Content Update (NEW) --- // Check if the list itself was provided (even if empty, it signifies a complete replacement) if (request.TitleDynamic != null) { // 1. Remove old DynamicValue entities associated with this list _context.DynamicValues.RemoveRange(blog.TitleDynamic); // 2. Clear navigation property list blog.TitleDynamic.Clear(); // 3. Add new DynamicValue entities if (request.TitleDynamic.Any()) { blog.TitleDynamic.AddRange(ConvertDynamicValueDtosToEntities(request.TitleDynamic)); } changed = true; } if (request.ContentDynamic != null) { // 1. Remove old DynamicValue entities associated with this list _context.DynamicValues.RemoveRange(blog.ContentDynamic); // 2. Clear navigation property list blog.ContentDynamic.Clear(); // 3. Add new DynamicValue entities if (request.ContentDynamic.Any()) { blog.ContentDynamic.AddRange(ConvertDynamicValueDtosToEntities(request.ContentDynamic)); } changed = true; } // --- END: Dynamic Localized Content Update --- // Update the Published status (always provided in UpdateBlogPostRequest) if (blog.Published != request.Published) { blog.Published = request.Published; changed = true; } if (changed) { blog.UpdatedAt = DateTime.UtcNow; _context.Blogs.Update(blog); await _context.SaveChangesAsync(); } // Return the fully loaded blog after update return await GetBlogPostByIdAsync(blogId); } public async Task UpdateBlogImageAsync(int blogId, FileModel fileModel) { var blog = await GetBlogPostByIdAsync(blogId); if (blog == null) { return null; } blog.SetImage(fileModel); blog.UpdatedAt = DateTime.UtcNow; _context.Blogs.Update(blog); await _context.SaveChangesAsync(); return blog; } public async Task ToggleBlogPostStatusAsync(int blogId, bool newStatus) { var blog = await GetBlogPostByIdAsync(blogId); if (blog == null) { return null; } if (blog.Published != newStatus) { blog.Published = newStatus; blog.UpdatedAt = DateTime.UtcNow; _context.Blogs.Update(blog); await _context.SaveChangesAsync(); } return blog; } public async Task DeleteBlogPostAsync(int blogId) { // Load dynamic values to ensure proper cascade delete for related entities var blog = await GetBlogsWithImageAndDynamic().FirstOrDefaultAsync(b => b.Id == blogId); if (blog == null) { return false; } _context.Blogs.Remove(blog); await _context.SaveChangesAsync(); return true; } }