using System;
using System.Collections.Generic;
using AIRuntime.Runtime.Agents.Permissions;


namespace AIRuntime.Runtime.Agents
{
    /// <summary>
    /// Defines the identity and behaviour contract of an agent.
    /// This is configuration data, not execution state.
    /// </summary>
    public sealed class AgentDefinition
    {
        private readonly CapabilityAccessPolicy _policy =
            new CapabilityAccessPolicy();
        private AgentProfile _profile;
        public AgentDefinition(
            string id,
            string displayName,
            string description,
            string systemPrompt)
        {
            if (string.IsNullOrWhiteSpace(id))
            {
                throw new ArgumentException(
                    "Agent id cannot be empty.",
                    nameof(id));
            }


            if (string.IsNullOrWhiteSpace(displayName))
            {
                throw new ArgumentException(
                    "Agent display name cannot be empty.",
                    nameof(displayName));
            }


            Id =
                id;


            DisplayName =
                displayName;


            Description =
                description ??
                string.Empty;


            SystemPrompt =
                systemPrompt ??
                string.Empty;
            
            _profile =
                new AgentProfile(
                    Id);
        }


        /// <summary>
        /// Unique agent identifier.
        /// Example: ArchitectAgent
        /// </summary>
        public string Id
        {
            get;
        }


        /// <summary>
        /// Friendly display name.
        /// </summary>
        public string DisplayName
        {
            get;
        }


        /// <summary>
        /// Description of the agent role.
        /// </summary>
        public string Description
        {
            get;
        }


        /// <summary>
        /// Instructions supplied to the model.
        /// </summary>
        public string SystemPrompt
        {
            get;
        }
        /// <summary>
        /// Runtime configuration for this agent.
        /// </summary>
        public AgentProfile Profile
        {
            get
            {
                return _profile;
            }
        }

        /// <summary>
        /// Capabilities this agent is allowed to use.
        /// </summary>
        public IReadOnlyCollection<string> Capabilities
        {
            get
            {
                return _policy.AllowedCapabilities;
            }
        }

        public void AttachProfile(
            AgentProfile profile)
        {
            if (profile == null)
            {
                throw new ArgumentNullException(
                    nameof(profile));
            }


            if (profile.AgentId != Id)
            {
                throw new InvalidOperationException(
                    $"Profile agent id '{profile.AgentId}' does not match definition '{Id}'.");
            }


            _profile =
                profile;
        }
        public void AddCapability(
            string capabilityName)
        {
            if (string.IsNullOrWhiteSpace(capabilityName))
            {
                throw new ArgumentException(
                    "Capability name cannot be empty.",
                    nameof(capabilityName));
            }


            _policy.Allow(
                capabilityName);
        }

        public CapabilityAccessPolicy CapabilityPolicy
        {
            get
            {
                return _policy;
            }
        }
        public void AllowCapability(
            string capabilityName)
        {
            _policy.Allow(
                capabilityName);
        }


        public bool CanUseCapability(
            string capabilityName)
        {
            return _policy.CanUse(
                capabilityName);
        }
        public void RemoveCapability(
            string capabilityName)
        {
            if (string.IsNullOrWhiteSpace(capabilityName))
                return;


            _policy.Deny(
                capabilityName);
        }
        
    }
    
}
