using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using TINK.Repository;
using TINK.Repository.Response;
using static TINK.Repository.CopriCallsMemory;

namespace TestTINKLib.Fixtures.Connector.Request
{
    
    [TestFixture]
    public class TestCopriCallsMemory
    {
        [Test]
        public void TestConsistency()
        {
            foreach (SampleSets l_oSampleSet in Enum.GetValues(typeof(SampleSets)))
            {
                var l_oCopri = new CopriCallsMemory(l_oSampleSet, 1, "4da3044c8657a04ba60e2eaa753bc51a");

                for (var l_iStageIndex = 1; l_iStageIndex <= l_oCopri.StagesCount; l_iStageIndex++)
                {
                    Assert.That(l_oCopri.GetBikesAvailableAsync().Result?.bikes, Is.Not.Null, $"There must be at least one bike for sample set {l_oSampleSet}, stage {l_iStageIndex}.");
                    VerifyBikeIdIsUnique(l_oCopri);

                    Assert.IsNull(
                        l_oCopri.GetBikesAvailableAsync().Result.bikes.Values.FirstOrDefault(x => x.state != "available"),
                        "Bikes available must return bikes which are all of state available.");

                    Assert.IsNull(
                        l_oCopri.GetBikesOccupiedAsync().Result.bikes_occupied.Values.FirstOrDefault(x => x.state == "available"),
                        "Bikes occupied must return bikes which are either reserved or booked.");
                }
            }
        }

        /// <summary>
        /// Test consistency for a single sample set, 
        /// </summary>
        /// <param name="p_oMemory"></param>
        private void VerifyBikeIdIsUnique(CopriCallsMemory p_oMemory)
        {
            Dictionary<string, BikeInfoBase> l_oChecker = new Dictionary<string, BikeInfoBase>();

            var l_oBikesAvailable = p_oMemory.GetBikesAvailableAsync().Result;
            foreach (var l_oBike in l_oBikesAvailable.bikes.Values)
            {
                Assert.IsFalse(
                    l_oChecker.Keys.Contains(l_oBike.bike), 
                    string.Format(
                        "Bike form available bikes with id {0} already exist in dictionary. Sample set is {1}, stage index {2}.",
                        l_oBike.bike,
                        p_oMemory.ActiveSampleSet,
                        p_oMemory.ActiveStageIndex));

                l_oChecker.Add(l_oBike.bike, l_oBike);
            }

            var l_oBikesOccupied = p_oMemory.GetBikesOccupiedAsync().Result;
            foreach (var l_oBike in l_oBikesOccupied.bikes_occupied.Values)
            {
                Assert.IsFalse(
                    l_oChecker.Keys.Contains(l_oBike.bike),
                    string.Format(
                        "Bike from occupied bikes with id {0} already exist in dictionary. Sample set is {1}, stage index {2}.",
                        l_oBike.bike,
                        p_oMemory.ActiveSampleSet,
                        p_oMemory.ActiveStageIndex));
                l_oChecker.Add(l_oBike.bike, l_oBike);
            }
        }
    }
}