
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Configurations\XAIServiceConfiguration.cs

namespace xAiService.Configurations
{
    public partial class XAIServiceConfiguration
    {
        public string Url { get; set; }
        public string XPoweredValue { get; set; }
        public int DefaultClientTimeout { get; set; } = 360;
    }
}

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

namespace xAiService.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string AI_SERVICE_NODE = "AIServiceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Constants\XAiApiConstants.cs

namespace xAiService.Constants
{
    public struct XAiApiQueryParams
    {
        public const string Prompt = "prompt";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Constants\XAiApiEndpoint.cs

using xExceptions.Attributes;

namespace xAiService.Constants
{
    public enum XAiApiEndpoint
    {
        [StringValue("AskAI")]
        Ask,
        [StringValue("AskAIStream")]
        Stream,
    }
}

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

using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xAiService.Configurations;
using xAiService.Constants;
using xAiService.Extensions;
using xAiService.Interfaces;
using xAiService.Services;
using xCommons.Extensions;
using xExceptions.Constants;

namespace xAiService.DI
{
    public static partial class XDIHelperExtension
    {
        /// <summary>
        /// Extract AI Service Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XAIServiceConfiguration GetXAIServiceConfiguration(this IConfiguration source)
        {
            //
            XAIServiceConfiguration result = null;

            //
            var section = source.GetSection(ConfigurationNodeNames.AI_SERVICE_NODE);
            if (!section.IsNull())
            {
                result = section.Get<XAIServiceConfiguration>();
            }

            //
            return result;
        }

        /// <summary>
        /// Add AI Service Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXAIServiceConfiguration(
            this IServiceCollection source,
            XAIServiceConfiguration configuration
        )
        {
            source.AddSingleton<XAIServiceConfiguration>(configuration);
        }

        /// <summary>
        /// Adding XAiService ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="lifeTime"></param>
        public static void AddXAIService(
            this IServiceCollection services,
            IConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var config = configuration.GetXAIServiceConfiguration();
            AddAIService(
                services,
                config,
                lifeTime
            );
        }

        /// <summary>
        /// Adding XAiService ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="lifeTime"></param>
        public static void AddXAIService(
            this IServiceCollection services,
            XAIServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            AddAIService(
                services,
                configuration,
                lifeTime
            );
        }

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

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

        /// <summary>
        /// Adding Ai Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="lifeTime"></param>
        private static void AddAIService(
            this IServiceCollection services,
            XAIServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

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

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

            //
            // Check Dependencies Exists ...
            var isDependenciesPassed = true;
            if (!isDependenciesPassed)
            {
                //
                Log("AddAIService failed due Dependencies Issues, not provided ...");
                throw exception;
            }

            //
            // Validate Configurations ...
            var isConfigurationExists =
                !configuration.IsNull() &&
                configuration.IsValid();
            if (!isConfigurationExists)
            {
                //
                Log("AddAIService failed due InValid Service Configuration or not provided ...");
                throw exception;
            }

            //
            // Register Configurations ...
            services.AddXAIServiceConfiguration(configuration);

            //
            // Register Services ...
            services.Add(new ServiceDescriptor(typeof(IXAiService), typeof(XAiService), lifeTime));
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Extensions\ConfigurationExtensions.cs

using xAiService.Configurations;
using xCommons.Extensions;

namespace xAiService.Extensions
{
    public static class ModelExtensions
    {
        /// <summary>
        /// Validate XAiServiceConfiguration ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAIServiceConfiguration source)
        {
            //
            bool result =
                !source.IsNull() &&
                !source.Url.IsNullOrEmpty() &&
                source.Url.IsValidUrl();

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Extensions\PromptExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xAiService.Models.Dtos;
using xCommons.Extensions;

namespace xAiService.Extensions
{
    public static class PromptExtensions
    {
        /// <summary>
        /// Get Template Params Filled Prompt ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="params"></param>
        /// <returns></returns>
        public static string GetMessage(
            this XPromptDto source,
            IDictionary<string, string> @params = null
        )
        {
            //
            var result = string.Empty;

            //
            if (!source.IsNullOrDefault() &&
                !source.Prompt.IsNullOrEmpty()
            )
            {
                result = source.Prompt;
            }

            //
            // Check Params Conditions ...
            if (!source.Params.IsNullOrDefault() &&
                source.Params.HasChild() &&
                !@params.IsNullOrDefault() &&
                @params.HasChild()
            )
            {
                //
                // Select Params ...
                var existsParams = source.Params
                    .Where(p => @params.Any(pr => pr.Key == p.Name))
                    .Distinct()
                    .ToList();

                //
                // Replace Selected Params ...
                existsParams
                    .ForEach(pk =>
                    {
                        result = result.Replace(pk.Param, @params[pk.Name]);
                    });
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Helpers\XPromptHelper.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using xAiService.Models.Dtos;
using xCommons.Extensions;

namespace xAiService.Helpers
{
    public static class XPromptHelper
    {
        /// <summary>
        /// Holds Initialized Prompts ...
        /// </summary>
        private static XPromptsDto prompts;

        /// <summary>
        /// Initialize Prompt Helper ...
        /// </summary>
        /// <param name="path"></param>
        /// <exception cref="Exception"></exception>
        /// <exception cref="InvalidDataException"></exception>
        public static void Initialize(string path = "prompts.json")
        {
            //
            // Create full Path and Check File Exists ...
            var fullPath = Path.Combine(AppContext.BaseDirectory, path);
            if (!File.Exists(fullPath))
            {
                throw new Exception($"Prompts Resources not found: {fullPath}");
            }

            //
            // Read File as Json Text ...
            var json = File.ReadAllText(fullPath);
            var options = new JsonSerializerOptions
            {
                AllowTrailingCommas = true,
                PropertyNameCaseInsensitive = true,
                ReadCommentHandling = JsonCommentHandling.Skip,
                Converters =
                {
                    new JsonStringEnumConverter(
                        namingPolicy: null,
                        allowIntegerValues: false
                    )
                }
            };

            //
            // Serialized Root Object ...
            var root = JsonSerializer.Deserialize<XPromptsDto>(json, options);
            if (!root.IsNullOrDefault())
            {
                prompts = new XPromptsDto { Prompts = root.Prompts };
            }
        }

        /// <summary>
        /// Retrieve all Allowed Prompts as Enumerable ...
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<XPromptDto> GetPrompts()
        {
            return prompts!.Prompts.AsEnumerable();
        }

        /// <summary>
        /// Get Specified Prompt ...
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static XPromptDto GetPrompt(string name)
        {
            //
            return GetPrompts()
                .FirstOrDefault(p => p.Name == name);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Interfaces\IXAiService.cs

using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using xAiService.Configurations;
using xIdentityModels.Models;
using xIdentityService.Interfaces;

namespace xAiService.Interfaces
{
    public interface IXAiService : IXBaseIdentityHttpProvider
    {
        /// <summary>
        /// XAiService Configurations ...
        /// </summary>
        /// <value></value>
        XAIServiceConfiguration Configuration { get; }

        //
        #region Text Actions ...
        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<ChatResponse> GetResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<string> GetTextResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Generate Text Response Stream ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<Stream> GetTextReponseStreamAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Interfaces\IXAiServiceControllerBase.cs

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace xAiService.Interfaces
{
    public interface IXAiServiceControllerBase
    {
        Task<ActionResult<string>> Ask(
            [FromQuery] string prompt,
            CancellationToken cancellationToken = default
        );
        
        Task<ActionResult> AskStream(
            [FromQuery] string prompt,
            CancellationToken cancellationToken = default
        );        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Models\Dtos\XPromptsDto.cs

namespace xAiService.Models.Dtos
{
    /// <summary>
    /// Described Prompts in app ...
    /// </summary>
    public class XPromptsDto
    {
        public XPromptDto[] Prompts { get; set; } = [];
    }

    /// <summary>
    /// a Single Prompt Description ...
    /// </summary>
    public class XPromptDto
    {
        /// <summary>
        /// Prompt Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Prompt Template Message ...
        /// </summary>
        public string Prompt { get; set; }

        /// <summary>
        /// Prompt Description ...
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Describe Prompt Params ...
        /// </summary>
        public virtual XPromptParamDto[] Params { get; set; } = null;
    }

    /// <summary>
    /// Prompt Param used to Fill dynamic Datas to Specified Prompts ...
    /// </summary>
    public class XPromptParamDto
    {
        /// <summary>
        /// Param Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Parma Identifier ...
        /// </summary>
        public string Param { get; set; }

        /// <summary>
        /// Param Description ...
        /// </summary>
        public string Description { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Services\XAiService.cs

using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
using xAiService.Configurations;
using xAiService.Constants;
using xAiService.Interfaces;
using xCommons.Providers;
using xHttpService.Constants;
using xIdentityModels.Models;
using xIdentityService.Interfaces;
using xIdentityService.Providers;

namespace xAiService.Services
{
    public class XAiService : XBaseIdentityHttpProvider, IXAiService
    {
        /// <summary>
        /// XAiService Configurations ...
        /// </summary>
        /// <value></value>
        public XAIServiceConfiguration Configuration { get; }

        public XAiService(
            ILogger<XAiService> logger,
            IXTokenProvider tokenProvider,
            IXIdentityProvider identityProvider,
            XAIServiceConfiguration configuration,
            XValidationProvider validationProvider
        ) : base(
            configuration.Url,
            logger,
            configuration.XPoweredValue,
            configuration.DefaultClientTimeout,
            tokenProvider,
            identityProvider,
            validationProvider
        )
        { }

        //
        #region Text Actions ...
        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<ChatResponse> GetResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        )
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> GetTextResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(prompt);

            //
            var client = GetRestClient(userInfo);
            var request = GetRestRequet(
                endpoint: XAiApiEndpoint.Ask,
                addXPoweredValue: true,
                queryStrings: new Dictionary<string, string>
                {
                    { XAiApiQueryParams.Prompt, prompt }
                }
            );

            //
            var response = await RunRestRequest<string>(
                client,
                request,
                XHttpMethod.GET,
                cancellationToken: cancellationToken
            );

            //
            return response;
        }

        /// <summary>
        /// Generate Text Response Stream ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<Stream> GetTextReponseStreamAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(prompt)
                .AddNotNull(userInfo)
                .AddNotZero(userInfo.ExpiresAt)
                .AddNotEmpty(userInfo.AccessToken)
                .AddNotEmpty(userInfo.RefreshToken)
                .ValidateGroup();

            //
            var tokens = ToTokenResponse(userInfo);
            var result = await StreamData(
                tokens: tokens,
                addXPoweredValue: true,
                endpoint: XAiApiEndpoint.Stream,
                cancellationToken: cancellationToken,
                queryStrings: new Dictionary<string, string>
                {
                    { XAiApiQueryParams.Prompt, prompt }
                }
            );

            //
            return result;
        }
        #endregion
    }
}
