using System.Runtime.CompilerServices;
using Avalonia.Controls;
using ClaudeDo.Ui.ViewModels.MissionControl;

namespace ClaudeDo.Ui.Views.MissionControl;

/// <summary>
/// Hosts the single long-lived <see cref="ConPtyPaneView"/> of a <see cref="ConPtyPaneViewModel"/>.
/// The Mission Control layouts recreate their DataTemplate content freely (the overview grid is
/// rebuilt from scratch on every pane/column change, focus-mode tabs re-present on selection), but
/// the running PTY session is bound to the original TerminalControl — a freshly instantiated view
/// would render a dead, empty terminal. This host therefore reparents the pane's one real view
/// instead of letting the template create a new one. Safe while the session runs because
/// <see cref="Services.PtyTerminalSession"/> puts the control in permanent reparent mode
/// (detach never kills the child process).
/// </summary>
public sealed class ConPtyPaneHost : Decorator
{
    // Keyed weakly so a closed pane's view dies with its view model.
    private static readonly ConditionalWeakTable<ConPtyPaneViewModel, ConPtyPaneView> Views = new();

    public ConPtyPaneHost()
    {
        DataContextChanged += (_, _) => Reclaim();
        AttachedToVisualTree += (_, _) => Reclaim();
    }

    /// <summary>Takes ownership of the pane's cached view, stealing it from whichever host showed
    /// it last — but only while effectively visible, so the hidden layout (overview grid vs. focus
    /// tabs) never yanks the view away from the visible one.</summary>
    public void Reclaim()
    {
        var vm = DataContext as ConPtyPaneViewModel;

        // A recycled host now bound to a different pane must not keep showing the old view.
        // The cached views carry their own local DataContext, so this check can't be fooled
        // by DataContext inheritance.
        if (Child is ConPtyPaneView stale && !ReferenceEquals(stale.DataContext, vm))
            Child = null;

        if (vm is null || !IsEffectivelyVisible) return;

        var view = Views.GetValue(vm, static key => new ConPtyPaneView { DataContext = key });
        if (ReferenceEquals(Child, view)) return;
        if (view.Parent is ConPtyPaneHost previous) previous.Child = null;
        Child = view;
    }
}
