using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PlanTempus.Core.Configurations.JsonConfigProvider;
using PlanTempus.Core.Exceptions;

namespace PlanTempus.Core.Configurations.SmartConfigProvider
{
    /// <summary>
    /// Configuration provider that loads configuration from a smart configuration source (e.g. database).
    /// The provider reads connection details from a JSON file and uses them to connect to a configuration repository.
    /// </summary>
    /// <remarks>
    /// The provider supports multiple initialization methods:
    /// - Through SmartConfigOptions for flexible repository configuration
    /// - Through direct configuration key and file path
    /// Configuration is loaded from the repository during Build() and converted to a JSON structure.
    /// </remarks>
    public class SmartConfigProvider : IConfigurationProvider
    {
        string _configKey;
        string _connectionString;
        string _path;
        IConfigurationBuilder _builder;

        JObject _configuration;
        SmartConfigOptions _smartConfigOptions;

        public SmartConfigProvider() { }

        public SmartConfigProvider(IConfigurationBuilder builder, SmartConfigOptions smartConfigOptions)
        {
            _builder = builder;
            _smartConfigOptions = smartConfigOptions;
            _configKey = smartConfigOptions._configKey;
            SetConnectionString();

        }
        public SmartConfigProvider(IConfigurationBuilder builder, string configKey, string configurationFilePath)
        {
            _builder = builder;
            _configKey = configKey;
            _path = configurationFilePath;
            SetConnectionString();
        }

        void SetConnectionString()
        {
            var carrier = _builder.ConfigurationProviders.OfType<IHasConfigurationFilePath>().SingleOrDefault();

            if (carrier?.ConfigurationFilePath is null && _path is null)
                throw new ConfigurationException($"Expected a previous added ConfigurationProvider with IHasConfigurationFilePath or a configurationFilePath where to find the appsettingsfile");

            _path ??= carrier.ConfigurationFilePath;

            if (!File.Exists(_path))
                throw new ConfigurationException($"File not found, configurationFilePath: {_path}");


            using (StreamReader file = File.OpenText(_path))
            using (JsonTextReader reader = new JsonTextReader(file))
            {
                var jsonConfiguration = (JObject)JToken.ReadFrom(reader);

                _connectionString = jsonConfiguration.SelectToken($"ConnectionStrings.{_configKey}")?.ToString();
            }
        }
        public void Build()
        {
            var repository = _smartConfigOptions.GetRepository();
            repository.ConnectionString = _connectionString;

            var configs = repository.GetActiveConfigurations();

            var pairs = configs.Select(x => new KeyValuePair<string, JToken>(x.Key, JToken.Parse(x.Value.ToString())));

            _configuration = Common.KeyValueToJson.Convert(pairs);

        }

        public JObject Configuration()
        {
            return _configuration;
        }
    }
}