namespace TaxBaik.Web.Services.AdminClients; using System.Text.Json; using TaxBaik.Domain.Entities; public interface IConsultingActivityBrowserClient { Task> GetAllAsync(CancellationToken ct = default); Task> GetByClientIdAsync(int clientId, CancellationToken ct = default); Task> GetPendingFollowupsAsync(CancellationToken ct = default); Task CreateAsync(int clientId, string activityType, DateTime activityDate, string description, int? consultantId = null, DateTime? nextFollowupDate = null, CancellationToken ct = default); Task UpdateAsync(int id, string? outcome = null, DateTime? nextFollowupDate = null, CancellationToken ct = default); Task DeleteAsync(int id, CancellationToken ct = default); } public class ConsultingActivityBrowserClient(HttpClient httpClient, ITokenStore tokenStore, ILogger logger) : IConsultingActivityBrowserClient { private const string BaseUrl = "/api/consultingactivity"; private void EnsureAuthHeader() { if (!string.IsNullOrEmpty(tokenStore.AccessToken)) httpClient.DefaultRequestHeaders.Authorization = new("Bearer", tokenStore.AccessToken); else httpClient.DefaultRequestHeaders.Authorization = null; } public async Task> GetAllAsync(CancellationToken ct = default) { try { EnsureAuthHeader(); return await httpClient.GetFromJsonAsync>($"{BaseUrl}", ct) ?? []; } catch (Exception ex) { logger.LogError(ex, "Failed to get consulting activities"); return []; } } public async Task> GetByClientIdAsync(int clientId, CancellationToken ct = default) { try { EnsureAuthHeader(); return await httpClient.GetFromJsonAsync>($"{BaseUrl}/client/{clientId}", ct) ?? []; } catch (Exception ex) { logger.LogError(ex, "Failed to get activities for client {ClientId}", clientId); return []; } } public async Task> GetPendingFollowupsAsync(CancellationToken ct = default) { try { EnsureAuthHeader(); var response = await httpClient.GetFromJsonAsync($"{BaseUrl}/pending-followups", ct); if (response.TryGetProperty("data", out var data)) return System.Text.Json.JsonSerializer.Deserialize>(data.GetRawText()) ?? []; return []; } catch (Exception ex) { logger.LogError(ex, "Failed to get pending followups"); return []; } } public async Task CreateAsync(int clientId, string activityType, DateTime activityDate, string description, int? consultantId = null, DateTime? nextFollowupDate = null, CancellationToken ct = default) { try { EnsureAuthHeader(); var request = new { clientId, activityType, activityDate, description, consultantId, nextFollowupDate }; var response = await httpClient.PostAsJsonAsync(BaseUrl, request, ct); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadFromJsonAsync(cancellationToken: ct); return result.TryGetProperty("id", out var idProp) ? idProp.GetInt32() : 0; } catch (Exception ex) { logger.LogError(ex, "Failed to create consulting activity"); return 0; } } public async Task UpdateAsync(int id, string? outcome = null, DateTime? nextFollowupDate = null, CancellationToken ct = default) { try { EnsureAuthHeader(); var request = new { outcome, nextFollowupDate }; var response = await httpClient.PutAsJsonAsync($"{BaseUrl}/{id}", request, ct); response.EnsureSuccessStatusCode(); } catch (Exception ex) { logger.LogError(ex, "Failed to update consulting activity {Id}", id); } } public async Task DeleteAsync(int id, CancellationToken ct = default) { try { EnsureAuthHeader(); var response = await httpClient.DeleteAsync($"{BaseUrl}/{id}", ct); response.EnsureSuccessStatusCode(); } catch (Exception ex) { logger.LogError(ex, "Failed to delete consulting activity {Id}", id); } } }