using Invio.Extensions.Authentication.JwtBearer;
using IRaCIS.Core.Application.Auth;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Text;

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
                   };

                   // 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 => { });
                       
        }
    }
}