using System.Net.Http.Json; using System.Text.Json; using GB5Shared.DTO.Framework.Login; using Microsoft.Extensions.Logging; namespace SwBLL.Integration; /// Mirrors EntitlementBLL.Onboarding.SqlWorkbenchClient's exact shape (IHttpClientFactory, /// a named client, JSON GET, Login-header convention) for the reverse direction — SqlWorkbench /// calling INTO Entitlement (tracker §40) instead of Entitlement calling into SqlWorkbench. public class EntitlementSubscriptionClient : IEntitlementSubscriptionClient { private readonly IHttpClientFactory _HttpClientFactory; private readonly ILogger _Logger; public EntitlementSubscriptionClient(IHttpClientFactory httpClientFactory, ILogger logger) { _HttpClientFactory = httpClientFactory; _Logger = logger; } public async Task GetSnapshotAsync(int clientId, LoginDTO swLogin, CancellationToken ct) { var client = _HttpClientFactory.CreateClient("Entitlement"); // Only ClientId carries meaning for this call — DatabaseName is Entitlement's own // concern to resolve server-side, not something SqlWorkbench should dictate (unlike the // reverse direction, where Entitlement must explicitly override DatabaseName to // "Gb5System" since it knows SW's schema lives there — SqlWorkbench has no equivalent // fixed knowledge of which physical database backs Entitlement in a given deployment). var login = new LoginDTO { ClientId = swLogin.ClientId, UserId = swLogin.UserId }; client.DefaultRequestHeaders.Remove("Login"); client.DefaultRequestHeaders.Add("Login", JsonSerializer.Serialize(login)); HttpResponseMessage response; try { response = await client.GetAsync($"/lic/Subscription.svc/GetClientEntitlementSnapshot?ClientId={clientId}", ct) .ConfigureAwait(false); } catch (HttpRequestException ex) { _Logger.LogError(ex, "Entitlement GetClientEntitlementSnapshot call failed for ClientId {ClientId}.", clientId); throw new InvalidOperationException($"Could not reach Entitlement to resolve entitlement snapshot for ClientId {clientId}.", ex); } var raw = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { _Logger.LogError("Entitlement GetClientEntitlementSnapshot returned {StatusCode} for ClientId {ClientId}: {Body}", response.StatusCode, clientId, raw); throw new InvalidOperationException($"Entitlement GetClientEntitlementSnapshot failed ({(int)response.StatusCode}) for ClientId {clientId}."); } using var doc = JsonDocument.Parse(raw); if (!doc.RootElement.TryGetProperty("Body", out var body) || body.ValueKind != JsonValueKind.Object) return null; // Entitlement has nothing for this client — caller treats as "cannot determine" return body.Deserialize(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); } }