using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.Telemetry; using Microsoft.Extensions.Logging; using PartnerBLL.PartnerSync; using PartnerDAL.CustomCode.PartnerSync; using PartnerDAL.DTO.PartnerSync; using static GB5Shared.GB5Constant.Constant; namespace PartnerBLL.Implementations { public class PartnerSyncBLL : IPartnerSyncBLL { private readonly IPartnerSyncDAL _dal; private readonly AutoNumber _autoNumber; private readonly ILogger _logger; public PartnerSyncBLL(IPartnerSyncDAL dal, AutoNumber autoNumber, ILogger logger) { _dal = dal; _autoNumber = autoNumber; _logger = logger; } public async Task ProvisionPartnerSync( int partnerId, int targetDbInstanceId, int centralDbInstanceId, LoginDTO login, CancellationToken ct) { GB5Trace.Step("validate-provision", new { partnerId }); if (partnerId <= 0) throw new ArgumentException("PartnerId is required."); if (targetDbInstanceId <= 0) throw new ArgumentException("TargetDbInstanceId is required."); if (centralDbInstanceId <= 0) throw new ArgumentException("CentralDbInstanceId is required."); GB5Trace.Step("lookup-datasets", new { partnerId }); var directDatasetId = await _dal.GetDatasetIdByCode("PARTNER_DIRECT", login, ct).ConfigureAwait(false); if (directDatasetId <= 0) throw new InvalidOperationException("PARTNER_DIRECT dataset not found. Run migration 20260621_PartnerSyncDataset.sql first."); var productDatasetId = await _dal.GetDatasetIdByCode("PARTNER_PRODUCT", login, ct).ConfigureAwait(false); if (productDatasetId <= 0) throw new InvalidOperationException("PARTNER_PRODUCT dataset not found. Run migration 20260621_PartnerSyncDataset.sql first."); var productIds = await _dal.GetPartnerProductIds(partnerId, login, ct).ConfigureAwait(false); var productCondition = productIds.Count > 0 ? $"PARTNERPRODUCTID IN ({string.Join(",", productIds)})" : "1=0"; GB5Trace.Step("upsert-jobs", new { partnerId, productCount = productIds.Count }); var jobAId = await UpsertJobAsync( $"PARTNER_DIRECT_{partnerId}", directDatasetId, $"PARTNERID = {partnerId}", centralDbInstanceId, targetDbInstanceId, login, ct).ConfigureAwait(false); var jobBId = await UpsertJobAsync( $"PARTNER_PRODUCT_{partnerId}", productDatasetId, productCondition, centralDbInstanceId, targetDbInstanceId, login, ct).ConfigureAwait(false); _logger.LogInformation( "PartnerSync provisioned for Partner {PartnerId}: JobA={JobAId} JobB={JobBId}", partnerId, jobAId, jobBId); return $"{SuccessResponse.SaveSuccessMessage} JobA={jobAId} JobB={jobBId}"; } public async Task RefreshPartnerSyncProducts(int partnerId, LoginDTO login, CancellationToken ct) { GB5Trace.Step("refresh-products", new { partnerId }); var productIds = await _dal.GetPartnerProductIds(partnerId, login, ct).ConfigureAwait(false); var productCondition = productIds.Count > 0 ? $"PARTNERPRODUCTID IN ({string.Join(",", productIds)})" : "1=0"; var jobBId = await _dal.GetSyncJobIdByDescription($"PARTNER_PRODUCT_{partnerId}", login, ct).ConfigureAwait(false); if (jobBId is null) throw new InvalidOperationException($"PARTNER_PRODUCT_{partnerId} sync job not found. Call ProvisionPartnerSync first."); await _dal.UpdateSyncJobProvision( jobBId.Value, productCondition, 0, 0, login.UserId, login, ct).ConfigureAwait(false); _logger.LogInformation("RefreshPartnerSyncProducts updated Job {JobId} for Partner {PartnerId}", jobBId, partnerId); return $"{SuccessResponse.UpdateSuccessMessage} SyncJobId={jobBId}"; } // ── Private ────────────────────────────────────────────────────────────── private async Task UpsertJobAsync( string description, int datasetId, string queryCondition, int sourceDbInstanceId, int targetDbInstanceId, LoginDTO login, CancellationToken ct) { var existingId = await _dal.GetSyncJobIdByDescription(description, login, ct).ConfigureAwait(false); if (existingId.HasValue) { await _dal.UpdateSyncJobProvision( existingId.Value, queryCondition, sourceDbInstanceId, targetDbInstanceId, login.UserId, login, ct).ConfigureAwait(false); return existingId.Value; } var autoNum = await _autoNumber.GetAutoNumber(1, AUTONUMBERCONSTANT.DSYNCJOB, login) .ConfigureAwait(false); var dto = new PartnerSyncJobDTO { SyncJobId = autoNum.StartNumber, Description = description, DatasetId = datasetId, SourceDbInstanceId = sourceDbInstanceId, TargetDbInstanceId = targetDbInstanceId, SchedulerId = null, ConflictPolicy = 0, // Overwrite — central always wins Direction = 1, // Source → Target IsEnabled = 1, QueryCondition = queryCondition, LastInsertedTill = null, LastUpdatedTill = null, LastDeleteTill = null, SortOrder = 9999, Status = 1, Version = 0, SourceType = 5, CreatedById = login.UserId, CreatedOn = DateTime.UtcNow, ModifiedById = login.UserId, ModifiedOn = DateTime.UtcNow }; await _dal.SaveSyncJob(dto, login, ct).ConfigureAwait(false); return dto.SyncJobId; } } }