using Diligent.WebAPI.Data;
using Diligent.WebAPI.Host.Hubs;
using Diligent.WebAPI.Data.Entities;
using Diligent.WebAPI.Host.Mapper;
using MediatR;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.SignalR;
using Serilog;
using System.Reflection;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Diligent.WebAPI.Business.Services;
using Diligent.WebAPI.Host.Middlewares;
using Diligent.WebAPI.Business.Interfaces;

namespace Diligent.WebAPI.Host.Extensions;

public static class WebAppBuilder
{
    public static void ConfigureData(this WebApplicationBuilder builder, IConfiguration configuration)
    {
        // database configuration
        builder.Services.Configure<WebApiDatabaseSettings>(
            builder.Configuration.GetSection("WebApiDB"));

        builder.Services.AddAutoMapper(typeof(RequestMappingProfile));

        builder.Services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));
        builder.Services.AddScoped<IRequestRepository, RequestRepository>();
        builder.Services.AddScoped<IRoomRepository, RoomRepository>();
        builder.Services.AddScoped<IMongoDBContext, MongoDBContext>();
        builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
        builder.Services.AddScoped<ICustomerService, CustomerService>();

        builder.Services.AddSingleton<RoomService>();
        builder.Services.AddSingleton<AuthorizationService>();

        builder.Services.AddMediatR(Assembly.GetExecutingAssembly());
        builder.Services.AddSignalR(options =>
        {
            options.EnableDetailedErrors = true;
            options.AddFilter<AuthorizationHubFilter>();
        });

        builder.Services.AddSingleton<AuthorizationHubFilter>();

        var mongoDbSettings = configuration.GetSection("WebApiDB");

        builder.Services.AddIdentity<Customer, Roles>()
            .AddMongoDbStores<Customer, Roles, Guid>
            (
                mongoDbSettings["ConnectionString"], mongoDbSettings["DatabaseName"]
            );

        var jwtSettings = configuration.GetSection("JwtSettings");

        builder.Services.AddAuthentication(opt =>
        {
            opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
             .AddJwtBearer(options =>
             {
                 options.TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidateIssuer = true,
                     ValidateAudience = true,
                     ValidateLifetime = true,
                     ValidateIssuerSigningKey = true,
                     ValidIssuer = jwtSettings.GetSection("validIssuer").Value,
                     ValidAudience = jwtSettings.GetSection("validAudience").Value,
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["jwtSecret"]))
                 };
             });

        builder.Services.AddCors(options =>
        {
            options.AddPolicy("ClientPermission", policy =>
            {
                policy.AllowAnyHeader()
                    .AllowAnyMethod()
                    .WithOrigins("http://localhost:3000")
                    .AllowCredentials();
            });
        });

        var logger = new LoggerConfiguration()
            .ReadFrom.Configuration(builder.Configuration)
            .Enrich.FromLogContext()
            .CreateLogger();

        builder.Logging.ClearProviders();
        builder.Logging.AddSerilog(logger);

        builder.Services.AddSingleton<Serilog.ILogger>(Log.Logger);

        // SignalR group chat configuration
        builder.Services.AddSingleton<IDictionary<string, UserConnection>>(opts => new Dictionary<string, UserConnection>());
    }
}
