using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using AxCopilot.Services.Agent;

namespace AxCopilot.ViewModels;

/// <summary>설치된 플러그인 한 항목의 ViewModel.</summary>
public class PluginItemViewModel : INotifyPropertyChanged
{
    private bool _isEnabled;

    public InstalledPlugin Plugin { get; }

    public string Id          => Plugin.Manifest.Id;
    public string Name        => Plugin.Manifest.Name;
    public string Version     => Plugin.Manifest.Version;
    public string Description => Plugin.Manifest.Description;
    public string Author      => Plugin.Manifest.Author;
    public string Type        => Plugin.Manifest.Type;
    public string InstalledAt => Plugin.InstalledAt.ToLocalTime().ToString("yyyy-MM-dd");

    public bool IsEnabled
    {
        get => _isEnabled;
        set { _isEnabled = value; OnPropertyChanged(); }
    }

    public PluginItemViewModel(InstalledPlugin plugin)
    {
        Plugin    = plugin;
        _isEnabled = plugin.IsEnabled;
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string? name = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

/// <summary>
/// Phase L3-1: 플러그인 갤러리 ViewModel.
/// SettingsWindow 또는 별도 플러그인 관리 화면에서 바인딩합니다.
/// </summary>
public class PluginGalleryViewModel : INotifyPropertyChanged
{
    private readonly PluginInstallService _service;
    private PluginItemViewModel? _selectedPlugin;
    private string _statusMessage = "";
    private bool _isBusy;

    public ObservableCollection<PluginItemViewModel> Plugins { get; } = new();

    public PluginItemViewModel? SelectedPlugin
    {
        get => _selectedPlugin;
        set { _selectedPlugin = value; OnPropertyChanged(); OnPropertyChanged(nameof(HasSelection)); }
    }

    public bool HasSelection => _selectedPlugin != null;

    public string StatusMessage
    {
        get => _statusMessage;
        private set { _statusMessage = value; OnPropertyChanged(); }
    }

    public bool IsBusy
    {
        get => _isBusy;
        private set { _isBusy = value; OnPropertyChanged(); }
    }

    // ─── Commands ───────────────────────────────────────────────────────────

    public ICommand InstallFromZipCommand { get; }
    public ICommand UninstallCommand      { get; }
    public ICommand ToggleEnabledCommand  { get; }
    public ICommand RefreshCommand        { get; }

    public PluginGalleryViewModel(PluginInstallService service)
    {
        _service = service;

        InstallFromZipCommand = new RelayCommand<string>(async zipPath =>
        {
            if (string.IsNullOrWhiteSpace(zipPath)) return;
            IsBusy = true;
            StatusMessage = "설치 중…";
            var result = await _service.InstallFromZipAsync(zipPath);
            StatusMessage = result.Message;
            if (result.Success) Refresh();
            IsBusy = false;
        });

        UninstallCommand = new RelayCommand<string>(async pluginId =>
        {
            if (string.IsNullOrWhiteSpace(pluginId)) return;
            IsBusy = true;
            StatusMessage = "제거 중…";
            var ok = await _service.UninstallAsync(pluginId);
            StatusMessage = ok ? "제거 완료." : "제거 실패.";
            if (ok) Refresh();
            IsBusy = false;
        });

        ToggleEnabledCommand = new RelayCommand<PluginItemViewModel>(async item =>
        {
            if (item == null) return;
            await _service.SetEnabledAsync(item.Id, item.IsEnabled);
            StatusMessage = $"'{item.Name}' {(item.IsEnabled ? "활성화" : "비활성화")} 완료.";
        });

        RefreshCommand = new RelayCommand<object>(_ => { Refresh(); return Task.CompletedTask; })!;

        Refresh();
    }

    /// <summary>서비스에서 설치 목록을 다시 로드합니다.</summary>
    public void Refresh()
    {
        Plugins.Clear();
        foreach (var p in _service.Installed)
            Plugins.Add(new PluginItemViewModel(p));
        StatusMessage = Plugins.Count == 0 ? "설치된 플러그인이 없습니다." : $"{Plugins.Count}개 설치됨";
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string? name = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

// ─── 간단한 RelayCommand 구현 (WPF MVVM) ────────────────────────────────────

file sealed class RelayCommand<T> : ICommand
{
    private readonly Func<T?, Task> _execute;
    private bool _running;

    public RelayCommand(Func<T?, Task> execute) => _execute = execute;

    public event EventHandler? CanExecuteChanged;
    public bool CanExecute(object? _) => !_running;
    public async void Execute(object? parameter)
    {
        _running = true;
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        try { await _execute(parameter is T t ? t : default); }
        finally
        {
            _running = false;
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }
    }
}
