using DotNetDDI.Data;
using DotNetDDI.Integrations.Kea;
using DotNetDDI.Integrations.PowerDns;
using DotNetDDI.Options;
using DotNetDDI.Services.Dhcp;
using DotNetDDI.Services.Dns;

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Connections;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSystemd();

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

bool adminAuthenticate = builder.Configuration.GetValue("Admin:Authentication", true);
if (adminAuthenticate)
{
	builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
		.AddEntityFrameworkStores<ApplicationDbContext>();
}

builder.Services.AddRazorPages();

builder.Services.Configure<DhcpOptions>(builder.Configuration.GetRequiredSection("Dhcp"));
builder.Services.Configure<PowerDnsOptions>(builder.Configuration.GetRequiredSection("PowerDns"));

builder.Services.AddHostedService<DhcpWatcher>();
builder.Services.AddHostedService<DhcpQueueWorker>();

builder.Services.AddSingleton<DhcpLeaseQueue>();
builder.Services.AddSingleton<DnsRepository>();

builder.Services.AddDhcpWatcherFactory();
builder.Services.AddKeaFactory();

builder.WebHost.ConfigureKestrel((context, options) =>
{
	options.UseSystemd(_ => throw new InvalidOperationException("SystemD Socket Activation is not supported by Kestrel."));

	var pdnsOptions = context.Configuration.GetRequiredSection("PowerDns:Listener").Get<PowerDnsListenerOptions>();
	ArgumentNullException.ThrowIfNull(pdnsOptions);
	var path = PathEx.ExpandPath(pdnsOptions.Socket);
	FileInfo file = new(path);
	file.Directory!.Create();
	file.Delete();
	options.ListenUnixSocket(path, options =>
	{
		options.UseConnectionHandler<PowerDnsHandler>();
	});
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
	app.UseMigrationsEndPoint();
}
else
{
	app.UseExceptionHandler("/Error");
}

app.UseRouting();

if (adminAuthenticate)
{
	app.UseAuthorization();
}

app.UseStaticFiles();
app.MapRazorPages();

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

	if (adminAuthenticate)
	{
		/* TODO: Generate Admin Account if None found */
	}
}

app.Run();
