using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MTWorkHR.Core.Global;
using MTWorkHR.Infrastructure.Entities;

namespace MTWorkHR.Application.Filters
{
    public class AppAuthorize : AuthorizeAttribute, IAsyncAuthorizationFilter
    {
        public string Permissions { get; set; } //Permission string to get from controller

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            //The below line can be used if you are reading permissions from token
            //var permissionsFromToken=context.HttpContext.User.Claims.Where(x=>x.Type=="Permissions").Select(x=>x.Value).ToList()

            //var userNamex = context.HttpContext.User.Identity.Name;
            var cc = context.HttpContext.User.Identities.FirstOrDefault();
            var cc2 = cc.Claims.FirstOrDefault(c => c.Type.Contains( "email"));
            var email = cc2 != null ? cc2.Value : "";
            var generatedGuid = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("Jti")?.Value;
            var companyId = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("companyId")?.Value;
            var userId = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
            var userName = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("name")?.Value;
        //    var email1 = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("emailaddress").Value;
        //    var email2 = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("email").Value;
          //  var hierarchyIds = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("hierarchyIds").Value;
         //   var allowedBranchs = context.HttpContext.User.Identities.FirstOrDefault().FindFirst("branchs").Value;
           // var branch = context.HttpContext.Request.Headers.FirstOrDefault(x => x.Key == "branch").Value;
            var lang = context.HttpContext.Request.Headers.FirstOrDefault(x => x.Key == "lang").Value;
            var timeZone = context.HttpContext.Request.Headers.FirstOrDefault(x => x.Key == "timezone").Value;
           // var tenantLong = string.IsNullOrEmpty(tenant.ToString()) ? (long?)null : long.Parse(tenant);
            //var branchLong = string.IsNullOrEmpty(branch.ToString()) ? (long?)null : long.Parse(branch);
            var token = context.HttpContext.Request.Headers.FirstOrDefault(x => x.Key == "Authorization").Value;

           // var allowedHierarchies = hierarchyIds.Split(',');
          //  var hierarchyLong = !string.IsNullOrEmpty(hierarchyIds) && allowedHierarchies != null && allowedHierarchies.Count() > 0 ? allowedHierarchies.Select(h => long.Parse(h)).ToArray() : new long[] { };

            //check if header branch not in allowed branches
         //   var allowedBranchsArray = allowedBranchs.Split(',');
            //if (!string.IsNullOrEmpty(branch) && !allowedBranchs.Contains(branch))
            //{
            //    context.Result = new UnauthorizedResult();
            //    return;
            //}


            var globalInfo = context.HttpContext.RequestServices.GetService<GlobalInfo>();
            globalInfo.SetValues( userName, userId, companyId !=null && companyId != "" ? long.Parse(companyId) : null , token, lang, timeZone);

            var userManager = context.HttpContext.RequestServices.GetService<ApplicationUserManager>();
            bool hasAllowAnonymousFlag = context.ActionDescriptor.EndpointMetadata
                           .Any(em => em.GetType() == typeof(AllowAnonymousAttribute));
            if (hasAllowAnonymousFlag)
            {
                return;
            }
            //check if user blocked
            if (await userManager.IsStopped(userId))
            {
                context.Result = new UnauthorizedResult();
                return;
            }
            var loggedUser = await userManager.Users
               .FirstOrDefaultAsync(x => x.Id == userId);
            globalInfo.UserType = loggedUser != null ? (UserTypeEnum)loggedUser.UserType : UserTypeEnum.Employee;

            var requiredPermissions = Permissions?.Split(','); //Multiple permissiosn can be received from controller, delimiter "," is used to get individual values

            bool hasAllowAnonymous = context.ActionDescriptor.EndpointMetadata
                            .Any(em => em.GetType() == typeof(AllowAnonymousAttribute));

            if (!hasAllowAnonymous && requiredPermissions?.Length > 0)
            {
                var grantedPermissions = await userManager.GetUserPermission(globalInfo.UserId);
                if (!grantedPermissions.Any(x => requiredPermissions.Contains(x)))
                {
                    context.Result = new UnauthorizedResult();
                    return;
                }
            }

            return;
        }

    }
}
