using Ashermed.ApiLogCoreFramework.ContractModel;
using Ashermed.ApiLogCoreFramework.Service;
using ASHermed.SingleSignOnFramework;
using ASHermed.SinoInterface.Api.IService;
using ASHermed.SinoInterface.Exception;
using ASHermed.SinoInterface.Tools;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using PoJun.Util.Helpers;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace ASHermed.SinoInterface.WebApi.Filters
{
    /// <summary>
    /// 不强制使用token
    /// </summary>
    public class TokenIgnoreFilter : ActionFilterAttribute, IActionFilter
    {
        /// <summary>
        /// token服务
        /// </summary>
        private readonly ITokenService _tokenService;

        /// <summary>
        /// 接口日志服务
        /// </summary>
        private readonly IAPILogService _apiLogService;

        /// <summary>
        /// 文本日志
        /// </summary>
        private readonly ILogger<TokenIgnoreFilter> _logger;

        /// <summary>
        ///  ctor
        /// </summary>
        /// <param name="tokenService"></param>
        /// <param name="apiLogService"></param>
        /// <param name="logger"></param>
        public TokenIgnoreFilter(ITokenService tokenService, IAPILogService apiLogService, ILogger<TokenIgnoreFilter> logger)
        {
            _tokenService = tokenService;
            _apiLogService = apiLogService;
            _logger = logger;
        }

        /// <summary>
        /// invoke
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            #region 获取传入的数据

            //logger.LogError("OnActionExecutionAsync11111----------");
            var jsonData = string.Empty;

            if (context.HttpContext.Request.ContentType != null)
            {
                var contentType = context.HttpContext.Request.ContentType.ToLower();
                if ((contentType.Contains("application/x-www-form-urlencoded")
                     || contentType.Contains("multipart/form-data"))
                    && context.HttpContext.Request.ContentLength != null
                    && context.HttpContext.Request.ContentLength > 0)
                {
                    jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(context.HttpContext.Request.Form);
                }
                else if (contentType.Contains("application/json"))
                {
                    foreach (var item in context.ActionArguments)
                    {
                        jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(item.Value);
                    }
                }
            }

            #endregion

            #region 新增接口日志

            //获取日志ID
            var logTraceId = Id.GetGuidBy32();
            var requestTime = DateTime.Now;

            var logParam = new AddRequestLogParam
            {
                APIName = context.HttpContext.Request.Path.ToString().ToLower(),
                //这里存储的是客户端的IP+端口
                ClientHost =
                    $"{context.HttpContext.Connection.RemoteIpAddress}:{context.HttpContext.Connection.RemotePort}",
                Headers = Newtonsoft.Json.JsonConvert.SerializeObject(context.HttpContext.Request.Headers.ToList()),
                Level = 1,
                RequestBody = jsonData,
                //这里存储的当前服务器的IP+端口+接口地址+url参数
                ServerHost =
                    $"{Web.Ip}:{context.HttpContext.Request.Host.Port}{context.HttpContext.Request.Path}{context.HttpContext.Request.QueryString}",
                SystemID = SysUtil.GetSystemId(),
                TraceID = logTraceId,
                RequestTime = requestTime
            };

            try
            {
                //新增日志
                await _apiLogService.AddRequestLogAsync(logParam);
            }
            catch (System.Exception)
            {
                //记录文本日志
                _logger.LogCritical($"{Newtonsoft.Json.JsonConvert.SerializeObject(logParam)},");
            }

            #endregion

            #region 向后传输数据

            //把日志ID写入
            context.HttpContext.Items.Add(nameof(APILogConfig.PoJun_LogTraceID), logTraceId);
            context.HttpContext.Request.Headers.Add(nameof(APILogConfig.PoJun_LogTraceID), logTraceId);
            //把接口请求时间写入
            context.HttpContext.Items.Add(nameof(APILogConfig.RequestTime), requestTime);
            context.HttpContext.Request.Headers.Add(nameof(APILogConfig.RequestTime),
                requestTime.ToString("yyyy-MM-dd HH:mm:ss.fff"));

            #endregion

            #region 根据控制器名称判断是否进行登录验证

            var controller = MyHttpContext.Current.Request.RouteValues["controller"].ToString()?.ToLower();
            if (SingleSignOnConfig.GetInstance().ExcludeControllerNames.Contains(controller))
            {
                await base.OnActionExecutionAsync(context, next);
                return;
            }

            #endregion

            #region Token校验

            if (string.IsNullOrEmpty(SysUtil.GetClientId()))
                throw new ParamErrorException("请传入正确的版本号！");

            if (string.IsNullOrEmpty(SysUtil.GetToken()))
            {
                await base.OnActionExecutionAsync(context, next);
                return;
            }

            //if (SysUtil.GetClientType() == ClientType.None)
            //    throw new ParamErrorException("请传入正确的客户端类型！");

            try
            {
                if (context.HttpContext.Request.Headers.TryGetValue("Authorization", out var authorizationString))
                {
                    if (string.IsNullOrEmpty(authorizationString) || authorizationString == "null")
                    {
                        await base.OnActionExecutionAsync(context, next);
                        return;
                    }
                }

                var result = _tokenService.CheckToken(SysUtil.GetToken());
                if (result.VersionUpdateTime == null ||
                    System.Convert.ToDateTime(result.VersionUpdateTime).ToString("yyyy-MM-dd") !=
                    DateTime.Now.ToString("yyyy-MM-dd"))
                {
                    _tokenService.UpdateUserVersion(result.ID, SysUtil.GetClientId());
                }

                if (result == null)
                    throw new BaseException("token验证失败");

                var userInfo = result;
                //把用户信息存入本次请求中
                context.HttpContext.Items.Add(nameof(APILogConfig.LoginUserInfo), userInfo);
                context.HttpContext.Request.Headers.Add(nameof(APILogConfig.LoginUserInfo),
                    Newtonsoft.Json.JsonConvert.SerializeObject(userInfo));
            }
            catch
            {
                await base.OnActionExecutionAsync(context, next);
                return;
            }



            #endregion

            await base.OnActionExecutionAsync(context, next);
        }
    }
}