using Backend.Controllers;
using Backend.Database;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;


using (var db = Db.Connect())
{
    db.CreateFakeRelations();
}



var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();  // TODO: remove magic, specify controllers explicitly
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle

builder.Services.AddHttpContextAccessor(); 
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*"))); // TODO
builder.Services.AddSwaggerGen(config =>
{
    config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" });
    config.OperationFilter<MyHeaderFilter>();   //Todo testing throw me out
});



var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(cfg => cfg.EnableFilter());
}

app.UseCors();
app.UseHttpsRedirection();
app.UseAuthorization();
app.Use(SetSessionUser);
app.MapControllers();

app.Run();






//================= Functions for above ===================

//Setting User for current Session
async Task SetSessionUser(HttpContext ctx, RequestDelegate next)
{
    var headers = ctx.Request.Headers;
    var hasToken = headers.TryGetValue("auth", out var token);
    
    if (!ctx.Request.Path.ToString().Contains(nameof(Controller.Login)))
    {
        if (!hasToken)
        {
            ctx.Response.StatusCode = 403;
            return;
        }
        
        using var db = Db.Connect();
        var user = db.GetUserByToken(token.ToString());

        if (user is null)
        {
            ctx.Response.StatusCode = 403;
            return;                
        }
        
        ctx.Items["User"] = user;    
    }
    
    await next(ctx);
}




/// <summary>
/// This is for convenient testing! Todo throw me out?
/// Operation filter to add the requirement of the custom header
/// </summary>
public class MyHeaderFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        operation.Parameters ??= new List<OpenApiParameter>();

        operation.Parameters.Add(new OpenApiParameter
        {
            Name = "auth",
            In =  ParameterLocation.Header,
            Content = new Dictionary<String, OpenApiMediaType>(),
            Required = false
        });
    }
}