using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Core.Cerberos.Adapters.Attributes
{
    /// 
    /// Custom authorization attribute that checks if the user has any of the required permissions.
    /// 
    [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
    public class PermissionAttribute : AuthorizeAttribute, IAuthorizationFilter
    {
        private readonly string _requiredPermissions;
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The array of permissions required to access the resource.
        public PermissionAttribute(string requiredPermissions)
        {
            _requiredPermissions = requiredPermissions;
        }
        /// 
        /// Called during the authorization process to determine if the user has any of the required permissions.
        /// 
        /// The context in which the authorization filter operates.
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            try
            {
                var hasPermission = false;
                var servicePermissionsList = _requiredPermissions.Replace(" ", "").Split(',').ToList();
                var servicePermissions = servicePermissionsList.Select(s => new Permission
                {
                    Name = s.Substring(0, s.IndexOf('.')),
                    AccessLevel = s.Substring(s.IndexOf('.') + 1),
                });
                var userPermissionsList = context.HttpContext.User.Claims
                    .Where(c => c.Type == "permissions")
                    .Select(c => c.Value)
                    .ToList();
                var userPermissions = userPermissionsList.Select(s => new Permission
                {
                    Name = s.Substring(0, s.IndexOf('.')),
                    AccessLevel = s.Substring(s.IndexOf('.') + 1),
                });
                foreach (var servicePermission in servicePermissions)
                {
                    hasPermission = userPermissions
                        .Where(up => up.Name == servicePermission.Name && up.AccessLevel == "All"
                                   || up.Name == servicePermission.Name && up.AccessLevel == servicePermission.AccessLevel)
                        .Count() > 0 ? true : false;
                    if (hasPermission) break;
                }
                if (!hasPermission)
                    context.Result = new UnauthorizedResult();
            }
            catch (Exception ex)
            {
                context.Result = new UnauthorizedResult();
            }
        }
    }
}