using Newtonsoft.Json.Linq;
using PlanTempus.Core.Configurations;
using PlanTempus.Core.Configurations.JsonConfigProvider;
using PlanTempus.Core.Configurations.SmartConfigProvider;
using Shouldly;

namespace PlanTempus.X.TDD.ConfigurationTests;

[TestClass]
public class JsonConfigurationProviderTests : TestFixture
{
    private const string _testFolder = "ConfigurationTests/";

    public JsonConfigurationProviderTests() : base(_testFolder)
    {
    }


    [TestMethod]
    public void GetSection_ShouldReturnCorrectFeatureSection()
    {
        // Arrange
        var expectedJObject = JObject.Parse(@"{
                    'Enabled': true,
                    'RolloutPercentage': 25,
                    'AllowedUserGroups': ['beta']
                }") as JToken;

        var builder = new ConfigurationBuilder()
            .AddJsonFile($"{_testFolder}appconfiguration.dev.json")
            .Build();

        // Act
        var section = builder.GetSection("Feature");

        // Assert
        section.ShouldNotBeNull();
        section.Value.ShouldBeEquivalentTo(expectedJObject);
    }

    [TestMethod]
    public void Get_ShouldReturnCorrectFeatureObject()
    {
        // Arrange
        var expectedFeature = new Feature
        {
            Enabled = true,
            RolloutPercentage = 25,
            AllowedUserGroups = new List<string> { "beta" }
        };

        var builder = new ConfigurationBuilder()
            .AddJsonFile($"{_testFolder}appconfiguration.dev.json")
            .Build();

        // Act
        var actualFeature = builder.GetSection("Feature").ToObject<Feature>();
#pragma warning disable CS0618 // Type or member is obsolete
        var actualFeatureObsoleted = builder.GetSection("Feature").Get<Feature>();
#pragma warning restore CS0618 // Type or member is obsolete
        // Assert
        actualFeature.ShouldBeEquivalentTo(expectedFeature);
        actualFeatureObsoleted.ShouldBeEquivalentTo(expectedFeature);
    }

    [TestMethod]
    public void Get_ShouldReturnCorrectValueAsString()
    {
        // Arrange
        var expectedFeature = "123";

        var builder = new ConfigurationBuilder()
            .AddJsonFile($"{_testFolder}appconfiguration.dev.json")
            .Build();

        // Act
        var actualFeature = builder.GetSection("AnotherSetting").Get<string>("Thresholds:High");

        // Assert
        actualFeature.ShouldBeEquivalentTo(expectedFeature);
    }

    /// <summary>
    ///     Testing a stupid indexer for compability with Microsoft ConfigurationBuilder
    /// </summary>
    [TestMethod]
    public void Indexer_ShouldReturnValueAsString()
    {
        // Arrange
        var expected = "SHA256";

        var builder = new ConfigurationBuilder()
            .AddJsonFile($"{_testFolder}appconfiguration.dev.json")
            .Build();

        // Act
        var actual = builder["Authentication"];

        // Assert
        actual.ShouldBeEquivalentTo(expected);
    }

    [TestMethod]
    public void Get_ShouldReturnCorrectValueAsInt()
    {
        // Arrange
        var expectedFeature = 22;

        var builder = new ConfigurationBuilder()
            .AddJsonFile($"{_testFolder}appconfiguration.dev.json")
            .Build();

        // Act
        var actualFeature = builder.GetSection("AnotherSetting:Temperature").Get<int>("Indoor:Max:Limit");

        // Assert
        actualFeature.ShouldBe(expectedFeature);
    }

    [TestMethod]
    public void Get_ShouldReturnCorrectValueAsNullBool()
    {
        // Arrange
        bool? expectedFeature = null;

        var configRoot = new ConfigurationBuilder()
            .AddJsonFile($"{_testFolder}appconfiguration.dev.json")
            .Build();

        // Act
        var actualFeature = configRoot.Get<bool?>("MissingKey:WhatThen");

        // Assert
        actualFeature.ShouldBe(expectedFeature);
    }
}

internal class Feature
{
    public bool Enabled { get; set; }
    public int RolloutPercentage { get; set; }
    public List<string> AllowedUserGroups { get; set; }
}