//using AAIntegration.SimmonsBank.API.Authorization;
using AAIntegration.SimmonsBank.API.Config;
using Microsoft.EntityFrameworkCore;

using AAIntegration.SimmonsBank.API.Services;
using Microsoft.OpenApi.Models;
using System.Text.Json.Serialization;
using AAIntegration.SimmonsBank.API.Configs;
using AAIntegration.SimmonsBank.API.Handlers;
using Microsoft.IdentityModel.Tokens;
using System.Text;
//using Microsoft.Build.Framework;
using Microsoft.AspNetCore.Authorization;
using AAIntegration.SimmonsBank.API.Processes;
using AAIntegration.SimmonsBank.API.Workers;

internal class Program
{
    private static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // Add services to the container.
        var  MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
        
        builder.Services.AddCors(options =>
        {
            options.AddPolicy("ClientPermission", policy =>
            {
                policy.AllowAnyHeader()
                    .AllowAnyMethod()
                    .SetIsOriginAllowed(_ => true)
                    .AllowCredentials();
            });

            options.AddPolicy(name: MyAllowSpecificOrigins, policy  =>
            {
                policy.WithOrigins(builder.Configuration.GetSection("ActiveAllocator:AllowedHosts").Get<string[]>());
            });
        });

        // Authentication
        builder.Services.AddAuthentication()
        .AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme, null);

        // Authorization
        builder.Services.AddAuthorization(options => {
            AuthorizationPolicyBuilder defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
                ApiKeyAuthenticationOptions.DefaultScheme
            );

            defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
            options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
        });

        builder.Services.AddControllersWithViews().AddJsonOptions(x =>
        {
            // serialize enums as strings in api responses (e.g. Role)
            x.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());

            // ignore omitted parameters on models to enable optional params (e.g. User update)
            x.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
        });
        
        builder.Services.AddEndpointsApiExplorer();
        builder.Services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "AA API", Version = "v1" });
        });

        // Configure strongly typed settings object
        builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
        builder.Services.Configure<EnvelopeFundConfig>(builder.Configuration.GetSection("EnvelopeFund"));
        builder.Services.Configure<DatabaseConfig>(builder.Configuration.GetSection("ActiveAllocator:Database"));

        DatabaseConfig dbConfig = builder.Configuration.GetSection("ActiveAllocator:Database").Get<DatabaseConfig>();

        builder.Services.AddAutoMapper(typeof(Program));
        builder.Services.AddDbContext<DataContext>(opt =>
            opt.UseNpgsql(dbConfig.GetConnectionString()));

        builder.Services.AddScoped<IUserService, UserService>();
        builder.Services.AddScoped<IAccountService, AccountService>();
        builder.Services.AddScoped<ITransactionService, TransactionService>();
        builder.Services.AddScoped<ICacheService, CacheService>();
        builder.Services.AddScoped<IVersionService, VersionService>();

        builder.Services.AddScoped<ApiKeyAuthenticationHandler>();

        builder.Services.AddSingleton<IPuppeteerProcess, PuppeteerProcess>();

        builder.Services.AddHostedService<PuppeteerWorker>();

        var app = builder.Build();

        // Apply Database Migrations - This is NOT recommended for multi-node deployment!!!
        using var scope = app.Services.CreateScope();
        using var dbContext = scope.ServiceProvider.GetRequiredService<DataContext>();
        dbContext.Database.Migrate();

        // Configure the HTTP request pipeline.
        if (!app.Environment.IsDevelopment())
        {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseCors("ClientPermission");
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSwagger();
        app.UseSwaggerUI();
        app.UseRouting();
        app.UseCors(MyAllowSpecificOrigins);

        app.UseAuthentication();
        app.UseAuthorization();

        // global error handler
        app.UseMiddleware<ErrorHandlerMiddleware>();

        app.MapControllerRoute(
            name: "default",
            pattern: "{controller}/{action=Index}/{id?}");

        app.MapFallbackToFile("index.html");

        app.Run();
    }
}