using GB5Shared.IceMap; using GB5Shared.DTO.Ice; using GB5Shared.DTO.Framework.Login; using GB5Shared.Telemetry; using GB5Shared.Validation; using IceImportDAL.CustomCode.IceMapFtpSource; using IceImportDAL.DTO.IceMapFtpSource; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace IceImportBLL.IceMapFtpSource; public class IceMapFtpSourceBLL : IIceMapFtpSourceBLL { private static readonly HashSet ValidConnectionTypes = new() { 0, 1 }; private static readonly HashSet ValidPostProcessActions = new() { 0, 1, 2 }; private readonly IIceMapBLL _iceMapBLL; private readonly IIceMapFtpSourceDAL _dal; private readonly IValidation _validation; private readonly ILogger _logger; public IceMapFtpSourceBLL( IIceMapBLL iceMapBLL, IIceMapFtpSourceDAL dal, IValidation validation, ILogger logger) { _iceMapBLL = iceMapBLL; _dal = dal; _validation = validation; _logger = logger; } public async Task SaveAsync(MicemapFtpSourceDTO config, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-ftp-source", new { config.IceMapId, config.ConnectionType }); await EnsureIceMapExistsAsync(config.IceMapId, login).ConfigureAwait(false); if (!ValidConnectionTypes.Contains(config.ConnectionType)) throw new ArgumentException($"ConnectionType must be 0 (FTP) or 1 (SFTP), got {config.ConnectionType}."); if (!ValidPostProcessActions.Contains(config.PostProcessAction)) throw new ArgumentException( $"PostProcessAction must be 0 (None), 1 (Delete), or 2 (Archive), got {config.PostProcessAction}."); if (config.PostProcessAction == 2 && string.IsNullOrWhiteSpace(config.ArchiveFolderPath)) throw new ArgumentException("ArchiveFolderPath is required when PostProcessAction is Archive."); await _validation.NotEmpty(config.HostVaultRef, nameof(config.HostVaultRef)).ConfigureAwait(false); await _validation.NotEmpty(config.UsernameVaultRef, nameof(config.UsernameVaultRef)).ConfigureAwait(false); await _validation.NotEmpty(config.CredentialVaultRef, nameof(config.CredentialVaultRef)).ConfigureAwait(false); await _validation.NotEmpty(config.RemoteFolderPath, nameof(config.RemoteFolderPath)).ConfigureAwait(false); await _validation.NotEmpty(config.FileNamePattern, nameof(config.FileNamePattern)).ConfigureAwait(false); GB5Trace.Step("save-ftp-source", new { config.IceMapId }); await _dal.SaveAsync(config, login, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("save-ftp-source-failed", ex); _logger.LogError(ex, "SaveIceMapFtpSource failed for IceMapId {IceMapId}", config.IceMapId); throw; } } public async Task GetAsync(int iceMapId, LoginDTO login, CancellationToken ct) { await EnsureIceMapExistsAsync(iceMapId, login).ConfigureAwait(false); return await _dal.GetByIceMapIdAsync(iceMapId, login, ct).ConfigureAwait(false); } private async Task EnsureIceMapExistsAsync(int iceMapId, LoginDTO login) { var json = await _iceMapBLL.GetIceMap(iceMapId, login).ConfigureAwait(false); _ = JsonConvert.DeserializeObject(json) ?? throw new InvalidOperationException($"IceMap {iceMapId} was not found."); } }