using CloudBuilder.Core.Application.Packs;
using CloudBuilder.Core.Authorization;
using CloudBuilder.Core.DatabaseAccessor;
using CloudBuilder.Core.DatabaseAccessor.Entity;
using CloudBuilder.Core.DependencyInjection.Request;
using CloudBuilder.Core.Policy;
using CloudBuilder.Core.Service;
using CloudBuilder.Security.Policy;
using DocumentFormat.OpenXml.Drawing.Charts;
using DocumentFormat.OpenXml.EMMA;
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
using DocumentFormat.OpenXml.Wordprocessing;
using EnvDTE;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace CloudBuilder.Security.Service.Authorization
{
    public class PermissionHandler : AuthorizationHandler<PermissionRequirement>, IAuthorize
    {
        private readonly WebService service;
        private readonly IContext loginContext;
        private readonly IHttpContextAccessor httpContextAccessor;

        public PermissionHandler(WebService service, IContext loginContext, IHttpContextAccessor httpContextAccessor)
        {
            this.service = service;
            this.loginContext = loginContext;
            this.httpContextAccessor = httpContextAccessor;
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
        {
            if (context.HasFailed) return Task.CompletedTask;

            var httpContext = httpContextAccessor.HttpContext;

            EndpointMetadataCollection collection = httpContext.GetEndpoint().Metadata;

            PermissionOperateAttribute permission = null;
            foreach (var item in collection)
            {
                if (!(item is PermissionOperateAttribute)) continue;
                permission = (PermissionOperateAttribute)item;
                break;
            }

            //没有设置权限名出错
            if (permission == null)
            {
                context.Fail();
                return Task.CompletedTask;
            }

            string userName = ClaimPolicy.GetClaimValue(httpContextAccessor, ClaimPolicy.CLAINM_USERID);
            loginContext.Requestor = userName;
            loginContext.SetToken(ClaimPolicy.GetJwtBearerToken(httpContextAccessor.HttpContext));
            loginContext.SetCulture(ClaimPolicy.GetClaimValue(httpContextAccessor, ClaimPolicy.CLAINM_LOCALE) ?? CulturePolicy.ZH_CN);

            IApplicationService applicationService = service.Services.BuildServiceProvider().GetRequiredService<IApplicationService>();
            PermissionContext permissionContext = new PermissionContext(applicationService);

            bool result = false;
            switch (permission.Operate)
            {
                case "None":
                    result = permissionContext.CanNone(permission.Name);
                    break;
                case "Find":
                case "Print":
                    result = permissionContext.CanView(permission.Name);
                    break;
                case "Insert":
                    result = permissionContext.CanCreate(permission.Name);
                    break;
                case "Update":
                    result = permissionContext.CanAmend(permission.Name);
                    break;
                case "Delete":
                    result = permissionContext.CanDelete(permission.Name);
                    break;
                default:
                    result = permissionContext.CanNone(permission.Name, permission.Operate);
                    break;
            }

            if (result && httpContext != null)
            {
                context.Succeed(requirement);
                return Task.CompletedTask;
            }

            context.Fail();

            return Task.CompletedTask;
        }
    }
}
