using System;
using System.Linq;
using System.Text;
using DiplomovaPrace.Services.Security;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;

namespace DiplomovaPrace.Web.Server.Infrastructure.ConfigurationExtensions
{
	public static class AuthenticationConfig
	{
		private static bool addCustomizedAuthenticationCalled = false;

		public static void AddCustomizedAuthentication(this IServiceCollection services, IConfiguration configuration)
		{
			services.Configure<JwtConfiguration>(configuration.GetSection("AppSettings:JwtConfiguration"));
			JwtConfiguration jwtConfiguration = configuration.GetSection("AppSettings:JwtConfiguration").Get<JwtConfiguration>();

			AuthenticationBuilder authenticationBuilder = services.AddAuthentication(options =>
			{
				options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
				options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
			});

			authenticationBuilder = authenticationBuilder.AddJwtBearer(options =>
			{
				options.RequireHttpsMetadata = false;
				options.SaveToken = true;
				options.TokenValidationParameters = new TokenValidationParameters
				{
					ValidateIssuerSigningKey = true,
					IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtConfiguration.Key)),
					ValidateIssuer = false,
					ValidateAudience = false
				};
			});

			// Pod IClaimsTransformation je standardně zaregistrováno NoopClaimsTransformation
			// Pokud přidáme naší vlastní službu přes Castle Windsor, je tato až druhá a není tak resolvována (uff),
			// Proto tuto službu, kterou nechceme, odebereme (a použijeme službu zaregistrovanou přes Castle Windsor).
			services.Remove(services.Single(item => item.ImplementationType == typeof(NoopClaimsTransformation)));

			addCustomizedAuthenticationCalled = true;
		}

		public static string[] GetAuthenticationSchemes(IConfiguration configuration)
		{
			if (!addCustomizedAuthenticationCalled)
			{
				throw new InvalidOperationException("Nejdříve je třeba zavolat metodu AddCustomizedAuthentication.");
			}

			return new string[] { JwtBearerDefaults.AuthenticationScheme };
		}
	}
}
