using Microsoft.EntityFrameworkCore;

using Aberwyn.Data;
using System.Text;
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Aberwyn.Models;
using Microsoft.AspNetCore.Identity;
using System.Text.Json;
using Aberwyn.Services;

var config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: true)
    .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
    .AddEnvironmentVariables()
    .Build();

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    EnvironmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"
});
builder.Configuration.AddConfiguration(config);


// Läser setup.json eller skapar en ny tom om den inte finns
var dataRoot = Path.Combine(Directory.GetCurrentDirectory(), "data");
var setupFilePath = Path.Combine(dataRoot, "infrastructure", "setup.json");

if (!File.Exists(setupFilePath))
{
    var initialSettings = new SetupSettings
    {
        IsConfigured = false,
        DbPort = 3306
    };

    var initialJson = JsonSerializer.Serialize(initialSettings, new JsonSerializerOptions { WriteIndented = true });
    Directory.CreateDirectory(Path.GetDirectoryName(setupFilePath)!); // säkerställ att mappen finns
    File.WriteAllText(setupFilePath, initialJson);
}

SetupSettings setup;
try
{
    using var jsonStream = File.OpenRead(setupFilePath);
    setup = JsonSerializer.Deserialize<SetupSettings>(jsonStream)!;

    if (setup.IsConfigured)
    {
        if (string.IsNullOrWhiteSpace(setup.DbHost) ||
            string.IsNullOrWhiteSpace(setup.DbName) ||
            string.IsNullOrWhiteSpace(setup.DbUser) ||
            string.IsNullOrWhiteSpace(setup.DbPassword))
        {
            throw new Exception("Databasinställningarna är ofullständiga.");
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Fel vid läsning av setup.json: {ex.Message}");
    setup = new SetupSettings { IsConfigured = false };
}


builder.Services.AddHttpClient<ITorrentService, TorrentService>();
builder.Services.AddScoped<ITorrentService, TorrentService>();
builder.Services.AddHttpClient<RssProcessor>();
builder.Services.AddScoped<IRssProcessor, RssProcessor>();
builder.Services.AddHostedService<TorrentRssService>();

builder.Services.AddHttpClient<HdTorrentsTrackerScraper>();
builder.Services.AddScoped<HdTorrentsTrackerScraper>();
builder.Services.AddHttpClient<DelugeClient>();
builder.Services.AddHttpClient<MovieMetadataService>();
builder.Services.AddScoped<ITorrentService, TorrentService>();
builder.Services.AddHttpClient<ITorrentService, TorrentService>();
builder.Services.AddScoped<TorrentService>();

// Add services to the container
builder.Services.AddControllersWithViews()
    .AddJsonOptions(opts =>
    {
        opts.JsonSerializerOptions.PropertyNamingPolicy = null;
        opts.JsonSerializerOptions.IgnoreNullValues = true;
    });

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromDays(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

builder.Services.AddRazorPages();
builder.Services.AddHttpClient();

// Registrera rätt databas och identity beroende på om setup är klar
if (setup.IsConfigured)
{

    var csBuilder = new MySqlConnector.MySqlConnectionStringBuilder
    {
        Server = setup.DbHost,
        Port = (uint)setup.DbPort,
        Database = setup.DbName,
        UserID = setup.DbUser,
        Password = setup.DbPassword,
        AllowUserVariables = true // valfritt – ta bort om du inte använder det
    };

    var connectionString = csBuilder.ConnectionString;

    builder.Services.AddDbContext<ApplicationDbContext>(options =>
        options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));

    builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
    {
        options.SignIn.RequireConfirmedAccount = false;
    })
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();
}
else
{
    builder.Services.AddDbContext<ApplicationDbContext>(options =>
        options.UseInMemoryDatabase("TempSetup"));

    builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();
}

// Identity inställningar
builder.Services.Configure<IdentityOptions>(options =>
{
    options.Password.RequireDigit = false;
    options.Password.RequiredLength = 6;
    options.Password.RequireLowercase = false;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireUppercase = false;
});

// Appens övriga tjänster
builder.Services.AddScoped<MenuService>();

builder.Services.AddScoped<PushNotificationService>(sp =>
{
    var config = sp.GetRequiredService<IConfiguration>();
    return new PushNotificationService(
        config["VapidKeys:Subject"],
        config["VapidKeys:PublicKey"],
        config["VapidKeys:PrivateKey"]
    );
});

builder.Services.AddScoped<PizzaNotificationService>();

builder.Services.Configure<VapidOptions>(builder.Configuration.GetSection("Vapid"));

builder.Services.ConfigureApplicationCookie(options =>
{
    options.LoginPath = "/Identity/Account/Login";
    options.ExpireTimeSpan = TimeSpan.FromDays(30);
    options.SlidingExpiration = true;
    options.Cookie.IsEssential = true;
});

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[] { new CultureInfo("sv-SE") };
    options.DefaultRequestCulture = new RequestCulture("sv-SE");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
});
builder.Services.AddSingleton<SetupService>();
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddDebug();


builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll", policy =>
    {
        policy.AllowAnyOrigin()   // Tillåt alla domäner
              .AllowAnyHeader()   // Tillåt alla headers
              .AllowAnyMethod();  // Tillåt GET, POST, etc.
    });
});


// Eller om du vill ha mer detaljerad loggning:
builder.Logging.SetMinimumLevel(LogLevel.Information);
var app = builder.Build();

app.UseStaticFiles();
// Middleware: om ej konfigurerad → redirect till /setup
app.Use(async (context, next) =>
{
    var setupService = context.RequestServices.GetRequiredService<SetupService>();
    var currentSetup = setupService.GetSetup();

    var path = context.Request.Path;
    var method = context.Request.Method;

    if (!currentSetup.IsConfigured &&
        !path.StartsWithSegments("/setup") &&
        !(path == "/setup" && method == "POST") && // 👈 tillåt POST till /setup
        !path.StartsWithSegments("/api/setup"))
    {
        context.Response.Redirect("/setup");
        return;
    }

    await next();
});



app.UseRouting();
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("AllowAll");
// Routing
app.MapControllers();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

    app.UseExceptionHandler("/Error");
    app.UseStatusCodePagesWithReExecute("/Error/{0}");
    app.UseHsts();


// Init: migrera databas och skapa admin
if (setup.IsConfigured)
{
    using var scope = app.Services.CreateScope();
    var services = scope.ServiceProvider;

    var context = services.GetRequiredService<ApplicationDbContext>();

    int retries = 10;
    while (retries > 0)
    {
        try
        {
            context.Database.OpenConnection();
            context.Database.CloseConnection();
            break;
        }
        catch
        {
            retries--;
            Console.WriteLine("⏳ Väntar på databas...");
            Thread.Sleep(3000);
        }
    }

    context.Database.Migrate();

    var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
    var anyUsers = await userManager.Users.AnyAsync();

    if (!anyUsers)
    {
        Console.WriteLine("🧩 Ingen användare hittades – skapar admin...");
        await IdentityDataInitializer.SeedData(services, setup);
    }
}
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage(); // Detta ger stacktraces i browsern
}

app.Run();
