using System;
using System.Threading;
using System.Windows;
using System.Windows.Interop;
using Microsoft.Win32;
using TodoList.Services;
using TodoList.ViewModels;
using TodoList.Views;
using System.Linq;
using System.Reflection;

namespace TodoList
{
    public partial class App : System.Windows.Application
    {
        private const string MainWindowTitle = "待办事项";
        private IDataService _dataService;
        private GlobalShortcutService _shortcutService;
        private MainWindow _mainWindow;
        private QuickEntryWindow? _quickEntryWindow;
        private SettingsService _settingsService;
        private NotifyIcon _notifyIcon;
        private Mutex _mutex;
        private EventWaitHandle _eventWaitHandle;
        private const string UniqueEventName = "Global\\TodoListApp_Event_v1";

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        public App()
        {
            // Disable hardware acceleration to prevent black screen issues
            // Must be set before any UI is created
            System.Windows.Media.RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            // Ensure app doesn't shutdown when main window closes (we hide it)
            this.ShutdownMode = ShutdownMode.OnExplicitShutdown;

            const string appName = "Global\\TodoListApp_Unique_Mutex_v1";
            bool createdNew;
            _mutex = new Mutex(true, appName, out createdNew);
            
            if (!createdNew)
            {
                // Signal the existing instance
                try 
                {
                    using (var evt = EventWaitHandle.OpenExisting(UniqueEventName))
                    {
                        evt.Set();
                    }
                }
                catch 
                {
                    // Fallback to old method if event open fails
                    var hWnd = FindWindow(null, MainWindowTitle);
                    if (hWnd != IntPtr.Zero)
                    {
                        ShowWindow(hWnd, 9); // SW_RESTORE
                        SetForegroundWindow(hWnd);
                    }
                }
                
                // Force exit to prevent second instance from running
                Environment.Exit(0);
                return;
            }
            
            // Create the event handle for this instance
            _eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, UniqueEventName);
            
            // Start a thread to listen for signals
            Thread thread = new Thread(() =>
            {
                while (true)
                {
                    _eventWaitHandle.WaitOne();
                    this.Dispatcher.Invoke(() => ShowMainWindow());
                }
            });
            thread.IsBackground = true;
            thread.Start();

            base.OnStartup(e);

            // Configure Auto Start
            ConfigureAutoStart();
            
            // Create Desktop/StartMenu Shortcut if needed (optional feature)
            // CreateShortcut();

            this.DispatcherUnhandledException += App_DispatcherUnhandledException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            try 
            {
                _settingsService = new SettingsService();
                _dataService = new SqliteDataService();
                _shortcutService = new GlobalShortcutService();

                var mainViewModel = new MainViewModel(_dataService, _settingsService);
                
                _mainWindow = new MainWindow(mainViewModel);
                _mainWindow.Title = MainWindowTitle;
                _mainWindow.Loaded += MainWindow_Loaded;
                
                // Initialize Tray Icon
                InitializeTrayIcon();

                // Check for silent mode
                bool silent = e.Args.Contains("--silent") || e.Args.Contains("-s");
                
                if (!silent)
                {
                    _mainWindow.Show();
                }
            }
            catch (Exception ex)
            {
                Log("Startup Error: " + ex.ToString());
                System.Windows.MessageBox.Show("Startup Error: " + ex.Message);
            }
        }

        private void ConfigureAutoStart()
        {
            try
            {
                var exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName;
                string cmd = $"\"{exePath}\" --silent";

                // If running as dotnet tool, try to find the shim or stable entry point
                // Usually %USERPROFILE%\.dotnet\tools\todo.exe
                var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                var toolShim = System.IO.Path.Combine(userProfile, ".dotnet", "tools", "todo.exe");
                
                if (System.IO.File.Exists(toolShim))
                {
                     // If the shim exists and we are likely running it (or just installed it), prefer the shim
                     // This handles updates better as the shim path stays constant.
                     // But we should verify if the current process IS related to it? 
                     // Actually, if installed as tool, we definitely want to use the shim.
                     cmd = $"\"{toolShim}\" --silent";
                }

                var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
                if (key != null)
                {
                    var existing = key.GetValue("TodoListApp");
                    if (existing == null || existing.ToString() != cmd)
                    {
                        key.SetValue("TodoListApp", cmd);
                    }
                    key.Close();
                }
            }
            catch (Exception ex)
            {
                Log("AutoStart Error: " + ex.Message);
            }
        }

        private void InitializeTrayIcon()
        {
            _notifyIcon = new NotifyIcon();
            
            // Try load icon from resource or file
            try 
            {
                // Load from embedded resource
                var resourceUri = new Uri("pack://application:,,,/icon.ico");
                var streamInfo = System.Windows.Application.GetResourceStream(resourceUri);
                
                if (streamInfo != null)
                {
                    using (var stream = streamInfo.Stream)
                    {
                        _notifyIcon.Icon = new System.Drawing.Icon(stream);
                    }
                }
                else
                {
                    _notifyIcon.Icon = System.Drawing.SystemIcons.Application; 
                }
            }
            catch
            {
                _notifyIcon.Icon = System.Drawing.SystemIcons.Application;
            }

            _notifyIcon.Visible = true;
            _notifyIcon.Text = GetNotifyIconText();
            _notifyIcon.DoubleClick += (s, e) => ShowMainWindow();

            var contextMenu = new ContextMenuStrip();
            contextMenu.Items.Add("打开主界面", null, (s, e) => ShowMainWindow());
            contextMenu.Items.Add("退出", null, (s, e) => ExitApplication());
            _notifyIcon.ContextMenuStrip = contextMenu;
        }

        private static string GetNotifyIconText()
        {
            var version = GetDisplayVersion();
            var text = string.IsNullOrWhiteSpace(version) ? MainWindowTitle : $"{MainWindowTitle} v{version}";

            return text.Length > 63 ? text[..63] : text;
        }

        private static string? GetDisplayVersion()
        {
            var asm = Assembly.GetExecutingAssembly();

            var info = asm.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion?.Trim();
            if (!string.IsNullOrWhiteSpace(info))
            {
                var plus = info.IndexOf('+');
                return plus >= 0 ? info[..plus] : info;
            }

            var file = asm.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version?.Trim();
            if (!string.IsNullOrWhiteSpace(file))
            {
                return file;
            }

            return asm.GetName().Version?.ToString();
        }

        private void ShowMainWindow()
        {
            Log("ShowMainWindow called");
            if (_mainWindow != null)
            {
                if (_mainWindow.WindowState == WindowState.Minimized)
                {
                    _mainWindow.WindowState = WindowState.Normal;
                }
                _mainWindow.Show();
                _mainWindow.Activate();

                // Force foreground
                var helper = new WindowInteropHelper(_mainWindow);
                var handle = helper.Handle;
                if (handle != IntPtr.Zero)
                {
                    SetForegroundWindow(handle);
                }
            }
        }

        private void ExitApplication()
        {
            _notifyIcon?.Dispose();
            _notifyIcon = null;
            Shutdown();
        }

        private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            Log("Dispatcher Error: " + e.Exception.ToString());
            System.Windows.MessageBox.Show("Dispatcher Error: " + e.Exception.Message);
            e.Handled = true;
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Log("Domain Error: " + e.ExceptionObject.ToString());
            System.Windows.MessageBox.Show("Critical Error: " + e.ExceptionObject.ToString());
        }

        private void Log(string message)
        {
            try
            {
                System.IO.File.AppendAllText("error.log", DateTime.Now + ": " + message + Environment.NewLine);
            }
            catch { }
        }

        private bool _isHotkeyRegistered;

        private void RegisterHotkey()
        {
            if (_isHotkeyRegistered || _shortcutService == null || _settingsService == null) return;
            
            var helper = new WindowInteropHelper(_mainWindow);
            var handle = helper.Handle;
            
            if (handle != IntPtr.Zero)
            {
                var settings = _settingsService.Settings;
                var mods = GlobalShortcutService.GetModifier(settings.ShortcutModifiers);
                var key = GlobalShortcutService.GetKey(settings.ShortcutKey);
                
                _shortcutService.Register(handle, OnHotKeyPressed, mods, key);
                _isHotkeyRegistered = true;
                
                // Subscribe to settings changes to update hotkey
                _settingsService.Settings.PropertyChanged += (s, args) =>
                {
                    if (args.PropertyName == nameof(AppSettings.ShortcutModifiers) || 
                        args.PropertyName == nameof(AppSettings.ShortcutKey))
                    {
                         var newMods = GlobalShortcutService.GetModifier(_settingsService.Settings.ShortcutModifiers);
                         var newKey = GlobalShortcutService.GetKey(_settingsService.Settings.ShortcutKey);
                         _shortcutService.UpdateShortcut(newMods, newKey);
                    }
                };
            }
        }

        private void OnHotKeyPressed()
        {
            Log("Hotkey pressed.");
            ShowQuickEntryWindow();
        }

        private void ShowQuickEntryWindow()
        {
            if (_quickEntryWindow == null)
            {
                _quickEntryWindow = new QuickEntryWindow(_dataService);
                _quickEntryWindow.Title = "新建待办";
            }

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

            _quickEntryWindow.Show();
            _quickEntryWindow.Activate();

            var helper = new WindowInteropHelper(_quickEntryWindow);
            var handle = helper.Handle;
            if (handle != IntPtr.Zero)
            {
                SetForegroundWindow(handle);
            }
        }

        protected override void OnExit(ExitEventArgs e)
        {
            _notifyIcon?.Dispose();
            _shortcutService?.Dispose();
            base.OnExit(e);
        }

        // We can hook into MainWindow's Loaded event to register hotkey
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            RegisterHotkey();
        }
    }
}
