using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

using AIRuntime.Runtime.Agents.Permissions;
using AIRuntime.Runtime.Capabilities;
using AIRuntime.Runtime.Models;
using AIRuntime.Runtime.Providers.Models;

using NUnit.Framework;


namespace AIRuntime.Tests
{
    public sealed class CapabilityIsolationTests
    {


        //--------------------------------------------------
        // Allowed Capability Executes
        //--------------------------------------------------

        [Test]
        public void Policy_Allows_GrantedCapability()
        {
            CapabilityAccessPolicy policy =
                new CapabilityAccessPolicy();


            policy.Allow(
                "ReadFile");


            Assert.IsTrue(
                policy.CanUse(
                    "ReadFile"));
        }



        //--------------------------------------------------
        // Missing Capability Blocked
        //--------------------------------------------------

        [Test]
        public void Policy_Blocks_UnapprovedCapability()
        {
            CapabilityAccessPolicy policy =
                new CapabilityAccessPolicy();


            policy.Allow(
                "ReadFile");


            Assert.IsFalse(
                policy.CanUse(
                    "DeleteFile"));
        }



        //--------------------------------------------------
        // Duplicate Permissions Safe
        //--------------------------------------------------

        [Test]
        public void Policy_DuplicateAllowDoesNotDuplicate()
        {
            CapabilityAccessPolicy policy =
                new CapabilityAccessPolicy();


            policy.Allow(
                "ReadFile");


            policy.Allow(
                "ReadFile");


            Assert.AreEqual(
                1,
                policy.AllowedCapabilities.Count);
        }



        //--------------------------------------------------
        // Remove Permission
        //--------------------------------------------------

        [Test]
        public void Policy_Deny_RemovesCapability()
        {
            CapabilityAccessPolicy policy =
                new CapabilityAccessPolicy();


            policy.Allow(
                "ReadFile");


            policy.Deny(
                "ReadFile");


            Assert.IsFalse(
                policy.CanUse(
                    "ReadFile"));
        }



        //--------------------------------------------------
        // Clear Permissions
        //--------------------------------------------------

        [Test]
        public void Policy_Clear_RemovesAllCapabilities()
        {
            CapabilityAccessPolicy policy =
                new CapabilityAccessPolicy();


            policy.Allow(
                "ReadFile");


            policy.Allow(
                "WriteFile");


            policy.Clear();


            Assert.AreEqual(
                0,
                policy.AllowedCapabilities.Count);
        }



        //--------------------------------------------------
        // Unknown Capability Cannot Be Added Empty
        //--------------------------------------------------

        [Test]
        public void Policy_RejectsEmptyCapabilityNames()
        {
            CapabilityAccessPolicy policy =
                new CapabilityAccessPolicy();


            Assert.Throws<ArgumentException>(
                () =>
                {
                    policy.Allow(
                        "");
                });
        }



        //--------------------------------------------------
        // Agent Profiles Isolation
        //--------------------------------------------------

        [Test]
        public void DifferentAgentsHaveDifferentPolicies()
        {
            CapabilityAccessPolicy architectPolicy =
                new CapabilityAccessPolicy();


            CapabilityAccessPolicy developerPolicy =
                new CapabilityAccessPolicy();


            architectPolicy.Allow(
                "ReadFile");


            developerPolicy.Allow(
                "WriteFile");


            Assert.IsTrue(
                architectPolicy.CanUse(
                    "ReadFile"));


            Assert.IsFalse(
                architectPolicy.CanUse(
                    "WriteFile"));


            Assert.IsTrue(
                developerPolicy.CanUse(
                    "WriteFile"));


            Assert.IsFalse(
                developerPolicy.CanUse(
                    "ReadFile"));
        }
    }
}
