using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Microsoft.EntityFrameworkCore;
namespace Application.Features.Api.Stocks.GetMacroIndicators;
///
/// 거시경제지표 조회 — 지표코드별 최근 시점 추이 + 최신값 (KOSIS 수집, 익명). Codes 비면 적재된 전 지표.
/// 지표당 최근 Limit 시점을 시점 내림차순으로 뽑은 뒤 오름차순으로 되돌려(Points) 대시보드 차트에 그대로 쓴다.
///
internal sealed class Handler(IAppDbContext db) : IQueryHandler
{
private const int DefaultLimit = 60;
private const int MaxLimit = 240;
public async Task Handle(Query request, CancellationToken ct)
{
var limit = request.Limit > 0 ? Math.Min(request.Limit, MaxLimit) : DefaultLimit;
var codes = request.Codes?.Where(c => !string.IsNullOrWhiteSpace(c)).Select(c => c.Trim()).ToList() ?? [];
var query = db.MacroIndicator.AsNoTracking();
if (codes.Count > 0)
{
query = query.Where(c => codes.Contains(c.Code));
}
var rows = await query
.Select(c => new
{
c.Code,
c.Name,
c.Period,
c.Value,
c.Unit
})
.ToListAsync(ct);
var indicators = rows
.GroupBy(c => c.Code)
.Select(g =>
{
var ordered = g.OrderByDescending(c => c.Period).Take(limit).OrderBy(c => c.Period).ToList();
var latest = ordered.Count > 0 ? ordered[^1] : null;
return new Response.Indicator
{
Code = g.Key,
Name = latest?.Name ?? g.First().Name,
Unit = latest?.Unit,
LatestPeriod = latest?.Period,
LatestValue = latest?.Value,
Points = ordered.Select(c => new Response.Point
{
Period = c.Period,
Value = c.Value
}).ToList()
};
})
.OrderBy(c => c.Code)
.ToList();
return new Response
{
Total = indicators.Count,
List = indicators
};
}
}