using System.Net.Http.Json; using System.Text.Json; using Gateway.Models; namespace Gateway.ProviderClients; public sealed class GoogleProviderClient { private readonly HttpClient _http; private readonly IConfiguration _config; private readonly ILogger _logger; public GoogleProviderClient(HttpClient http, IConfiguration config, ILogger logger) { _http = http; _config = config; _logger = logger; } private string GetInternalKey() => _config["Provider:Google:InternalKey"] ?? Environment.GetEnvironmentVariable("GOOGLE_INTERNAL_KEY") ?? ""; public async Task<(int status, ProviderResponse body)> ExecuteAsync(ProviderRequest req, CancellationToken ct) { var key = GetInternalKey(); if (string.IsNullOrWhiteSpace(key)) return (500, new ProviderResponse { Ok = false, RequestId = req.RequestId, Error = new ProviderError { Code = "CONFIG", Message = "Missing Google internal key" } }); using var msg = new HttpRequestMessage(HttpMethod.Post, "internal/execute"); msg.Headers.Add("X-Internal-Key", key); msg.Content = JsonContent.Create(req, options: new JsonSerializerOptions(JsonSerializerDefaults.Web)); var res = await _http.SendAsync(msg, ct); ProviderResponse? body = null; try { body = await res.Content.ReadFromJsonAsync(cancellationToken: ct); } catch (Exception ex) { _logger.LogWarning(ex, "Failed to parse provider response as JSON"); } body ??= new ProviderResponse { Ok = res.IsSuccessStatusCode, RequestId = req.RequestId, Error = res.IsSuccessStatusCode ? null : new ProviderError { Code = "PROVIDER", Message = "Non-JSON error from provider" } }; // If provider returned a 4xx/5xx but body says Ok=true, normalize if (!res.IsSuccessStatusCode && body.Ok) body.Ok = false; return ((int)res.StatusCode, body); } }