using System.Net.Http; using System.Net.Http.Json; using TaxBaik.Application.Services; using TaxBaik.Domain.Entities; namespace TaxBaik.Web.Services; /// /// Admin Dashboard API Client /// SOLID: Single Responsibility - Dashboard API 호출만 담당 /// Dependency Inversion - 추상화된 인터페이스 사용 /// public interface IAdminDashboardClient { Task GetSummaryAsync(CancellationToken ct = default); Task> GetUpcomingFilingsAsync(int days = 30, CancellationToken ct = default); Task> GetRecentInquiriesAsync(int limit = 10, CancellationToken ct = default); Task GetMonthlyStatsAsync(string? month = null, CancellationToken ct = default); } public class AdminDashboardClient : IAdminDashboardClient { private readonly HttpClient _http; private readonly ILogger _logger; private readonly ITokenStore _tokenStore; public AdminDashboardClient(HttpClient http, ILogger logger, ITokenStore tokenStore) { _http = http; _logger = logger; _tokenStore = tokenStore; } private void EnsureAuthHeader() { if (!string.IsNullOrEmpty(_tokenStore.AccessToken)) _http.DefaultRequestHeaders.Authorization = new("Bearer", _tokenStore.AccessToken); else _http.DefaultRequestHeaders.Authorization = null; } public async Task GetSummaryAsync(CancellationToken ct = default) { try { EnsureAuthHeader(); var result = await _http.GetFromJsonAsync( "admin-dashboard/summary", cancellationToken: ct); return result ?? new(0, 0, 0, 0, []); } catch (HttpRequestException ex) { _logger.LogError(ex, "Failed to fetch dashboard summary"); throw; } } public async Task> GetUpcomingFilingsAsync(int days = 30, CancellationToken ct = default) { try { EnsureAuthHeader(); var result = await _http.GetFromJsonAsync>( $"admin-dashboard/upcoming-filings?days={days}", cancellationToken: ct); return result?.Data ?? []; } catch (HttpRequestException ex) { _logger.LogError(ex, "Failed to fetch upcoming filings"); throw; } } public async Task> GetRecentInquiriesAsync(int limit = 10, CancellationToken ct = default) { try { EnsureAuthHeader(); var result = await _http.GetFromJsonAsync>( $"admin-dashboard/recent-inquiries?limit={limit}", cancellationToken: ct); return result?.Data ?? []; } catch (HttpRequestException ex) { _logger.LogError(ex, "Failed to fetch recent inquiries"); throw; } } public async Task GetMonthlyStatsAsync(string? month = null, CancellationToken ct = default) { try { EnsureAuthHeader(); var url = "admin-dashboard/monthly-stats"; if (!string.IsNullOrEmpty(month)) url += $"?month={month}"; var result = await _http.GetFromJsonAsync(url, cancellationToken: ct); return result ?? new(); } catch (HttpRequestException ex) { _logger.LogError(ex, "Failed to fetch monthly stats"); throw; } } } /// /// API Response wrapper /// internal class ApiResponse { public IEnumerable? Data { get; set; } public int Total { get; set; } public int Page { get; set; } public int PageSize { get; set; } }