using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using TEAMModelOS.SDK.Extension;
using System;
using TEAMModelOS.Models;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;

namespace TEAMModelOS.Filter
{
    public class AuthTokenAttribute : Attribute, IFilterFactory
    {
        public bool IsReusable => true;
        public string Roles { get; set; }
        public string Permissions { get; set; }

        public IFilterMetadata CreateInstance(IServiceProvider services)
        {
            var option = services.GetService<IOptions<Option>>();
            return new InternalAuthTokenFilter(option, Roles, Permissions);
        }

        private class InternalAuthTokenFilter : IResourceFilter
        {
            private readonly Option _option;
            private readonly string _roles;
            private readonly string _permissions;

            public InternalAuthTokenFilter(IOptions<Option> option, string roles, string permissions)
            {
                _option = option.Value;
                _roles = roles;
                _permissions = permissions;
            }
            public void OnResourceExecuting(ResourceExecutingContext context)
            {
                bool pass = false;
                string id = string.Empty, name = string.Empty, picture = string.Empty, school = string.Empty;
                var authtoken = context.HttpContext.GetXAuth("AuthToken");
                if (!string.IsNullOrWhiteSpace(authtoken) && JwtAuthExtension.ValidateAuthToken(authtoken, _option.JwtSecretKey))
                {
                    var jwt = new JwtSecurityTokenHandler().ReadJwtToken(authtoken);
                    id = jwt.Payload.Sub;
                    school = jwt.Payload.Azp;
                    name = jwt.Claims.FirstOrDefault(claim => claim.Type == "name")?.Value;
                    picture = jwt.Claims.FirstOrDefault(claim => claim.Type == "picture")?.Value;

                    if (!string.IsNullOrWhiteSpace(_roles))
                    {
                        var roles = jwt.Claims.Where(c => c.Type == "roles");
                        foreach (var role in roles)
                        {
                            if (_roles.Contains(role.Value, StringComparison.Ordinal))
                            {
                                pass = true;
                                break;
                            }
                        }
                    }
                    if (!string.IsNullOrWhiteSpace(_permissions))
                    {
                        var permissions = jwt.Claims.Where(c => c.Type == "permissions");
                        foreach (var permission in permissions)
                        {
                            if (_permissions.Contains(permission.Value, StringComparison.Ordinal))
                            {
                                pass = true;
                                break;
                            }
                        }
                    }
                }

                if (pass)
                {
                    context.HttpContext.Items.Add("ID", id);
                    context.HttpContext.Items.Add("Name", name);
                    context.HttpContext.Items.Add("Picture", picture);
                    context.HttpContext.Items.Add("School", school);
                }
                else
                    context.Result = new BadRequestResult();
            }

            public void OnResourceExecuted(ResourceExecutedContext context)
            {
            }
        }
    }
}
