
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Configurations\XTermsAndConditionsServiceConfiguration.cs

using System.Collections.Generic;
using xDataService.Constants;
using xStringService.Models.Dtos;

namespace xTermsAndConditionsService.Configurations
{
    /// <summary>
    /// Terms and Conditions Configuration ...
    /// </summary>
    public class XTermsAndConditionsServiceConfiguration
    {
        /// <summary>
        /// Terms And Conditions Resource Title in XString Table ...
        /// </summary>
        public string ResourceTitle { get; set; } = "terms_and_conditions";

        /// <summary>
        /// Seeding Mode for Terms and Conditions ...
        /// </summary>
        public XDbSeedingMode SeedingMode { get; set; } = XDbSeedingMode.AddIfNotExists;

        /// <summary>
        /// Default Terms and Conditions for Add to Databse on App Startup ...
        /// </summary>
        public List<XStringDto> TermsAndConditions { get; set; } = null;        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Constants\ConfigurationNodeNames.cs

namespace xTermsAndConditionsService.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string TERMS_AND_CONDITIONS_SERVICE_NODE = "TermsAndConditionsService";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Constants\XTermsAndConditionsServiceConstants.cs

namespace xTermsAndConditionsService.Constants
{
    public struct XTermsAndConditionsServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XTermsAndConditionsServiceDILogTag = "XTermsAndConditionsService";

        //
        // Table Mapping Identifiers ...

        //
        // GraphQL Collection Mappings ...

        //
        // Hubs ...

        //
        // Custome Constants ...

        //
        // EF Repositories Helper Extensions ...        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Controllers\XTermsAndConditionsControllerBase.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xStringService.Controllers;
using xTermsAndConditionsService.Interfaces;

namespace xTermsAndConditionsService.Controllers
{
    /// <summary>
    /// a Base Controller Implementation for Providing Base Actions of 
    /// Terms and Conditions Provided Actions ...
    /// </summary>
    [AllowAnonymous]
    public abstract class XTermsAndConditionsControllerBase : XBaseResourceProviderControllerBase<IXTermsAndConditionsProvider>, IXTermsAndConditionsController
    {
        protected XTermsAndConditionsControllerBase(
            ILogger<XTermsAndConditionsControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTermsAndConditionsProvider provider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\DI\XDIHelperExtension.cs

using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Configurations;
using xCommons.Extensions;
using xExceptions.Constants;
using xPushService.DI;
using xPushService.Helpers;
using xStringService.Interfaces.Dtos;
using xTermsAndConditionsService.Configurations;
using xTermsAndConditionsService.Constants;
using xTermsAndConditionsService.Hubs;
using xTermsAndConditionsService.Interfaces;
using xTermsAndConditionsService.Providers;

namespace xTermsAndConditionsService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Retrieve xTermsAndConditionsService Configuration from AppSettings ...
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XTermsAndConditionsServiceConfiguration GetXTermsAndConditionsServiceConfiguration(
            this IConfiguration configuration
        )
        {
            //
            var section = configuration.GetSection(ConfigurationNodeNames.TERMS_AND_CONDITIONS_SERVICE_NODE);
            var result = section.Get<XTermsAndConditionsServiceConfiguration>();

            //
            return result;
        }

        /// <summary>
        /// Extract xTermsAndConditionsService Configurations from AppSettings 
        /// and Register it in DI ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXTermsAndConditionsConfiguration(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            var serviceConfiguration = configuration.GetXTermsAndConditionsServiceConfiguration();
            services.AddXTermsAndConditionsConfiguration(serviceConfiguration);
        }

        /// <summary>
        /// Register xTermsAndConditionsService Configurations in DI ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXTermsAndConditionsConfiguration(
            this IServiceCollection services,
            XTermsAndConditionsServiceConfiguration configuration
        )
        {
            //
            if (configuration.IsNull())
            {
                Log($"there is no provided configurations, using default ...");
                configuration = new XTermsAndConditionsServiceConfiguration();
            }

            //
            services.AddSingleton(configuration);
        }

        /// <summary>
        /// Register TermsConditions Provider ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration">provided AppSettings Configuration</param>
        /// <param name="lifeTime"></param>
        public static void AddXTermsConditionsService(
            this IServiceCollection services,
            IConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Transient
        )
        {
            //
            AddTermsAndConditionsService(
                services: services,
                lifeTime: lifeTime,
                configuration: configuration
            );
        }

        /// <summary>
        /// Register TermsConditions Provider ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration">provided xTermsAndConditionsService Configuration</param>
        /// <param name="lifeTime"></param>
        public static void AddXTermsConditionsService(
            this IServiceCollection services,
            XTermsAndConditionsServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Transient
        )
        {
            //
            AddTermsAndConditionsService(
                services: services,
                lifeTime: lifeTime,
                serviceConfiguration: configuration
            );
        }

        public static void UseXTermsAndConditionsService(
            this IApplicationBuilder app
        )
        {
            //
            // Create an Scope for Services Acess ...
            using (var scope = app.ApplicationServices.CreateScope())
            {
                //
                // Inject Requirements ...
                var stringProvider = scope.ServiceProvider.GetService<IXStringServiceProvider>();
                var serviceConfiguration = scope.ServiceProvider.GetService<XTermsAndConditionsServiceConfiguration>();

                //
                // Using XTerms Hub ...
                var pushHelper = new XPushServiceHelper();
                pushHelper.AddHub<XTermsHub>("terms");
                app.UseXPushService(pushHelper);

                //
                // Validate Requirements Exists ...
                var isValid =
                    !stringProvider.IsNull() &&
                    !serviceConfiguration.IsNull() &&
                    !serviceConfiguration.TermsAndConditions.IsNull() &&
                    serviceConfiguration.TermsAndConditions.HasChild() &&
                    serviceConfiguration.SeedingMode != xDataService.Constants.XDbSeedingMode.None;
                if (isValid)
                {
                    //
                    // Prepare Default Terms ...
                    serviceConfiguration
                        .TermsAndConditions
                        .ToList()
                        .ForEach(t => t.ResourceTitle = serviceConfiguration.ResourceTitle);

                    //
                    // Loop through Terms and Conditions for Seeding ...
                    foreach (var item in serviceConfiguration.TermsAndConditions)
                    {
                        //
                        // Detect Exists Item ...
                        var exists = stringProvider.FindOneAsync(
                            predicate: x =>
                                x.Language == item.Language &&
                                x.ResourceTitle == item.ResourceTitle
                        )
                        .GetAwaiter()
                        .GetResult();

                        //
                        var isExists = !exists.IsNullOrDefault();

                        //
                        switch (serviceConfiguration.SeedingMode)
                        {
                            //
                            case xDataService.Constants.XDbSeedingMode.AddOrUpdate:
                                //
                                // Update Exists by new Provided ...
                                exists.TranslatedValue = item.TranslatedValue;
                                exists = stringProvider.UpdateAsync(
                                    id: exists.Id,
                                    item: exists,
                                    saveChanges: true
                                )
                                .GetAwaiter()
                                .GetResult();

                                //
                                Log($"Refresh Terms and Conditions of {exists.Language}");
                                break;

                            //
                            case xDataService.Constants.XDbSeedingMode.AddIfNotExists:
                                //
                                if (!isExists)
                                {
                                    //
                                    exists = stringProvider.AddAsync(
                                        item: item,
                                        saveChanges: true
                                    )
                                    .GetAwaiter()
                                    .GetResult();

                                    //
                                    Log($"Add Terms and Conditions for {exists.Language}");
                                }
                                break;
                        }
                    }
                }
            }
        }

        //
        #region Private ...
        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XTermsAndConditionsServiceConstants.XTermsAndConditionsServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Add Terms and Conditions Provider Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="lifeTime"></param>
        private static void AddTermsAndConditionsService(
            IServiceCollection services,
            IConfiguration configuration = null,
            XTermsAndConditionsServiceConfiguration serviceConfiguration = null,
            ServiceLifetime lifeTime = ServiceLifetime.Transient
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("AddTermsAndConditions failed, services not provided ...");
                throw exception;
            }

            //
            // Validate Configuration ...
            var isConfigValid = !configuration.IsNull() || !serviceConfiguration.IsNull();
            if (!isConfigValid)
            {
                //
                Log("AddTermsAndConditions failed, configuration not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("AddTermsAndConditions failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Check Dependencies Exists ...
            var isDependenciesPassed = !services
                .GetRegisteredService<XAppConfiguration>()
                .IsNull() &&
                !services.GetRegisteredService<IXStringServiceProvider>()
                .IsNull();
            if (!isDependenciesPassed)
            {
                //
                Log("AddTermsAndConditions failed due Dependencies Issues, IXStringServiceProvider or XAppConfiguration not provided ...");
                throw exception;
            }

            //
            // Service Configuration Handler ...
            if (serviceConfiguration.IsNull())
            {
                serviceConfiguration = configuration.GetXTermsAndConditionsServiceConfiguration();
            }
            services.AddXTermsAndConditionsConfiguration(serviceConfiguration);

            //
            // Register Resource Providers ...
            services.Add(new ServiceDescriptor(typeof(IXTermsAndConditionsProvider), typeof(XTermsAndConditionsProvider), lifeTime));
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Hubs\XTermsHub.cs

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xPushService.Base;
using xPushService.Constants;
using xStringService.Models.Dtos;

namespace xTermsAndConditionsService.Hubs
{
    /// <summary>
    /// a Hub for Notifing Terms and Conditions Events to Connected Clients ...
    /// </summary>
    public class XTermsHub : XBaseHub
    {
        public XTermsHub(
            ILogger<XTermsHub> logger
        ) : base(logger)
        {
        }

        //
        #region Hub Actions ...
        /// <summary>
        /// Add Specified Terms and Conditions ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Add(
            XStringDto entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Add.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Deleted Specified Terms and Conditions ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Delete(
            XStringDto entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Delete.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify an Entity Updated ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Update(
            XStringDto entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Update.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Interfaces\IXTermsAndConditionsController.cs

using xStringService.Interfaces;

namespace xTermsAndConditionsService.Interfaces
{
    /// <summary>
    /// an Interface for Describing Terms and Conditions Management Controller Actions ...
    /// </summary>
    public interface IXTermsAndConditionsController : IXBaseResourceProviderController
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Interfaces\IXTermsAndConditionsProvider.cs

using xStringService.Interfaces;

namespace xTermsAndConditionsService.Interfaces
{
    /// <summary>
    /// an Interface for Describing Terms and Conditions Management Provided Actions ...
    /// </summary>
    public interface IXTermsAndConditionsProvider : IXResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Providers\XTermsAndConditionsProvider.cs

using xStringService.Interfaces.Dtos;
using xStringService.Providers;
using xTermsAndConditionsService.Configurations;
using xTermsAndConditionsService.Interfaces;

namespace xTermsAndConditionsService.Providers
{
    /// <summary>
    /// an Implementation of Terms and Conditions Management Provided Actions ...
    /// </summary>
    public class XTermsAndConditionsProvider : XBaseResourceProvider, IXTermsAndConditionsProvider
    {
        public XTermsAndConditionsProvider(
            IXStringServiceProvider provider,
            XTermsAndConditionsServiceConfiguration configuration
        ) : base(
            resource: "NULL", 
            provider
        )
        {
            //
            // Since we nee to Set Resource Title of Terms and Conditions 
            // during instancing using Provided Configurations ...
            // set this value here ...
            resource = configuration.ResourceTitle;
        }
    }
}
