using System.Linq;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Redis;

namespace Siger.ApiCommon.Filters
{
    public class TokenValidateFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (context.Filters.Any(q => q.GetType() == typeof(NoTokenValidateFilter)))
            {
                return;
            }
            var referer = GetHead(context, ParameterConstant.Referer);
            if (referer != null && referer.Contains("swagger/ui") && referer.Contains("projectid="))
            {
                return;
            }

            var token = GetHead(context, ParameterConstant.Token);
            if (token == null)
            {
                throw new BadRequestException(CommonEnum.TokenIsEmpty);
            }
            //if (RedisCache.Client == null || RedisCache.Client.Nodes == null || RedisCache.Client.Nodes.IsEmpty)
            //{
            //    RedisCache.Instance.Connect();
            //}
            if (RedisCache.Client == null)
            {
                throw new BadRequestException(CommonEnum.GetTokenFailed);
            }
            var controllerName = context.RouteData.Values["controller"];
            var actionName = context.RouteData.Values["action"];
            if (controllerName?.ToString() == "Login" && actionName?.ToString() == "Login")
            {
                if (string.IsNullOrEmpty(RedisCache.Client.Get(token)))
                {
                    throw new BadRequestException(CommonEnum.RequestInValid);
                }
            }
            else
            {
                var isvalid = RedisCache.Instance.IsValidToken(token);
                if (!isvalid)
                {
                    throw new BadRequestException(CommonEnum.TokenIsInvalid);
                }
            }

            var timestamp = GetHead(context, ParameterConstant.TimeStamp);
            if (timestamp == null)
            {
                throw new BadRequestException(CommonEnum.TimeStampIsEmpty);
            }
            var random = GetHead(context, ParameterConstant.Nonce);
            if (random == null)
            {
                throw new BadRequestException(CommonEnum.NonceIsEmpty);
            }
            var signValue = GetHead(context, ParameterConstant.Sign);
            if (signValue == null)
            {
                throw new BadRequestException(CommonEnum.SignIsEmpty);
            }

            var unSignedParameter = $"timestamp={timestamp}&nonce={random}";
            var signed = MD5Helper.GetHashString(unSignedParameter);
            if (!signed.IsEqual(signValue))
            {
                throw new BadRequestException(CommonEnum.SignIsInvalid);
            }
        }

        private string GetHead(ActionExecutingContext context, string key)
        {
            var hasValue = context.HttpContext.Request.Headers.TryGetValue(key, out StringValues value);
            if (hasValue)
            {
                return value;
            }
            return null;
        }
    }
}
