using System;
using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ClaudeDo.Ui.Services;

namespace ClaudeDo.Ui.ViewModels.MissionControl;

/// <summary>
/// Command Center pane hosting an embedded ConPTY terminal for either one task's interactive
/// Claude session, or an ad-hoc/free session in a user-chosen directory (no task, <see cref="TaskId"/>
/// is null — ad-hoc panes are never deduped, unlike task-based ones). Distinct from the streamed-log
/// <see cref="ClaudeDo.Ui.ViewModels.Islands.TaskMonitorViewModel"/> pane; the two coexist until
/// the streaming interactive stack is removed.
/// </summary>
public sealed partial class ConPtyPaneViewModel : ViewModelBase, IMissionControlPane, IDisposable
{
    public string? TaskId { get; }

    [ObservableProperty] private string _displayTitle;

    public InteractiveTerminalViewModel Terminal { get; } = new();

    /// <summary>Raised when the terminal failed to start — the host surfaces this via the footer error strip.</summary>
    public event Action<string>? ErrorReported;

    /// <summary>Set by the host (Mission Control) to remove this pane from its collection.</summary>
    public Action<ConPtyPaneViewModel>? CloseRequested { get; set; }

    /// <summary>Task-based pane — dedup'd by <see cref="TaskId"/>. Pass null for an ad-hoc pane
    /// (no task, never deduped); prefer <see cref="CreateAdHoc"/> at ad-hoc call sites.</summary>
    public ConPtyPaneViewModel(string? taskId, string displayTitle, TerminalLaunchDescriptor descriptor)
    {
        TaskId = taskId;
        _displayTitle = displayTitle;
        Terminal.PropertyChanged += OnTerminalPropertyChanged;
        Terminal.Start(descriptor);
    }

    /// <summary>Ad-hoc pane — no task, no dedup.</summary>
    public static ConPtyPaneViewModel CreateAdHoc(string displayTitle, TerminalLaunchDescriptor descriptor)
        => new(null, displayTitle, descriptor);

    private void OnTerminalPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(InteractiveTerminalViewModel.StartError) && Terminal.StartError is { Length: > 0 } error)
            ErrorReported?.Invoke(error);
    }

    [RelayCommand]
    private void Close() => CloseRequested?.Invoke(this);

    public void Dispose()
    {
        Terminal.PropertyChanged -= OnTerminalPropertyChanged;
        Terminal.Kill();
        Terminal.Dispose();
    }
}
