using System.Text.Json; using ECPBLL.Collaboration.Interfaces; using ECPDAL.Collaboration.DTOs; using ECPDAL.Collaboration.Interfaces; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.GB5Constant; using GB5Shared.GenerateAutoNumber; using GB5Shared.Telemetry; namespace ECPBLL.Collaboration.Implementations; public class CollaborationSpaceIntegrationBLL( ICollaborationSpaceIntegrationDAL _dal, AutoNumber _autoNumber, KeyInvalidate _keyInvalidate ) : ICollaborationSpaceIntegrationBLL { // Fixed catalog per the ECP preview's mock — no provider-management screen exists, so this // isn't backed by its own master table. private static readonly string[] KnownProviders = ["teams", "sharepoint", "googleworkspace"]; public async Task GetCollaborationSpaceIntegrationsAsync(int collaborationSpaceId, LoginDTO login, CancellationToken ct) { GB5Trace.Step("get-collaboration-space-integrations", new { collaborationSpaceId }); var rows = await _dal.GetIntegrationsForSpaceAsync(collaborationSpaceId, login, ct).ConfigureAwait(false); var byProvider = rows.ToDictionary(r => r.Provider, StringComparer.OrdinalIgnoreCase); var result = KnownProviders.Select(p => new { Provider = p, Connected = byProvider.TryGetValue(p, out var row) && row.Connected, }); return JsonSerializer.Serialize(result); } public async Task SaveCollaborationSpaceIntegrationAsync(SaveCollaborationSpaceIntegrationDTO dto, LoginDTO login, CancellationToken ct) { GB5Trace.Step("save-collaboration-space-integration", new { dto.CollaborationSpaceId, dto.Provider, dto.Connected }); if (!KnownProviders.Contains(dto.Provider, StringComparer.OrdinalIgnoreCase)) throw new InvalidOperationException($"Unknown integration provider '{dto.Provider}'."); var existing = await _dal.GetIntegrationAsync(dto.CollaborationSpaceId, dto.Provider, login, ct).ConfigureAwait(false); if (existing is null) { var autoNumber = await _autoNumber.GetNumberAsync(1, "COLLABORATIONSPACEINTEGRATION", login).ConfigureAwait(false); var entity = new CollaborationSpaceIntegrationDTO { CollaborationSpaceIntegrationId = autoNumber.StartNumber, CollaborationSpaceId = dto.CollaborationSpaceId, Provider = dto.Provider, Connected = dto.Connected, TenantId = login.ClientId, DatabaseName = login.DatabaseName, DatabaseType = login.DatabaseType, Version = 0, Status = 1, CreatedById = login.UserId, CreatedOn = DateTime.UtcNow, ModifiedById = login.UserId, ModifiedOn = DateTime.UtcNow, }; await _dal.InsertIntegrationAsync(entity, login, ct).ConfigureAwait(false); } else { existing.Connected = dto.Connected; existing.ModifiedById = login.UserId; existing.ModifiedOn = DateTime.UtcNow; await _dal.UpdateIntegrationAsync(existing, login, ct).ConfigureAwait(false); } await InvalidateIntegrationsCacheAsync(dto.CollaborationSpaceId, login).ConfigureAwait(false); return dto.Connected ? "Connected" : "Disconnected"; } // Clears GetCollaborationSpaceIntegrations' cache — without this, toggling Connect/Disconnect // would appear to have no effect until cache TTL expiry. private async Task InvalidateIntegrationsCacheAsync(int collaborationSpaceId, LoginDTO login) { var cacheKey = new CacheKeyGeneration().KeyGeneration( collaborationSpaceId.ToString(), Constant.EntityConstant.OBJECTCOLLABORATIONSPACEINTEGRATIONS, Constant.CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.InvalidateCache(cacheKey).ConfigureAwait(false); } }