using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using NexusShell.Models;
using NexusShell.Services;

namespace NexusShell.ViewModels;

public sealed class NexusConsoleViewModel : INotifyPropertyChanged
{
    private readonly NexusConsoleService _console;
    private readonly ProfileService _profile;
    private string _commandInput = string.Empty;

    public NexusConsoleViewModel(NexusConsoleService console, ProfileService profile)
    {
        _console = console;
        _profile = profile;
        OutputLines = new ObservableCollection<string>();
        ExecuteCommand = new RelayCommand(_ => SubmitCommand(), _ => CommandInput.Length > 0);
        CloseCommand = new RelayCommand(_ => ExitRequested?.Invoke(this, EventArgs.Empty));
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    public event EventHandler? ExitRequested;
    public event EventHandler<string?>? OpenBrowserRequested;
    public event EventHandler<string?>? OpenFilesRequested;
    public event EventHandler? RestartShellRequested;

    public ObservableCollection<string> OutputLines { get; }

    public string RoleLabel => FormatRole(_profile.CurrentProfile?.Role ?? "User");

    public string SessionLabel => "Local POC";

    public string CommandInput
    {
        get => _commandInput;
        set
        {
            _commandInput = value;
            OnPropertyChanged();
        }
    }

    public ICommand ExecuteCommand { get; }

    public ICommand CloseCommand { get; }

    public void Reset()
    {
        OutputLines.Clear();
        CommandInput = string.Empty;
        OnPropertyChanged(nameof(RoleLabel));
        AppendWelcome();
        _console.LogConsoleOpened();
    }

    public void SubmitCommand()
    {
        var input = CommandInput.Trim();
        if (input.Length == 0)
        {
            return;
        }

        AppendLine($"nexus> {input}");
        CommandInput = string.Empty;

        var result = _console.Execute(input);
        ApplyResult(result);
    }

    private void ApplyResult(NexusCommandResult result)
    {
        foreach (var line in result.Lines)
        {
            AppendLine(line);
        }

        switch (result.Action)
        {
            case NexusConsoleAction.ClearOutput:
                OutputLines.Clear();
                break;
            case NexusConsoleAction.ExitConsole:
                ExitRequested?.Invoke(this, EventArgs.Empty);
                break;
            case NexusConsoleAction.OpenBrowser:
                OpenBrowserRequested?.Invoke(this, result.ActionArgument);
                break;
            case NexusConsoleAction.OpenFiles:
                OpenFilesRequested?.Invoke(this, result.ActionArgument);
                break;
            case NexusConsoleAction.RestartShell:
                RestartShellRequested?.Invoke(this, EventArgs.Empty);
                break;
        }
    }

    private void AppendWelcome()
    {
        AppendLine("Nexus Console 1.0 POC — secure internal command interface");
        AppendLine("Type 'help' for whitelisted commands.");
        AppendLine("");
    }

    private void AppendLine(string line)
    {
        OutputLines.Add(line);
        OnPropertyChanged(nameof(OutputLines));
    }

    private static string FormatRole(string role) => role switch
    {
        "MasterDeveloper" => "Master Developer",
        "Developer" => "Developer",
        "Administrator" => "Administrator",
        _ => role,
    };

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