using System; using System.Linq; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using FrameworkDAL.CustomCode.Promotion; using FrameworkDAL.DTO.Promotion; using GB5Shared.DTO.Framework.Login; using GB5Shared.Resource.Response; using GB5Shared.Telemetry; using GB5Shared.Validation; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace FrameworkBLL.Promotion { public class PromotionCounterpartyBLL : IPromotionCounterpartyBLL { private readonly IPromotionCounterpartyDAL _Dal; private readonly IValidation _Validation; private readonly ILogger _Logger; public PromotionCounterpartyBLL( IPromotionCounterpartyDAL dal, IValidation validation, ILogger logger) { _Dal = dal; _Validation = validation; _Logger = logger; } public async Task GetPromotionCounterparty(string environmentCode, LoginDTO login, CancellationToken ct) { var dto = await _Dal.GetByEnvironmentCodeForAdmin(environmentCode, login, ct).ConfigureAwait(false); return JsonConvert.SerializeObject(dto); } public async Task GetPromotionCounterpartyList(LoginDTO login, CancellationToken ct) { var list = await _Dal.GetList(login, ct).ConfigureAwait(false); return JsonConvert.SerializeObject(list); } public async Task GetSelectListPromotionCounterparty(LoginDTO login, CancellationToken ct) { var list = await _Dal.GetSelectList(login, ct).ConfigureAwait(false); return JsonConvert.SerializeObject(list); } public async Task SavePromotionCounterparty( PromotionCounterpartyDTO dto, LoginDTO login, CancellationToken ct) { try { await _Validation.NotEmpty(dto.EnvironmentCode, nameof(dto.EnvironmentCode)).ConfigureAwait(false); await _Validation.NotEmpty(dto.DisplayName, nameof(dto.DisplayName)).ConfigureAwait(false); await _Validation.NotEmpty(dto.PublicKeyPem, nameof(dto.PublicKeyPem)).ConfigureAwait(false); // Fail fast with a clear message here — the alternative is a real counterparty // silently sitting in the registry with a broken key until the first real // encrypt/decrypt attempt fails, days or weeks later. try { using var rsa = RSA.Create(); rsa.ImportFromPem(dto.PublicKeyPem); } catch (Exception pemEx) { throw new ArgumentException( $"PublicKeyPem is not a valid RSA public key: {pemEx.Message}", nameof(dto.PublicKeyPem)); } GB5Trace.Step("validate-promotioncounterparty", new { dto.EnvironmentCode }); var isNew = !await _Dal.ExistsByEnvironmentCode(dto.EnvironmentCode, login, ct).ConfigureAwait(false); dto.ModifiedById = login.UserId; dto.ModifiedOn = DateTime.UtcNow; GB5Trace.Step("save-promotioncounterparty", new { dto.EnvironmentCode, isNew }); if (isNew) { dto.CreatedById = login.UserId; dto.CreatedOn = DateTime.UtcNow; await _Dal.InsertCounterparty(dto, login, ct).ConfigureAwait(false); } else { await _Dal.UpdateCounterparty(dto, login, ct).ConfigureAwait(false); } return isNew ? $"{SuccessResponse.SaveSuccessMessage} {dto.EnvironmentCode}" : SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-promotioncounterparty-failed", ex); _Logger.LogError(ex, "SavePromotionCounterparty failed for EnvironmentCode {EnvironmentCode}", dto.EnvironmentCode); throw; } } public async Task DeletePromotionCounterparty(string environmentCode, LoginDTO login, CancellationToken ct) { await _Dal.DeleteCounterparty(environmentCode, login, ct).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } } }