using GB5Shared.DateConverter; using GB5Shared.DTO.Framework.Login; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using System; using System.Net.Http; using System.Net.Http.Json; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace PayRollBLL.Common { // GB4 parity: gServiceHandler.CallServiceXml(ValidationUri, "POST", DTO), called by // ShiftPatternBLL.SaveShiftPattern/GratuityGroupBLL.SaveGratuityGroup before persisting — // if the validator doesn't return success, the save is aborted and its error is surfaced // as-is. gb4 posted XML and read a JSON-shaped ResponseStandardDTO back; gb5 posts JSON // (System.Text.Json, matching every other GB5 endpoint) since there's no XML consumer // to stay compatible with on this side. Base URI is read per-call from // EntityValidation:{configKey} (see PayRollSL/appsettings.json). public class EntityValidationClient : IEntityValidationClient { private static readonly JsonSerializerOptions _JsonOptions = GB5JsonOptions.CreateDefaultOptions(); private readonly IHttpClientFactory _HttpClientFactory; private readonly IConfiguration _Configuration; public EntityValidationClient(IHttpClientFactory httpClientFactory, IConfiguration configuration) { _HttpClientFactory = httpClientFactory; _Configuration = configuration; } public async Task<(bool IsValid, string? ErrorMessage)> ValidateAsync( string configKey, object dto, LoginDTO loginDTO, CancellationToken ct = default) { var baseUri = _Configuration[$"EntityValidation:{configKey}"]; if (string.IsNullOrWhiteSpace(baseUri)) { // No validator configured for this entity yet — treat as a no-op pass, // matching gb4 environments where BaseXxxValidationUri was never set up. return (true, null); } var http = _HttpClientFactory.CreateClient(); using var request = new HttpRequestMessage(HttpMethod.Post, baseUri) { Content = JsonContent.Create(dto, options: _JsonOptions) }; request.Headers.Add("Login", JsonConvert.SerializeObject(loginDTO)); using var response = await http.SendAsync(request, ct).ConfigureAwait(false); if (!response.IsSuccessStatusCode) return (false, $"Validation service returned {(int)response.StatusCode} {response.ReasonPhrase}."); var envelope = await response.Content.ReadFromJsonAsync(cancellationToken: ct).ConfigureAwait(false); if (envelope.TryGetProperty("Status", out var statusProp) && statusProp.GetInt32() == 200) return (true, null); var errorMessage = envelope.TryGetProperty("ErrorBody", out var errProp) ? errProp.GetString() : "Entity validation failed."; return (false, errorMessage); } } }