using FabAccessAPI;
using FabAccessAPI.Schema;
using NUnit.Framework;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace FabAccessAPI_Test.API_TestEnv
{
    [TestFixture, Parallelizable(ParallelScope.Children)]
    [Order(2)]
    public class User_Test_Stateless
    {
        [TestCase("Admin1", true)]
        [TestCase("ManagerA1", true)]
        [TestCase("MakerA1", true)]
        [TestCase("GuestA1", true)]
        [Order(1)]
        public async Task InfoInterface(string username, bool expectInterface)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);

            bool result = !((User.InfoInterface_Proxy)user.Info).IsNull;

            await api.Disconnect();

            Assert.AreEqual(expectInterface, result);
        }

        [TestCase("Admin1", true)]
        [TestCase("ManagerA1", true)]
        [TestCase("MakerA1", true)]
        [TestCase("GuestA1", true)]
        [Order(2)]
        public async Task ManageInterface(string username, bool expectInterface)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);

            bool result = !((User.ManageInterface_Proxy)user.Manage).IsNull;

            await api.Disconnect();

            Assert.AreEqual(expectInterface, result);
        }

        [TestCase("Admin1", true)]
        [TestCase("ManagerA1", true)]
        [TestCase("MakerA1", false)]
        [TestCase("GuestA1", false)]
        [Order(3)]
        public async Task AdminInterface(string username, bool expectInterface)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);

            bool result = !((User.AdminInterface_Proxy)user.Admin).IsNull;

            await api.Disconnect();

            Assert.AreEqual(expectInterface, result);
        }

        [TestCase("Admin1")]
        [TestCase("ManagerA1")]
        [TestCase("MakerA1")]
        [TestCase("GuestA1")]
        [Order(4)]
        public async Task ReadUserData(string username)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);

            await api.Disconnect();

            Assert.Multiple(() =>
            {
                Assert.AreEqual(username, user.Username);
            });
        }

        [TestCase("Admin1", "Admin", "ManageUsers")]
        [TestCase("ManagerA1", "ManageA", "UseA", "ReadA", "DiscloseA", "ManageUsers")]
        [TestCase("MakerA1", "UseA", "ReadA", "DiscloseA")]
        [TestCase("GuestA1", "ReadA", "DiscloseA")]
        [Order(5)]
        public async Task ListUserRoles(string username, params string[] expect_roles)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);

            List<Role> roles_user = new List<Role>(await user.Info.ListRoles().ConfigureAwait(false));
            List<string> expect_roles_list = new List<string>(expect_roles);

            await api.Disconnect();

            if (roles_user.Count != expect_roles_list.Count)
            {
                Assert.Fail("Roles Count is different");
            }

            foreach (Role role_user in roles_user)
            {
                if (!expect_roles_list.Exists(x => x == role_user.Name))
                {
                    Assert.Fail("Roles are different");
                }
            }
        }
    }
}
