using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Threading;
using Avalonia.VisualTree;
using ClaudeDo.Ui.ViewModels.Islands;

namespace ClaudeDo.Ui.Views.Islands;

public partial class NotesEditorView : UserControl
{
    private NotesEditorViewModel? _vm;

    public NotesEditorView()
    {
        InitializeComponent();
        DataContextChanged += OnDataContextChanged;
        // Tunnel, not bubble: with AcceptsReturn on, TextBox.OnKeyDown consumes Enter (any
        // modifier) before a bubbling handler ever sees it. Taking Enter in the tunnel phase
        // keeps the split chain, and letting Shift+Enter through leaves the newline to the box.
        AddHandler(KeyDownEvent, OnBulletKeyDown, RoutingStrategies.Tunnel);
    }


    private void OnDataContextChanged(object? sender, EventArgs e)
    {
        if (_vm is not null) _vm.FocusRequested -= FocusBullet;
        _vm = DataContext as NotesEditorViewModel;
        if (_vm is not null) _vm.FocusRequested += FocusBullet;
    }

    /// <summary>Rows the VM just inserted have no container yet — wait for the layout pass that
    /// creates it before reaching for the TextBox inside.</summary>
    private void FocusBullet(NoteBulletViewModel bullet) =>
        Dispatcher.UIThread.Post(
            () => RowsHost.ContainerFromItem(bullet)?.FindDescendantOfType<TextBox>()?.Focus(),
            DispatcherPriority.Loaded);

    private void OnBulletKeyDown(object? sender, KeyEventArgs e)
    {
        // Source, not sender: the tunnel handler is attached to the whole view, so it sees the
        // capture box at the top as well as the note rows. Both need the same Enter/Shift+Enter
        // split, and neither can get it from a KeyBinding — with AcceptsReturn on, TextBox eats
        // Enter in its own OnKeyDown before any bubbling handler or binding runs.
        if (e.Source is not TextBox box || DataContext is not NotesEditorViewModel vm) return;
        var shift = e.KeyModifiers.HasFlag(KeyModifiers.Shift);

        if (ReferenceEquals(box, NewNoteBox))
        {
            if (e.Key == Key.Enter && !shift)
            {
                e.Handled = true;
                vm.AddBulletCommand.Execute(null);
            }
            return;
        }

        if (box.DataContext is not NoteBulletViewModel bullet) return;

        // Shift+Enter falls through to the TextBox and breaks the line — a note can be several.
        if (e.Key == Key.Enter && !shift)
        {
            e.Handled = true;
            vm.SplitBulletCommand.Execute(bullet);
        }
        else if (e.Key == Key.Back && string.IsNullOrEmpty(box.Text))
        {
            e.Handled = true;
            vm.DeleteBulletCommand.Execute(bullet);
        }
    }

    private void OnBulletLostFocus(object? sender, RoutedEventArgs e)
    {
        if (sender is TextBox { DataContext: NoteBulletViewModel bullet }
            && DataContext is NotesEditorViewModel vm
            && vm.CommitBulletCommand.CanExecute(bullet))
            vm.CommitBulletCommand.Execute(bullet);
    }

    private void OnDeleteBulletClick(object? sender, RoutedEventArgs e)
    {
        if (sender is Button { DataContext: NoteBulletViewModel bullet }
            && DataContext is NotesEditorViewModel vm)
            vm.DeleteBulletCommand.Execute(bullet);
    }
}
