#if WINDOWS
using System.Runtime.InteropServices;
using WinRT.Interop;
using MauiWindow = Microsoft.Maui.Controls.Window;

namespace Hua.Todo.Maui.Services.Platforms
{
    /// <summary>
    /// Windows 平台全局热键服务实现类
    /// 使用 Windows API 实现全局热键功能
    /// </summary>
    public class WindowsGlobalHotKeyService : IGlobalHotKeyService
    {
        private const int HOTKEY_ID = 9000;
        private const int WM_HOTKEY = 0x0312;
        private const int GWL_WNDPROC = -4;

        public const uint MOD_ALT = 0x0001;
        public const uint MOD_CONTROL = 0x0002;
        public const uint MOD_SHIFT = 0x0004;
        public const uint MOD_WIN = 0x0008;

        [DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        private IntPtr _windowHandle;
        private MauiWindow? _window;
        private Action? _callback;
        private bool _isRegistered;
        private uint _currentModifiers;
        private uint _currentKey;
        private IntPtr _originalWndProc;
        private WndProcDelegate? _wndProc;

        /// <summary>
        /// Windows 平台支持全局热键
        /// </summary>
        public bool IsSupported => true;

        /// <summary>
        /// 注册全局热键
        /// </summary>
        /// <param name="modifiers">修饰键字符串，多个键用逗号分隔（如 "Control,Alt"）</param>
        /// <param name="key">主键字符串（如 "X"）</param>
        /// <param name="callback">热键触发时的回调操作</param>
        public void RegisterHotKey(string modifiers, string key, Action callback)
        {
            if (_window == null)
            {
                _window = Microsoft.Maui.Controls.Application.Current?.Windows.FirstOrDefault();
                if (_window == null) return;
            }

            if (_window.Handler?.PlatformView is not Microsoft.UI.Xaml.Window platformWindow) return;
            _windowHandle = WindowNative.GetWindowHandle(platformWindow);
            if (_windowHandle == IntPtr.Zero) return;

            _callback = callback;
            _currentModifiers = ParseModifiers(modifiers);
            _currentKey = ParseKey(key);

            if (_isRegistered)
            {
                UnregisterHotKey();
            }

            if (RegisterHotKey(_windowHandle, HOTKEY_ID, _currentModifiers, _currentKey))
            {
                _isRegistered = true;
                EnsureWndProcHook();
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Failed to register hotkey");
            }
        }

        /// <summary>
        /// 注销全局热键
        /// </summary>
        public void UnregisterHotKey()
        {
            if (_isRegistered)
            {
                UnregisterHotKey(_windowHandle, HOTKEY_ID);
                _isRegistered = false;
            }

            if (_originalWndProc != IntPtr.Zero && _windowHandle != IntPtr.Zero)
            {
                SetWindowProc(_windowHandle, GWL_WNDPROC, _originalWndProc);
                _originalWndProc = IntPtr.Zero;
                _wndProc = null;
            }
        }

        /// <summary>
        /// 更新热键配置
        /// </summary>
        /// <param name="modifiers">新的修饰键字符串</param>
        /// <param name="key">新的主键字符串</param>
        public void UpdateHotKey(string modifiers, string key)
        {
            if (_callback != null)
            {
                RegisterHotKey(modifiers, key, _callback);
            }
        }

        private void EnsureWndProcHook()
        {
            if (_originalWndProc != IntPtr.Zero) return;
            if (_windowHandle == IntPtr.Zero) return;

            _wndProc = WndProc;
            var newWndProcPtr = Marshal.GetFunctionPointerForDelegate(_wndProc);
            _originalWndProc = SetWindowProc(_windowHandle, GWL_WNDPROC, newWndProcPtr);
        }

        private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            if (msg == WM_HOTKEY && wParam == (IntPtr)HOTKEY_ID)
            {
                _callback?.Invoke();
            }

            if (_originalWndProc != IntPtr.Zero)
            {
                return CallWindowProc(_originalWndProc, hWnd, msg, wParam, lParam);
            }

            return DefWindowProc(hWnd, msg, wParam, lParam);
        }

        /// <summary>
        /// 解析修饰键字符串
        /// </summary>
        private uint ParseModifiers(string modifiers)
        {
            uint mod = 0;
            if (string.IsNullOrEmpty(modifiers)) return mod;

            var parts = modifiers.Split(',');
            foreach (var part in parts)
            {
                var p = part.Trim();
                if (p.Equals("Control", StringComparison.OrdinalIgnoreCase)) mod |= MOD_CONTROL;
                if (p.Equals("Alt", StringComparison.OrdinalIgnoreCase)) mod |= MOD_ALT;
                if (p.Equals("Shift", StringComparison.OrdinalIgnoreCase)) mod |= MOD_SHIFT;
                if (p.Equals("Windows", StringComparison.OrdinalIgnoreCase)) mod |= MOD_WIN;
            }
            return mod;
        }

        /// <summary>
        /// 解析主键
        /// </summary>
        private uint ParseKey(string key)
        {
            if (key.Length == 1)
            {
                char c = char.ToUpper(key[0]);
                if (c >= 'A' && c <= 'Z') return (uint)c;
                if (c >= '0' && c <= '9') return (uint)c;
            }
            return 0x58; // Default 'X'
        }

        private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtrW")]
        private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongW")]
        private static extern IntPtr SetWindowLong32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        private static IntPtr SetWindowProc(IntPtr hWnd, int nIndex, IntPtr newProc)
        {
            return IntPtr.Size == 8
                ? SetWindowLongPtr64(hWnd, nIndex, newProc)
                : SetWindowLong32(hWnd, nIndex, newProc);
        }

        [DllImport("user32.dll")]
        private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
    }
}
#endif
