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

namespace Hua.Todo.Maui;

/// <summary>
/// MAUI 程序启动类
/// </summary>
public static class MauiProgram
{
	/// <summary>
	/// 创建并配置 MAUI 应用程序
	/// </summary>
	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();
		
		// 如果未提供连接字符串，则设置默认的 SQLite 连接字符串
		if (string.IsNullOrEmpty(appSettings.WebServer.ConnectionString))
		{
			var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
			var dbDir = Path.Combine(localAppData, "Hua.Todo");
			if (!Directory.Exists(dbDir))
			{
				Directory.CreateDirectory(dbDir);
			}
			var dbPath = Path.Combine(dbDir, "Hua.Todo.db");
			appSettings.WebServer.ConnectionString = $"Data Source={dbPath};Cache=Shared";
		}
		
		builder.Services.AddSingleton(appSettings);
		var connectionString = appSettings.WebServer.ConnectionString;

		// 注册应用服务
		builder.Services.AddApplicationServices(connectionString);
		builder.Services.AddTransient<Views.MainPage>();

		// 注册热键设置服务
		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
		});

		// 注册嵌入式 Web 服务器（平台相关）
#if WINDOWS
        builder.Services.AddSingleton<IEmbeddedWebServerService, EmbeddedWebServerService>();
#elif ANDROID
        builder.Services.AddSingleton<IEmbeddedWebServerService, MobileEmbeddedWebServerService>();
#else
        builder.Services.AddSingleton<IEmbeddedWebServerService, NoopEmbeddedWebServerService>();
#endif

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

		var app = builder.Build();

		// 异步初始化数据库和 Web 服务器
		_ = Task.Run(async () =>
		{
			try
			{
				InitializeDatabase(app.Services, connectionString);
				await StartWebServer(app.Services);
			}
			catch (Exception ex)
			{
				System.Diagnostics.Debug.WriteLine($"App initialization failed: {ex}");
			}
		});

		return app;
	}

	/// <summary>
	/// 从 appsettings.json 加载配置
	/// </summary>
	private static AppSettings LoadAppSettings()
	{
		try
		{
			using var stream = FileSystem.OpenAppPackageFileAsync("appsettings.json").GetAwaiter().GetResult();
			using var reader = new StreamReader(stream);
			var json = reader.ReadToEnd();
			return JsonSerializer.Deserialize<AppSettings>(json) ?? new AppSettings();
		}
		catch
		{
			try
			{
				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();
			}
			catch
			{
				return new AppSettings();
			}
		}
	}

	/// <summary>
	/// 初始化数据库（执行迁移）
	/// </summary>
	private static void InitializeDatabase(IServiceProvider services, string connectionString)
	{
		using var scope = services.CreateScope();

		try
		{
			var dbContext = scope.ServiceProvider.GetRequiredService<TodoDbContext>();

			var sqliteBuilder = new SqliteConnectionStringBuilder(connectionString);
			var actualDbPath = sqliteBuilder.DataSource;
			if (!string.IsNullOrEmpty(actualDbPath))
			{
				var dbDir = Path.GetDirectoryName(actualDbPath);
				if (!string.IsNullOrEmpty(dbDir) && !Directory.Exists(dbDir))
				{
					Directory.CreateDirectory(dbDir);
				}
			}

			// 确保使用 WAL 模式以避免锁定问题
			dbContext.Database.ExecuteSqlRaw("PRAGMA journal_mode=WAL;");
			dbContext.Database.Migrate();
		}
		catch (Exception ex)
		{
			System.Diagnostics.Debug.WriteLine($"Database initialization failed: {ex.Message}");

			try
			{
				var context = scope.ServiceProvider.GetRequiredService<TodoDbContext>();
				context.Database.EnsureCreated();
			}
			catch
			{
			}
		}
	}

	/// <summary>
	/// 启动嵌入式 Web 服务器
	/// </summary>
	private static async Task StartWebServer(IServiceProvider services)
	{
		try
		{
			var webServer = services.GetRequiredService<IEmbeddedWebServerService>();
			await webServer.StartAsync();
		}
		catch (Exception ex)
		{
			System.Diagnostics.Debug.WriteLine($"Web server start failed: {ex}");
		}
	}
}
