using System;
using System.Collections.Concurrent;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Data;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using FontAwesome.Sharp;
using PersonalToolBox.Helpers;
using PersonalToolBox.ViewModels;

namespace PersonalToolBox.Views;

public partial class MainWindow : Window
{
    private readonly MainViewModel _viewModel;
    private readonly HotKeyManager _hotKeyManager;
    private NotifyIcon? _notifyIcon;
    private ToolStripMenuItem? _hotKeyToggleMenuItem;
    private bool _canActuallyClose;

    [DllImport("user32.dll")]
    private static extern uint RegisterWindowMessage(string lpString);

    private readonly int _showMainMsg;

    public MainWindow(MainViewModel viewModel, HotKeyManager hotKeyManager)
    {
        InitializeComponent();

        _viewModel = viewModel;
        _hotKeyManager = hotKeyManager;
        DataContext = viewModel;

        _showMainMsg = (int)RegisterWindowMessage("PersonalToolBox_ShowMain");

        var iconPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "app.ico");
        if (File.Exists(iconPath))
        {
            using var stream = File.OpenRead(iconPath);
            var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
            this.Icon = decoder.Frames[0];
        }

        viewModel.Logs.CollectionChanged += OnLogsCollectionChanged;
        viewModel.PropertyChanged += OnViewModelPropertyChanged;

        CreateTrayIcon();
    }

    /// <summary>
    /// 窗口句柄就绪后注册全局快捷键
    /// </summary>
    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        var hwndSource = (HwndSource)PresentationSource.FromVisual(this)!;
        _hotKeyManager.Initialize(hwndSource.Handle);
        hwndSource.AddHook(WndProcHook);
        _viewModel.RegisterAllHotKeys();
    }

    // ──────────────── 系统托盘 ────────────────

    /// <summary>
    /// 创建系统托盘图标及右键菜单
    /// </summary>
    private void CreateTrayIcon()
    {
        var iconPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "app.ico");
        var trayIcon = File.Exists(iconPath)
            ? new System.Drawing.Icon(iconPath)
            : System.Drawing.SystemIcons.Application;

        _notifyIcon = new NotifyIcon
        {
            Icon = trayIcon,
            Visible = true,
            Text = "个人工具箱"
        };

        _notifyIcon.MouseClick += (s, e) =>
        {
            if (e.Button == MouseButtons.Left)
                ToggleVisibility();
        };

        var menu = new ContextMenuStrip();
        menu.Items.Add("显示主界面", null, (_, _) => ShowMainWindow());

        _hotKeyToggleMenuItem = new ToolStripMenuItem(
            _viewModel.IsHotKeyEnabled ? "暂停快捷键功能" : "恢复快捷键功能");
        _hotKeyToggleMenuItem.Click += (_, _) => _viewModel.ToggleHotKeyCommand.Execute(null);
        menu.Items.Add(_hotKeyToggleMenuItem);

        menu.Items.Add(new ToolStripSeparator());
        menu.Items.Add("彻底退出", null, (_, _) => ExitApplication());
        _notifyIcon.ContextMenuStrip = menu;
    }

    /// <summary>
    /// 左键托盘图标：切换窗口显示/隐藏
    /// </summary>
    private void ToggleVisibility()
    {
        if (IsVisible)
            Hide();
        else
            ShowMainWindow();
    }

    /// <summary>
    /// 显示主窗口并置前
    /// </summary>
    private void ShowMainWindow()
    {
        Show();
        WindowState = WindowState.Normal;
        Activate();
    }

    /// <summary>
    /// 彻底退出程序
    /// </summary>
    public void ExitApplication()
    {
        _canActuallyClose = true;
        _notifyIcon?.Dispose();
        _hotKeyManager.Dispose();
        System.Windows.Application.Current.Shutdown();
    }

    /// <summary>
    /// 点击关闭按钮时隐藏窗口而非退出
    /// </summary>
    protected override void OnClosing(CancelEventArgs e)
    {
        if (!_canActuallyClose)
        {
            e.Cancel = true;
            Hide();
        }
        base.OnClosing(e);
    }

    // ──────────────── 其他 ────────────────

    private IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == _showMainMsg)
        {
            Dispatcher.Invoke(() => ShowMainWindow());
            handled = true;
            return IntPtr.Zero;
        }

        handled = _hotKeyManager.TryHandleMessage(msg, wParam, lParam);
        return IntPtr.Zero;
    }

    private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(MainViewModel.IsHotKeyEnabled) && _hotKeyToggleMenuItem != null)
        {
            bool enabled = _viewModel.IsHotKeyEnabled;
            _hotKeyToggleMenuItem.Text = enabled ? "暂停快捷键功能" : "恢复快捷键功能";
        }
    }

    private void OnLogsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add && LogListBox.Items.Count > 0)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                LogListBox.ScrollIntoView(LogListBox.Items[^1]);
            }), System.Windows.Threading.DispatcherPriority.Background);
        }
    }
}

/// <summary>
/// bool → double: true=1.0, false=0.4 (工具卡片失效时置灰)
/// </summary>
public class BoolToOpacityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is bool b && b ? 1.0 : 0.4;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => throw new NotImplementedException();
}

/// <summary>
/// string → string: 取字符串首字符作为图标占位
/// </summary>
public class FirstCharConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var s = value as string;
        return string.IsNullOrEmpty(s) ? "?" : s[0].ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => throw new NotImplementedException();
}

/// <summary>
/// string → IconChar: 将图标枚举名称字符串转换为 IconChar 枚举值
/// </summary>
public class StringToIconCharConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string s && !string.IsNullOrEmpty(s) && System.Enum.TryParse<IconChar>(s, true, out var icon))
            return icon;
        return IconChar.None;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => throw new NotImplementedException();
}

/// <summary>
/// string (exe路径) → ImageSource: 提取 .exe 文件自身图标，带缓存
/// </summary>
public class ExePathToIconConverter : IValueConverter
{
    private static readonly ConcurrentDictionary<string, ImageSource?> Cache = new();

    public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is not string path || path.Length == 0)
            return null;

        if (!path.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
            return null;

        return Cache.GetOrAdd(path, key =>
        {
            try
            {
                if (!File.Exists(key))
                    return null;

                using var icon = System.Drawing.Icon.ExtractAssociatedIcon(key);
                if (icon == null)
                    return null;

                using var bitmap = icon.ToBitmap();
                using var ms = new MemoryStream();
                bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                ms.Seek(0, SeekOrigin.Begin);

                var image = new BitmapImage();
                image.BeginInit();
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.StreamSource = ms;
                image.EndInit();
                image.Freeze();
                return image;
            }
            catch
            {
                return null;
            }
        });
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => throw new NotImplementedException();
}
