using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;

using Serilog;

using Watcher.Data;
using Watcher.Models;
using Watcher.Services;


var builder = WebApplication.CreateBuilder(args);


// Serilog konfigurieren – nur Logs, die nicht von Microsoft stammen
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .WriteTo.File(
        "logs/watcher-.log",
        outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}",
        rollingInterval: RollingInterval.Day
    )
    .CreateLogger();

builder.Host.UseSerilog();


// Add services to the container.
builder.Services.AddControllersWithViews();

// Health Checks
builder.Services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>("database");

// HttpContentAccessor
builder.Services.AddHttpContextAccessor();

// Storage Singleton
builder.Services.AddSingleton<IDashboardStore, DashboardStore>();
builder.Services.AddSingleton<IVersionService, VersionService>();
builder.Services.AddSingleton<IUpdateCheckStore, UpdateCheckStore>();

// SystemStore mit Konfiguration initialisieren
builder.Services.AddSingleton<ISystemStore>(sp =>
{
    var configuration = sp.GetRequiredService<IConfiguration>();
    var refreshIntervalSeconds = int.TryParse(
        configuration["Frontend:RefreshIntervalSeconds"]
        ?? Environment.GetEnvironmentVariable("FRONTEND_REFRESH_INTERVAL_SECONDS"),
        out var seconds) ? seconds : 30;

    return new SystemStore
    {
        FrontendRefreshIntervalMilliseconds = refreshIntervalSeconds * 1000
    };
});

// Background Services
builder.Services.AddHostedService<NetworkCheck>();
builder.Services.AddHostedService<DatabaseCheck>();
builder.Services.AddHostedService<MetricCleanupService>();
builder.Services.AddHostedService<UpdateCheckService>();

// Swagger API-Dokumentation
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "Watcher-Server API", Version = "v1" });
});

// ---------- Konfiguration ----------
DotNetEnv.Env.Load();

builder.Configuration
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables();


// Konfiguration laden
var configuration = builder.Configuration;


// ---------- DB-Kontext ----------
// Nur SQLite wird unterstützt
var sqliteConnectionString = configuration.GetConnectionString("Sqlite")
    ?? configuration["Database:ConnectionStrings:Sqlite"]
    ?? "Data Source=./persistence/watcher.db";

builder.Services.AddDbContext<AppDbContext>((serviceProvider, options) =>
{
    options.UseSqlite(sqliteConnectionString);
});


// ---------- Authentifizierung konfigurieren ----------
// Nur Cookie-basierte lokale Authentifizierung
builder.Services.AddAuthentication("Cookies")
    .AddCookie("Cookies", options =>
    {
        options.LoginPath = "/Auth/Login";
        options.AccessDeniedPath = "/Auth/AccessDenied";
    });


var app = builder.Build();


// Migrationen anwenden (für SQLite oder andere DBs)
using (var scope = app.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
    db.Database.Migrate();
}


// Standard-Admin-User erstellen
using (var scope = app.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();

    Console.WriteLine("Checking for users...");

    if (!db.Users.Any())
    {
        Console.WriteLine("No users found, creating default admin user...");

        var defaultUser = new User
        {
            Username = "admin",
            Email = "admin@localhost",
            LastLogin = DateTime.UtcNow,
            Password = BCrypt.Net.BCrypt.HashPassword("changeme")
        };
        db.Users.Add(defaultUser);
        db.SaveChanges();

        Console.WriteLine("Default admin user created (username: admin, password: changeme)");
    }
    else
    {
        Console.WriteLine("Users already exist.");
    }
}


// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

// 🔹 Swagger aktivieren
app.UseSwagger();
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "Watcher-Server API v1");
    options.RoutePrefix = "api/v1/swagger";
});

// 🔹 Health Check Endpoint
app.MapHealthChecks("/health");

// 🔹 Authentifizierung & Autorisierung
app.UseAuthentication();
app.UseAuthorization();

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

app.Run();
