using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace AxCopilot.Views;

/// <summary>
/// 텍스트가 선택된 상태에서 핫키를 누르면 커서 위치에 표시되는 액션 선택 팝업.
/// ↑↓ 화살표로 이동, Enter로 실행, Esc로 닫기.
/// </summary>
public partial class TextActionPopup : Window
{
    [DllImport("user32.dll")]
    private static extern bool GetCursorPos(out POINT lpPoint);

    [StructLayout(LayoutKind.Sequential)]
    private struct POINT { public int X; public int Y; }

    public enum ActionResult { None, OpenLauncher, Translate, Summarize, GrammarFix, Explain, Rewrite }

    public ActionResult SelectedAction { get; private set; } = ActionResult.None;
    public string SelectedText { get; private set; } = "";

    private int _selectedIndex;
    private readonly List<(ActionResult Action, string Icon, string Label)> _items;

    // 전체 명령 정의 (key → ActionResult, icon, label)
    private static readonly (string Key, ActionResult Action, string Icon, string Label)[] AllCommands =
    {
        ("translate", ActionResult.Translate,   "\uE774", "번역"),
        ("summarize", ActionResult.Summarize,   "\uE8D2", "요약"),
        ("grammar",   ActionResult.GrammarFix,  "\uE8AC", "문법 교정"),
        ("explain",   ActionResult.Explain,     "\uE946", "설명"),
        ("rewrite",   ActionResult.Rewrite,     "\uE70F", "다시 쓰기"),
    };

    /// <summary>사용 가능한 전체 명령 키와 라벨 목록.</summary>
    public static IReadOnlyList<(string Key, string Label)> AvailableCommands
        => AllCommands.Select(c => (c.Key, c.Label)).ToList();

    public TextActionPopup(string selectedText, List<string>? enabledCommands = null)
    {
        InitializeComponent();

        SelectedText = selectedText;
        var preview = selectedText.Replace("\r\n", " ").Replace("\n", " ");
        PreviewText.Text = preview.Length > 60 ? preview[..57] + "…" : preview;

        // 설정에서 활성화된 명령만 표시
        var enabled = enabledCommands ?? AllCommands.Select(c => c.Key).ToList();

        _items = new() { (ActionResult.OpenLauncher, "\uE8A7", "AX Commander 열기") };
        foreach (var cmd in AllCommands)
        {
            if (enabled.Contains(cmd.Key, StringComparer.OrdinalIgnoreCase))
                _items.Add((cmd.Action, cmd.Icon, cmd.Label));
        }

        BuildMenuItems();
        PositionAtCursor();

        Loaded += (_, _) =>
        {
            Focus();
            UpdateSelection();
        };
    }

    private void BuildMenuItems()
    {
        var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
        var accentBrush = TryFindResource("AccentColor") as Brush ?? Brushes.CornflowerBlue;

        for (int i = 0; i < _items.Count; i++)
        {
            var (action, icon, label) = _items[i];
            var idx = i;

            var sp = new StackPanel { Orientation = Orientation.Horizontal };
            sp.Children.Add(new TextBlock
            {
                Text = icon,
                FontFamily = ThemeResourceHelper.SegoeMdl2,
                FontSize = 14,
                Foreground = accentBrush,
                VerticalAlignment = VerticalAlignment.Center,
                Margin = new Thickness(0, 0, 10, 0),
                Width = 20,
                TextAlignment = TextAlignment.Center,
            });
            sp.Children.Add(new TextBlock
            {
                Text = label,
                FontSize = 13,
                Foreground = primaryText,
                VerticalAlignment = VerticalAlignment.Center,
            });

            var border = new Border
            {
                Child = sp,
                CornerRadius = new CornerRadius(8),
                Padding = new Thickness(10, 8, 14, 8),
                Margin = new Thickness(0, 1, 0, 1),
                Background = Brushes.Transparent,
                Cursor = Cursors.Hand,
                Tag = idx,
            };

            border.MouseEnter += (s, _) =>
            {
                if (s is Border b && b.Tag is int n)
                {
                    _selectedIndex = n;
                    UpdateSelection();
                }
            };

            border.MouseLeftButtonUp += (_, _) =>
            {
                SelectedAction = action;
                Close();
            };

            MenuItems.Children.Add(border);
        }
    }

    private void UpdateSelection()
    {
        var hoverBrush = TryFindResource("ItemHoverBackground") as Brush
                         ?? new SolidColorBrush(Color.FromArgb(0x18, 0xFF, 0xFF, 0xFF));
        var selectedBrush = TryFindResource("ItemSelectedBackground") as Brush
                            ?? new SolidColorBrush(Color.FromArgb(0x44, 0x4B, 0x5E, 0xFC));

        for (int i = 0; i < MenuItems.Children.Count; i++)
        {
            if (MenuItems.Children[i] is Border b)
                b.Background = i == _selectedIndex ? selectedBrush : Brushes.Transparent;
        }
    }

    private void PositionAtCursor()
    {
        GetCursorPos(out var pt);

        // DPI 보정
        var source = PresentationSource.FromVisual(this);
        double dpiX = 1.0, dpiY = 1.0;
        if (source?.CompositionTarget != null)
        {
            dpiX = source.CompositionTarget.TransformFromDevice.M11;
            dpiY = source.CompositionTarget.TransformFromDevice.M22;
        }

        Left = pt.X * dpiX;
        Top = pt.Y * dpiY + 10; // 커서 아래쪽에 표시

        // 화면 밖으로 나가지 않도록 보정
        var screen = SystemParameters.WorkArea;
        if (Left + 280 > screen.Right) Left = screen.Right - 280;
        if (Top + 300 > screen.Bottom) Top = pt.Y * dpiY - 300; // 위쪽으로
        if (Left < screen.Left) Left = screen.Left;
        if (Top < screen.Top) Top = screen.Top;
    }

    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.Up:
                _selectedIndex = (_selectedIndex - 1 + _items.Count) % _items.Count;
                UpdateSelection();
                e.Handled = true;
                break;

            case Key.Down:
                _selectedIndex = (_selectedIndex + 1) % _items.Count;
                UpdateSelection();
                e.Handled = true;
                break;

            case Key.Enter:
                SelectedAction = _items[_selectedIndex].Action;
                Close();
                e.Handled = true;
                break;

            case Key.Escape:
                SelectedAction = ActionResult.None;
                Close();
                e.Handled = true;
                break;
        }
    }

    private void Window_Deactivated(object? sender, EventArgs e)
    {
        // 포커스를 잃으면 자동 닫기
        if (IsVisible) Close();
    }
}
