using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authentication.Firebase;
using Indotalent.Infrastructure.Authentication.Identity;
using Indotalent.Infrastructure.Authentication.Keycloak;
using Indotalent.Infrastructure.Database;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace Indotalent.Infrastructure.Authentication;

public static class DI
{
    public static IServiceCollection AddAuthenticationService(this IServiceCollection services, IConfiguration configuration)
    {
        //Identity
        services.AddScoped<IdentityService>();

        services.AddHttpContextAccessor();
        services.AddCascadingAuthenticationState();

        services.Configure<JwtSettingsModel>(configuration.GetSection("JwtSettings"));
        services.AddScoped<TokenProvider>();

        var identitySettings = configuration.GetSection("IdentitySettings").Get<IdentitySettingsModel>() ?? new IdentitySettingsModel();

        services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.Password.RequireDigit = identitySettings.Password.RequireDigit;
            options.Password.RequiredLength = identitySettings.Password.RequiredLength;
            options.Password.RequireNonAlphanumeric = identitySettings.Password.RequireNonAlphanumeric;
            options.Password.RequireUppercase = identitySettings.Password.RequireUppercase;
            options.Password.RequireLowercase = identitySettings.Password.RequireLowercase;
            options.SignIn.RequireConfirmedAccount = identitySettings.SignIn.RequireConfirmedAccount;
        })
        .AddEntityFrameworkStores<AppDbContext>()
        .AddDefaultTokenProviders()
        .AddClaimsPrincipalFactory<CustomClaimsPrincipalFactory>();

        services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = IdentityConstants.ApplicationScheme;
            options.DefaultSignInScheme = IdentityConstants.ApplicationScheme;
            options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
        })
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
        {
            var jwtSettings = configuration.GetSection("JwtSettings").Get<JwtSettingsModel>();
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = jwtSettings?.Issuer,
                ValidAudience = jwtSettings?.Audience,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings?.Key ?? "PRAGMATIC_FIX_KEY_MIN_32_CHARS_LONG_2026"))
            };
        });

        services.ConfigureApplicationCookie(options =>
        {
            options.LoginPath = identitySettings.Cookies.LoginPath;
            options.LogoutPath = identitySettings.Cookies.LogoutPath;
            options.AccessDeniedPath = identitySettings.Cookies.AccessDeniedPath;
            options.Cookie.Name = identitySettings.Cookies.Name;
            options.ExpireTimeSpan = TimeSpan.FromDays(identitySettings.Cookies.ExpireDays);
            options.Cookie.HttpOnly = true;
            options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            options.Cookie.SameSite = SameSiteMode.Lax;
        });


        //Firebase

        services.AddScoped<FirebaseService>();

        //Keycloak

        services.AddScoped<KeycloakService>();

        return services;
    }
}
