using IRaCIS.Core.Application.Auth;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IRaCIS.Core.API
{
    public static class JWTAuthSetup
    {
        public static void AddJWTAuthSetup(this IServiceCollection services, IConfiguration configuration)
        {
            services.Configure<JwtSetting>(configuration.GetSection("JwtSetting"));

            var jwtSetting = new JwtSetting();
            configuration.Bind("JwtSetting", jwtSetting);

            services
               .AddAuthentication(o =>
               {
                   o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                   o.DefaultChallengeScheme = nameof(ApiResponseHandler);
                   o.DefaultForbidScheme = nameof(ApiResponseHandler);
               })
               .AddJwtBearer(options =>
               {
                   options.TokenValidationParameters = new TokenValidationParameters
                   {
                       ValidIssuer = jwtSetting.Issuer,
                       ValidAudience = jwtSetting.Audience,
                       IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSetting.SecurityKey)),
                       // 默认 300s
                       ClockSkew = TimeSpan.Zero
                   };



                   options.Events = new JwtBearerEvents
                   {
                       OnMessageReceived = (context) =>
                       {
                          
                           if (context.Request.Query.TryGetValue("access_token", out StringValues values))
                           {
                               var queryToken = values.FirstOrDefault();

                               if (!String.IsNullOrWhiteSpace(queryToken))
                               {
                                   context.Token = queryToken;

                                   return Task.CompletedTask;
                               }
                           }

                         
                           //仅仅是访问文件的时候才会去取token认证  前端对cookie设置了有效期

                           if (context.Request.Path.ToString().Contains("IRaCISData") || context.Request.Path.ToString().Contains("SystemData") )
                           {
                               var cookieToken = context.Request.Cookies["access_token"];

                               if (!String.IsNullOrWhiteSpace(cookieToken))
                               {
                                   context.Token = cookieToken;
                               }

                           }
                           return Task.CompletedTask;

                       }
                   };

                   // OPTION 1: use `Invio.Extensions.Authentication.JwtBearer`

                   //options.AddQueryStringAuthentication();



                   // OPTION 2: do it manually

                   #region
                   //options.Events = new JwtBearerEvents
                   //{
                   //    OnMessageReceived = (context) => {

                   //        if (!context.Request.Query.TryGetValue("access_token", out StringValues values))
                   //        {
                   //            return Task.CompletedTask;
                   //        }

                   //        if (values.Count > 1)
                   //        {
                   //            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                   //            context.Fail(
                   //                "Only one 'access_token' query string parameter can be defined. " +
                   //                $"However, {values.Count:N0} were included in the request."
                   //            );

                   //            return Task.CompletedTask;
                   //        }

                   //        var token = values.Single();

                   //        if (String.IsNullOrWhiteSpace(token))
                   //        {
                   //            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                   //            context.Fail(
                   //                "The 'access_token' query string parameter was defined, " +
                   //                "but a value to represent the token was not included."
                   //            );

                   //            return Task.CompletedTask;
                   //        }

                   //        context.Token = token;

                   //        return Task.CompletedTask;
                   //    }
                   //};
                   #endregion

               })
               .AddScheme<AuthenticationSchemeOptions, ApiResponseHandler>(nameof(ApiResponseHandler), o => { });

        }
    }
}
