using Unity;
using Xunit;

namespace VCommon.Ioc.Tests
{
    public class ChildContainerTests
    {
        public class Session
        {
            public int UserId { get; set; }
        }

        public class Setting : ISingletonIocClass
        {
            public string Value { get; set; } = "Keep";
        }

        public abstract class AbstractContext
        {

        }

        private class ContextImpl : AbstractContext
        {
        }

        public class Service : ITransientIocClass
        {
            [Dependency] public AbstractContext Context { get; set; }
        }

        [Fact]
        public void ChildContainerTest()
        {
            var rootContainer = new IocManager();

            var child1 = rootContainer.CreateChildren();
            var child2 = rootContainer.CreateChildren();
            var child3 = rootContainer.CreateChildren();

            child1.RegisterInstanceToContainer(new Session { UserId = 1 });
            child2.RegisterInstanceToContainer(new Session { UserId = 2 });
            child3.RegisterInstanceToContainer<AbstractContext>(new ContextImpl());
            
            Assert.Same(rootContainer, rootContainer.Resolve<IIocManager>());
            Assert.Same(child1, child1.Resolve<IIocManager>());
            Assert.Same(child2, child2.Resolve<IIocManager>());
            Assert.Same(child3, child3.Resolve<IIocManager>());

            Assert.True(rootContainer.IsRegistered<Setting>());
            Assert.True(child1.IsRegistered<Setting>());
            Assert.True(child2.IsRegistered<Setting>());

            Assert.Same(rootContainer.Resolve<Setting>(), child1.Resolve<Setting>());
            Assert.Same(rootContainer.Resolve<Setting>(), child2.Resolve<Setting>());

            Assert.False(rootContainer.IsRegistered<Session>());
            Assert.True(child1.IsRegistered<Session>());
            Assert.True(child2.IsRegistered<Session>());
            Assert.False(child3.IsRegistered<Session>());

            Assert.Equal(1, child1.Resolve<Session>().UserId);
            Assert.Equal(2, child2.Resolve<Session>().UserId);

            Assert.True(rootContainer.IsRegistered<Service>());
            Assert.True(child1.IsRegistered<Service>());
            Assert.True(child2.IsRegistered<Service>());
            Assert.True(child3.IsRegistered<Service>());


            Assert.Throws<ResolutionFailedException>(() => rootContainer.Resolve<Service>());
            Assert.Throws<ResolutionFailedException>(() => child1.Resolve<Service>());
            Assert.Throws<ResolutionFailedException>(() => child2.Resolve<Service>());
            child3.Resolve<Service>();
        }
    }
}
