using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DragonISO.App.ViewModels;

namespace DragonISO.App.Views;

/// <summary>
/// The Ctrl+K command palette window. Centered over its <see cref="Window.Owner"/>,
/// chromeless, dismissable with Esc or clicking outside the palette card.
///
/// Keyboard contract:
///   <list type="bullet">
///     <item>Type to filter (autofocus on the TextBox at open time)</item>
///     <item>â†‘ / â†“ â€” move the selection</item>
///     <item>Enter â€” invoke the highlighted command, then close</item>
///     <item>Esc â€” close without invoking</item>
///   </list>
/// </summary>
public partial class CommandPaletteWindow : Window
{
    public CommandPaletteWindow()
    {
        InitializeComponent();
        // Autofocus the filter input on open so the operator can start typing
        // immediately â€” the whole point of Ctrl+K is "no mouse required".
        Loaded += (_, _) => FilterBox.Focus();
        // Closing on click-outside: WindowStyle=None means we don't get the
        // standard "deactivated" behavior cleanly, but Deactivated still
        // fires when focus leaves the window (e.g., clicking the main shell).
        Deactivated += (_, _) => Close();
    }

    public CommandPaletteWindow(CommandPaletteViewModel vm) : this()
    {
        DataContext = vm;
    }

    private CommandPaletteViewModel Vm => (CommandPaletteViewModel)DataContext;

    /// <summary>
    /// Window-level key handling. We use PreviewKeyDown so the TextBox's
    /// internal handling doesn't swallow â†‘/â†“/Enter before we see them.
    /// </summary>
    protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.Escape:
                e.Handled = true;
                Close();
                break;
            case Key.Down:
                e.Handled = true;
                Vm?.MoveSelection(+1);
                ScrollSelectedIntoView();
                break;
            case Key.Up:
                e.Handled = true;
                Vm?.MoveSelection(-1);
                ScrollSelectedIntoView();
                break;
            case Key.Enter:
                e.Handled = true;
                var invoked = Vm?.InvokeSelection() ?? false;
                // Close regardless â€” Enter on an empty palette is "I'm done";
                // Enter on a real command means the action fired and the
                // operator wants to return to the main shell.
                if (invoked) Close();
                break;
            default:
                base.OnPreviewKeyDown(e);
                break;
        }
    }

    private void ScrollSelectedIntoView()
    {
        if (ResultsList is null) return;
        var sel = ResultsList.SelectedItem;
        if (sel is null) return;
        ResultsList.ScrollIntoView(sel);
    }
}
