using Grand.Business.Core.Interfaces.Common.Security;
using Grand.Business.Core.Utilities.Common.Security;
using Grand.Web.Common.DataSource;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace Grand.Web.Common.Security.Authorization
{
    [AttributeUsage(AttributeTargets.Method)]
    public class PermissionAuthorizeActionAttribute : Attribute, IAsyncAuthorizationFilter
    {
        public PermissionAuthorizeActionAttribute(string actionName)
        {
            PermissionAction = actionName;
        }

        // Get or set the permission property by manipulating
        public string PermissionAction { get; set; }

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            //ignore filter (the action available even when navigation is not allowed)
            ArgumentNullException.ThrowIfNull(context);

            if (string.IsNullOrEmpty(PermissionAction))
                return;

            //check whether PermissionAuthorizeAttribute filter exists
            var permissionAuthorize = context.Filters
                .OfType<PermissionAuthorizeAttribute>().FirstOrDefault();

            if (permissionAuthorize == null || string.IsNullOrEmpty(permissionAuthorize.Permission))
                return;

            var permissionService = context.HttpContext.RequestServices.GetRequiredService<IPermissionService>();

            //check whether current customer has access to a public store
            if (await permissionService.AuthorizeAction(permissionAuthorize.Permission, PermissionAction))
                return;

            //authorize permission of access to the admin area
            if (!await permissionService.Authorize(StandardPermission.ManageAccessAdminPanel))
                context.Result = new RedirectToRouteResult("AdminLogin", new RouteValueDictionary());
            else
            {
                var isAjaxCall = context.HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest";
                if (!isAjaxCall)
                    context.Result = new RedirectToActionResult("AccessDenied", "Home", new { pageUrl = context.HttpContext.Request.Path });
                else
                {
                    context.Result = new JsonResult(new DataSourceResult { Errors = $"Access denied to the resource {context.HttpContext.Request.Path}" });
                }
            }
        }
    }
}
