using InboxIntel.Application.Abstractions; using Microsoft.AspNetCore.Mvc; namespace InboxIntel.Api.Controllers; public class AnalyticsController : ApiControllerBase { private readonly IAnalyticsService _analytics; public AnalyticsController(IAnalyticsService analytics) => _analytics = analytics; [HttpGet("dashboard")] public async Task Dashboard(CancellationToken ct) => Ok(await _analytics.GetDashboardAsync(UserId, ct)); [HttpGet("health")] public async Task Health(CancellationToken ct) => Ok(await _analytics.GetInboxHealthAsync(UserId, ct)); [HttpGet("top-senders")] public async Task TopSenders([FromQuery] int take = 20, CancellationToken ct = default) // V-10: clamp to a sane bound (the SPA legitimately requests up to 5000 to list // all senders) so a caller cannot force an unbounded scan. => Ok(await _analytics.GetTopSendersAsync(UserId, Math.Clamp(take, 1, 5000), ct)); [HttpGet("volume")] public async Task Volume([FromQuery] int days = 90, CancellationToken ct = default) => Ok(await _analytics.GetVolumeOverTimeAsync(UserId, Math.Clamp(days, 1, 3660), ct)); [HttpGet("heatmap")] public async Task Heatmap(CancellationToken ct) => Ok(await _analytics.GetHeatmapAsync(UserId, ct)); [HttpGet("category-heatmap")] public async Task CategoryHeatmap(CancellationToken ct) => Ok(await _analytics.GetCategoryHeatmapAsync(UserId, ct)); [HttpGet("attachments")] public async Task Attachments(CancellationToken ct) => Ok(await _analytics.GetAttachmentBreakdownAsync(UserId, ct)); [HttpGet("sidebar-counts")] public async Task SidebarCounts(CancellationToken ct) => Ok(await _analytics.GetSidebarCountsAsync(UserId, ct)); }