using DeepDrftData; using Microsoft.AspNetCore.Mvc; namespace DeepDrftAPI.Controllers; [ApiController] [Route("api/[controller]")] public class StatsController : ControllerBase { private readonly ITrackService _sqlTrackService; private readonly IEventService _eventService; private readonly ILogger _logger; public StatsController( ITrackService sqlTrackService, IEventService eventService, ILogger logger) { _sqlTrackService = sqlTrackService; _eventService = eventService; _logger = logger; } // GET api/stats/home (unauthenticated) // Aggregate figures behind the public home hero stat row — one read for all three cards. Same auth // posture as the other public browse reads (GET api/track/page). The figures span two domains: // the track-domain aggregation (Cuts/Mixes cards) lives in the SQL track service; the play-domain // figures (Phase 16 Plays card — total plays + unique listeners) live in the event service. This // controller is the thin composition seam that assembles both into one HomeStatsDto — neither // domain reaches into the other's tables. Play/listener figures are best-effort: a telemetry read // failure (or the not-yet-applied migration) leaves them at zero rather than failing the whole card. [HttpGet("home")] public async Task GetHome(CancellationToken ct = default) { var trackResult = await _sqlTrackService.GetHomeStats(ct); if (!trackResult.Success || trackResult.Value is null) { var error = trackResult.Messages.FirstOrDefault()?.Message ?? "Unknown error"; _logger.LogError("GetHome stats failed: {Error}", error); return StatusCode(500, "Failed to load stats"); } var stats = trackResult.Value; var playsResult = await _eventService.GetTotalPlayCount(ct); if (playsResult is { Success: true }) stats.TotalPlays = playsResult.Value; else _logger.LogWarning("GetHome total-plays read failed; Plays card falls back to 0: {Error}", playsResult.Messages.FirstOrDefault()?.Message); var listenersResult = await _eventService.GetDistinctListenerCount(ct); if (listenersResult is { Success: true }) stats.UniqueListeners = listenersResult.Value; else _logger.LogWarning("GetHome unique-listeners read failed; secondary line falls back to 0: {Error}", listenersResult.Messages.FirstOrDefault()?.Message); return Ok(stats); } }