// eprintServer/Services/FaqService.cs using eprintServer.Data; using eprintServer.Entities; using eprintServer.Requests; using eprintServer.Responses; using Microsoft.EntityFrameworkCore; using System.Linq; using System.Collections.Generic; // Added for List using System; // Added for DateTime.UtcNow namespace eprintServer.Services; public class FaqService { private readonly DataContext _context; public FaqService(DataContext context) { _context = context; } // Helper to include DynamicValues for all GET operations private IQueryable GetFaqsQuery() { return _context.Faqs .Include(f => f.Question) .Include(f => f.Answer); } public async Task> GetAllFaqsAsync() { return await GetFaqsQuery().ToListAsync(); } public async Task GetFaqByIdAsync(int faqId) { return await GetFaqsQuery().FirstOrDefaultAsync(f => f.Id == faqId); } public async Task CreateFaqAsync(CreateFaqRequest request) { var faq = new Faq { QuestionEN = request.QuestionEN, QuestionAR = request.QuestionAR, AnswerEN = request.AnswerEN, AnswerAR = request.AnswerAR, Active = request.Active, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow, Question = request.Question.Select(dv => new DynamicValue { Value = dv.Value, LanguageTag = dv.LanguageTag }).ToList(), Answer = request.Answer.Select(dv => new DynamicValue { Value = dv.Value, LanguageTag = dv.LanguageTag }).ToList() }; _context.Faqs.Add(faq); // Now that the schema is fixed (nullable FKs), a single SaveChangesAsync call works // to save the parent (Faq) and all attached children (DynamicValue). await _context.SaveChangesAsync(); // The current response returns the 'faq' object created here. Since the // DynamicValue lists were populated from the request, the response should now be correct. return faq; } public async Task> GetFaqsPaginatedAsync(int page, int size) { page = Math.Max(0, page); size = Math.Max(1, size); var query = GetFaqsQuery(); var totalCount = await query.CountAsync(); var faqs = await query .OrderByDescending(f => f.CreatedAt) .Skip(page * size) .Take(size) .ToListAsync(); return new PagedResult(faqs, totalCount, page, size); } public async Task UpdateFaqAsync(int faqId, UpdateFaqRequest request) { var faq = await GetFaqsQuery().FirstOrDefaultAsync(f => f.Id == faqId); if (faq == null) { return null; } bool changed = false; // Updates for legacy string properties if (request.QuestionEN != null) { faq.QuestionEN = request.QuestionEN; changed = true; } if (request.QuestionAR != null) { faq.QuestionAR = request.QuestionAR; changed = true; } if (request.AnswerEN != null) { faq.AnswerEN = request.AnswerEN; changed = true; } if (request.AnswerAR != null) { faq.AnswerAR = request.AnswerAR; changed = true; } // NEW: Logic to update Question DynamicValues if (request.Question != null) { // Delete old dynamic values associated with this question _context.DynamicValues.RemoveRange(faq.Question); faq.Question.Clear(); // Add new dynamic values faq.Question.AddRange(request.Question.Select(dv => new DynamicValue { LanguageTag = dv.LanguageTag, Value = dv.Value })); changed = true; } // NEW: Logic to update Answer DynamicValues if (request.Answer != null) { // Delete old dynamic values associated with this answer _context.DynamicValues.RemoveRange(faq.Answer); faq.Answer.Clear(); // Add new dynamic values faq.Answer.AddRange(request.Answer.Select(dv => new DynamicValue { LanguageTag = dv.LanguageTag, Value = dv.Value })); changed = true; } if (request.Active.HasValue && faq.Active != request.Active.Value) { faq.Active = request.Active.Value; changed = true; } if (changed) { faq.UpdatedAt = DateTime.UtcNow; _context.Faqs.Update(faq); await _context.SaveChangesAsync(); } return await GetFaqByIdAsync(faqId); } public async Task ToggleFaqStatusAsync(int faqId, bool newStatus) { var faq = await _context.Faqs .Include(f => f.Question) .Include(f => f.Answer) .FirstOrDefaultAsync(f => f.Id == faqId); if (faq == null) { return null; } if (faq.Active != newStatus) { faq.Active = newStatus; faq.UpdatedAt = DateTime.UtcNow; _context.Faqs.Update(faq); await _context.SaveChangesAsync(); } return faq; } public async Task DeleteFaqAsync(int faqId) { var faq = await _context.Faqs.FindAsync(faqId); if (faq == null) { return false; } _context.Faqs.Remove(faq); await _context.SaveChangesAsync(); return true; } }