using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Nuuru.Server.Data; using Nuuru.Server.DTOs; using Nuuru.Server.Extensions; using Nuuru.Server.Services; namespace Nuuru.Server.Controllers { [ApiController] [Route("api/stats")] public class StatsController : ControllerBase { private readonly ApplicationDbContext _context; private readonly IUserBadgeService _userBadgeService; private readonly ILogger _logger; public StatsController( ApplicationDbContext context, IUserBadgeService userBadgeService, ILogger logger) { _context = context; _userBadgeService = userBadgeService; _logger = logger; } /// /// Get global site statistics /// [HttpGet] [AllowAnonymous] public async Task GetGlobalStats() { try { // Run count queries in parallel var galleryPostCountTask = _context.BooruPosts.CountAsync(); var tagCountTask = _context.BooruTags.CountAsync(); var threadCountTask = _context.ForumThreads.CountAsync(); var forumPostCountTask = _context.ForumPosts.CountAsync(); // Get 3 most recent threads with author and category info var recentThreadsTask = _context.ForumThreads .Include(t => t.Author) .Include(t => t.Category) .OrderByDescending(t => t.CreatedAt) .Take(3) .AsSplitQuery() .ToListAsync(); await Task.WhenAll( galleryPostCountTask, tagCountTask, threadCountTask, forumPostCountTask, recentThreadsTask ); var recentThreads = await recentThreadsTask; // Batch-fetch display info for thread authors var authorIds = recentThreads .Where(t => t.Author != null) .Select(t => t.Author!.Id) .Distinct(); var displayInfoMap = await _userBadgeService.GetUsersDisplayInfoAsync(authorIds); var recentThreadDtos = recentThreads.ToDto(includeFirstPost: false, requestingUserId: null, displayInfoMap: displayInfoMap); return Ok(new GlobalStatsDto { GalleryPostCount = await galleryPostCountTask, TagCount = await tagCountTask, ThreadCount = await threadCountTask, ForumPostCount = await forumPostCountTask, RecentThreads = recentThreadDtos }); } catch (Exception ex) { _logger.LogError(ex, "Error retrieving global stats"); return StatusCode(500, new { error = "Failed to retrieve global stats" }); } } } }