using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Data.Sqlite;
using TodoList.Application;
using TodoList.Application.Data;
using TodoList.Maui.Models;
using TodoList.Maui.Services;
using TodoList.Maui.Services.Platforms;

namespace TodoList.Maui;

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			.ConfigureFonts(fonts =>
			{
				fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
				fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
			});

		var appSettings = LoadAppSettings();
		
		// Set default connection string if not provided
		if (string.IsNullOrEmpty(appSettings.WebServer.ConnectionString))
		{
			var dbPath = Path.Combine(FileSystem.AppDataDirectory, "todolist.db");
			appSettings.WebServer.ConnectionString = $"Data Source={dbPath}";
		}
		
		builder.Services.AddSingleton(appSettings);
		var connectionString = appSettings.WebServer.ConnectionString;

		builder.Services.AddApplicationServices(connectionString);

		builder.Services.AddSingleton<IHotKeySettingsService>(sp =>
			new HotKeySettingsService(sp.GetRequiredService<AppSettings>()));
		builder.Services.AddSingleton<IGlobalHotKeyService>(sp => GlobalHotKeyServiceFactory.Create());
		builder.Services.AddSingleton<ISystemTrayService>(sp =>
		{
#if WINDOWS
			return new WindowsSystemTrayService();
#else
			return new NullSystemTrayService();
#endif
		});
        builder.Services.AddSingleton<IEmbeddedWebServerService, EmbeddedWebServerService>();

#if DEBUG
        builder.Logging.AddDebug();
#endif

		var app = builder.Build();
		
		// Ensure database directory exists and apply migrations
		using (var scope = app.Services.CreateScope())
		{
			try
			{
				var dbContext = scope.ServiceProvider.GetRequiredService<TodoDbContext>();
				
				// Ensure database directory exists for the actual connection string
				var sqliteBuilder = new SqliteConnectionStringBuilder(connectionString);
				var actualDbPath = sqliteBuilder.DataSource;
				if (!string.IsNullOrEmpty(actualDbPath))
				{
					// If it's a relative path, we might need to resolve it, 
					// but for SQLite, it's usually better to have absolute paths.
					// For MAUI, FileSystem.AppDataDirectory returns an absolute path.
					var dbDir = Path.GetDirectoryName(actualDbPath);
					if (!string.IsNullOrEmpty(dbDir) && !Directory.Exists(dbDir))
					{
						Directory.CreateDirectory(dbDir);
					}
				}
				
				// Ensure database is up to date
				dbContext.Database.Migrate();
			}
			catch (Exception ex)
			{
				System.Diagnostics.Debug.WriteLine($"Database initialization failed: {ex.Message}");
				// Fallback to EnsureCreated if Migrate fails (though Migrate is preferred)
				using var context = scope.ServiceProvider.GetRequiredService<TodoDbContext>();
				context.Database.EnsureCreated();
			}
		}
		
		var webServer = app.Services.GetRequiredService<IEmbeddedWebServerService>();
		_ = webServer.StartAsync();

		return app;
	}

	private static AppSettings LoadAppSettings()
	{
		var settingsPath = Path.Combine(AppContext.BaseDirectory, "appsettings.json");
		if (!File.Exists(settingsPath))
		{
			return new AppSettings();
		}

		var json = File.ReadAllText(settingsPath);
		return JsonSerializer.Deserialize<AppSettings>(json) ?? new AppSettings();
	}
}
