using System.Net.Http.Json; using System.Text.Json; using GB5Shared.DTO.Framework.Login; using Microsoft.Extensions.Logging; namespace DXPBLL.VendorPo; public class MmIntegrationService : IMmIntegrationService { private readonly IHttpClientFactory _HttpClientFactory; private readonly ILogger _Logger; public MmIntegrationService(IHttpClientFactory httpClientFactory, ILogger logger) { _HttpClientFactory = httpClientFactory; _Logger = logger; } public async Task TriggerAutoReservationAsync( StockReservationRequestDTO request, LoginDTO tenantLogin, CancellationToken ct) { try { var client = _HttpClientFactory.CreateClient("MMModule"); client.DefaultRequestHeaders.Remove("Login"); client.DefaultRequestHeaders.Add("Login", JsonSerializer.Serialize(tenantLogin)); var response = await client.PostAsJsonAsync("StockReservation/SaveStockReservation", request, ct) .ConfigureAwait(false); if (!response.IsSuccessStatusCode) { var body = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false); _Logger.LogWarning( "MM SaveStockReservation returned {StatusCode} for LinkedPoId {LinkedPoId}: {Body}", response.StatusCode, request.LinkedPoId, body); return new StockReservationOutcome { Success = false, Error = $"MM returned {(int)response.StatusCode}" }; } // MM's own ResponseStandardDTO wraps the actual reservation id in .Body — read it // permissively (a reservation succeeding is what matters for Phase 1.3; a follow-up // phase should parse MM's exact Body shape once its ExecuteSaveAsync return // convention is confirmed against a live MM instance, see Part 4/1.7 of the plan). var raw = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false); return new StockReservationOutcome { Success = true, Error = null, ReservationId = TryExtractId(raw) }; } catch (Exception ex) { _Logger.LogError(ex, "MM SaveStockReservation call failed for LinkedPoId {LinkedPoId}", request.LinkedPoId); return new StockReservationOutcome { Success = false, Error = ex.Message }; } } private static int? TryExtractId(string rawJson) { try { using var doc = JsonDocument.Parse(rawJson); if (doc.RootElement.TryGetProperty("Body", out var body) && body.ValueKind == JsonValueKind.Number) return body.GetInt32(); } catch { /* best effort — reservation still succeeded even if we can't parse the id */ } return null; } public async Task SaveMmDocumentAsync( MmDocumentSaveRequestDTO request, LoginDTO tenantLogin, CancellationToken ct) { try { var client = _HttpClientFactory.CreateClient("MMModule"); client.DefaultRequestHeaders.Remove("Login"); client.DefaultRequestHeaders.Add("Login", JsonSerializer.Serialize(tenantLogin)); var response = await client.PostAsJsonAsync("MMHead/SaveMMHead", request, ct) .ConfigureAwait(false); if (!response.IsSuccessStatusCode) { var body = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false); _Logger.LogWarning( "MM SaveMMHead returned {StatusCode} for BizTransactionTypeId {BizTransactionTypeId}: {Body}", response.StatusCode, request.BizTransactionTypeId, body); return new MmDocumentSaveOutcome { Success = false, Error = $"MM returned {(int)response.StatusCode}: {body}" }; } return new MmDocumentSaveOutcome { Success = true }; } catch (Exception ex) { _Logger.LogError(ex, "MM SaveMMHead call failed for BizTransactionTypeId {BizTransactionTypeId}", request.BizTransactionTypeId); return new MmDocumentSaveOutcome { Success = false, Error = ex.Message }; } } }