using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using CouchLog.Components;
using CouchLog.Components.Account;
using CouchLog.Data;
using CouchLog;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<IdentityUserAccessor>();
builder.Services.AddScoped<IdentityRedirectManager>();
builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();

builder.Services.AddAuthentication(options =>
    {
        options.DefaultScheme = IdentityConstants.ApplicationScheme;
        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
    })
    .AddIdentityCookies();

var connectionString = builder.Configuration.GetConnectionString("CouchLogDB") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager()
    .AddDefaultTokenProviders();

builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    app.UseHsts();
}

app.UseHttpsRedirection();


app.UseAntiforgery();

app.MapStaticAssets();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.MapAdditionalIdentityEndpoints();

using (var scope = app.Services.CreateScope())
{
    var CouchLogDB = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
    CouchLogDB.Database.Migrate();

    var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
    var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();

    string[] roleNames = { "Admin", "User" };
    IdentityResult roleResult;

    foreach (var roleName in roleNames)
    {
        var roleExist = await roleManager.RoleExistsAsync(roleName);
        if (!roleExist)
        {
            roleResult = await roleManager.CreateAsync(new IdentityRole(roleName));
        }
    }

    var adminUsername = "Admin";
    var normalUsername = "User";
    var adminPassword = "EinSehrSicheresPasswort123!";

    var adminUser = await userManager.FindByNameAsync(adminUsername);
    var normalUser = await userManager.FindByNameAsync(normalUsername);

    if (adminUser == null)
    {
        adminUser = new ApplicationUser
        {
            UserName = adminUsername,
            EmailConfirmed = true
        };
        var createResult = await userManager.CreateAsync(adminUser, adminPassword);

        if (createResult.Succeeded)
        {
            await userManager.AddToRoleAsync(adminUser, "Admin");
        }
    }
    else if (normalUser == null)
    {
        normalUser = new ApplicationUser
        {
            UserName = normalUsername,
            EmailConfirmed = true
        };
        var createResult = await userManager.CreateAsync(normalUser, adminPassword);

        if (createResult.Succeeded)
        {
            await userManager.AddToRoleAsync(adminUser, "User");
        }
    }
    else if (!await userManager.IsInRoleAsync(normalUser, "User"))
    {
        await userManager.AddToRoleAsync(normalUser, "User");
    }
    else if (!await userManager.IsInRoleAsync(adminUser, "Admin"))
    {
        await userManager.AddToRoleAsync(adminUser, "Admin");
    }

    MediaType mediaType = new()
    {
        Name = "Movie"
    };

    if (!CouchLogDB.MediaType.Any())
        CouchLogDB.MediaType.Add(mediaType);

    await CouchLogDB.SaveChangesAsync();

    GlobalEntity globalEntity = new()
    {
        Title = "Inception",
        CreationTime = DateTime.Now,
        CreatorId = (await userManager.FindByNameAsync("Admin"))!.Id,
        TypeId = 1,
        PicturePath = "Pictures/Inception.jpg"
    };

    if (!CouchLogDB.GlobalEntities.Any())
        CouchLogDB.GlobalEntities.Add(globalEntity);

    await CouchLogDB.SaveChangesAsync();

    OnStartUp onStartUp = new(CouchLogDB);
    onStartUp.AddBasicDatabaseEntries();
}

app.Run();