using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using AvaloniaWebView;
using Hua.Todo.Avalonia.Models;
using Hua.Todo.Avalonia.Services;
using Hua.Todo.Avalonia.Services.Platforms;
using Hua.Todo.Avalonia.ViewModels;
using Hua.Todo.Avalonia.Views;
using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;

namespace Hua.Todo.Avalonia;

/// <summary>
/// Avalonia 应用入口。
/// 负责启动嵌入式 WebServer、创建主窗口并初始化 WebView 能力。
/// </summary>
public partial class App : global::Avalonia.Application
{
    private AppSettings? _appSettings;
    private IEmbeddedWebServerService? _webServer;
    private IHotKeySettingsService? _hotKeySettingsService;
    private IGlobalHotKeyService? _hotKeyService;
    private HotKeyConfig? _hotKeyConfig;
    private WindowsKeyboardHandler? _keyboardHandler;
    private MainWindow? _mainWindow;
    private bool _isExitRequested;
    private bool _isHotkeyRegistered;

    /// <summary>
    /// 初始化应用资源并加载配置。
    /// </summary>
    public override void Initialize()
    {
        AvaloniaXamlLoader.Load(this);
        LoadSettings();
    }

    /// <summary>
    /// 注册应用级服务。
    /// </summary>
    public override void RegisterServices()
    {
        base.RegisterServices();
        AvaloniaWebViewBuilder.Initialize(default);
    }

    private void LoadSettings()
    {
        try
        {
            var settingsPath = Path.Combine(AppContext.BaseDirectory, "appsettings.json");
            if (File.Exists(settingsPath))
            {
                var json = File.ReadAllText(settingsPath);
                _appSettings = JsonSerializer.Deserialize<AppSettings>(json);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"[App] Failed to load settings: {ex.Message}");
        }

        _appSettings ??= new AppSettings();

        EnsureDefaultConnectionString(_appSettings);
    }

    private static void EnsureDefaultConnectionString(AppSettings appSettings)
    {
        if (string.IsNullOrWhiteSpace(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";
        }
    }

    /// <summary>
    /// Avalonia 框架初始化完成回调。
    /// 启动嵌入式 WebServer（后台启动并捕获异常，避免阻塞/崩溃），并创建主窗口。
    /// </summary>
    public override void OnFrameworkInitializationCompleted()
    {
        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            DisableAvaloniaDataAnnotationValidation();

            _webServer = new EmbeddedWebServerService(_appSettings!);
            _ = Task.Run(async () =>
            {
                try
                {
                    await _webServer.StartAsync();
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[App] Web server start failed: {ex}");
                }
            });

            _hotKeySettingsService = new HotKeySettingsService(_appSettings!);
            _hotKeyConfig = _hotKeySettingsService.GetConfig();
            _hotKeyService = GlobalHotKeyServiceFactory.Create();

            if (OperatingSystem.IsWindows())
            {
                _keyboardHandler = new WindowsKeyboardHandler();
                _keyboardHandler.EscKeyPressed += (_, _) =>
                {
                    Dispatcher.UIThread.Post(() =>
                    {
                        if (_mainWindow is { IsVisible: true })
                        {
                            _mainWindow.WindowState = WindowState.Minimized;
                        }
                    });
                };
            }

            DataContext = new AppTrayViewModel(
                AppMetadata.GetTrayTooltipText(),
                ShowMainWindow,
                () => ExitApplication(desktop));

            _mainWindow = new MainWindow(_appSettings!, _webServer)
            {
                Width = 450,
                Height = 640,
                Title = AppMetadata.GetWindowTitle(),
            };

            _mainWindow.Opened += (_, _) =>
            {
                RegisterHotkey();
                _keyboardHandler?.Start();
            };

            _mainWindow.Closing += (_, e) =>
            {
                if (_isExitRequested)
                {
                    return;
                }

                e.Cancel = true;
                _mainWindow.Hide();
            };

            desktop.MainWindow = _mainWindow;

            desktop.Exit += async (s, e) =>
            {
                _keyboardHandler?.Dispose();
                _keyboardHandler = null;

                if (_isHotkeyRegistered)
                {
                    _hotKeyService?.UnregisterHotKey();
                    _isHotkeyRegistered = false;
                }

                if (_hotKeyService is IDisposable disposableHotKeyService)
                {
                    disposableHotKeyService.Dispose();
                }

                if (_webServer != null)
                {
                    await _webServer.StopAsync();
                }
            };
        }

        base.OnFrameworkInitializationCompleted();
    }

    private void ExitApplication(IClassicDesktopStyleApplicationLifetime desktop)
    {
        _isExitRequested = true;
        desktop.Shutdown();
    }

    private void ShowMainWindow()
    {
        if (_mainWindow == null) return;

        if (!_mainWindow.IsVisible)
        {
            _mainWindow.Show();
        }

        if (_mainWindow.WindowState == WindowState.Minimized)
        {
            _mainWindow.WindowState = WindowState.Normal;
        }

        _mainWindow.Activate();
    }

    private void RegisterHotkey()
    {
        if (_hotKeyService == null || _hotKeySettingsService == null) return;

        var config = _hotKeyConfig ?? _hotKeySettingsService.GetConfig();
        _hotKeyConfig = config;

        if (_hotKeyService.IsSupported && config.IsEnabled)
        {
            _hotKeyService.RegisterHotKey(config.Modifiers, config.Key, () =>
            {
                Dispatcher.UIThread.Post(ShowMainWindow);
            });
            _isHotkeyRegistered = true;
        }

        config.PropertyChanged -= OnHotKeyConfigPropertyChanged;
        config.PropertyChanged += OnHotKeyConfigPropertyChanged;
    }

    private void OnHotKeyConfigPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (_hotKeyService == null || _hotKeySettingsService == null || _hotKeyConfig == null) return;

        if (e.PropertyName != nameof(HotKeyConfig.Modifiers) &&
            e.PropertyName != nameof(HotKeyConfig.Key) &&
            e.PropertyName != nameof(HotKeyConfig.IsEnabled))
        {
            return;
        }

        _hotKeySettingsService.SaveConfig(_hotKeyConfig);

        if (_hotKeyConfig.IsEnabled && _hotKeyService.IsSupported)
        {
            _hotKeyService.UpdateHotKey(_hotKeyConfig.Modifiers, _hotKeyConfig.Key);
            _isHotkeyRegistered = true;
        }
        else
        {
            _hotKeyService.UnregisterHotKey();
            _isHotkeyRegistered = false;
        }
    }

    private void DisableAvaloniaDataAnnotationValidation()
    {
        var dataValidationPluginsToRemove =
            BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();

        foreach (var plugin in dataValidationPluginsToRemove)
        {
            BindingPlugins.DataValidators.Remove(plugin);
        }
    }
}
