using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reactive;
using Avalonia.Controls;
using Avalonia.Interactivity;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Input;
using DynamicData;
using DynamicData.Binding;
using Newtonsoft.Json;
using PSCHelpdesk.Plugins.HetznerServer.Models;
using PSCHelpdesk.Plugins.HetznerServer.Service;
using PSCHelpdesk.Plugins.HetznerServer.Views;
using PSCHelpdesk.Shared.Service;
using PSCHelpdesk.Shared.Setting;
using PSCHelpdesk.Shared.ViewModels;
using ReactiveUI;

namespace PSCHelpdesk.Plugins.HetznerServer.ViewModels;

public class Domain
{
    public string DomainName { get; set; } = string.Empty;
}

public class Customer
{
    public string Ip4 { get; set; } = string.Empty;
    public string ApiKey { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public List<Domain> Domains { get; set; } = new List<Domain>();
}

public class Customers
{
    public List<Customer> Data { get; set; } = new List<Customer>();
}

public partial class ServerViewModel : ViewModelBase, IViewModelBase
{
    public readonly ServerService  ServerService;
    public ReactiveCommand<SelectionChangedEventArgs, Unit> SelectionChanged { get; }
    public ReactiveCommand<Unit, Unit> SaveServerSettings { get; }
    
    public ReactiveCommand<Unit, Unit> AptUpdate { get; }
    public ReactiveCommand<Unit, Unit> ReScan { get; }
    public ReactiveCommand<Unit, Unit> Reboot { get; }
    
    protected readonly ReadOnlyObservableCollection<Server> _server;
    public ReadOnlyObservableCollection<Server> Server => _server;
    
    private SettingsManager _settingsManager;
    public ServerViewModel()
    {
        Title = "Server";
        ServerService = new ServerService();
        SelectedServer = new Server(1,"","","","","");
        SelectionChanged = ReactiveCommand.Create<SelectionChangedEventArgs>(selectionChanged);
        SaveServerSettings = ReactiveCommand.Create(saveServerSettings);
        AptUpdate = ReactiveCommand.Create(doAptUpdate);
        ReScan = ReactiveCommand.Create(doReScan);
        Reboot = ReactiveCommand.Create(doReboot);
        _settingsManager = (SettingsManager)Ioc.Default.GetService<ISettingsManager>();
        ServerService.SourceCache.Connect()
            // Sort Ascending on the OrderIndex property
            .Sort(SortExpressionComparer<Server>.Ascending(t => t.ServerId))
            .Filter(x => x.Name.Contains(_searchText, StringComparison.OrdinalIgnoreCase) || x.ServerId.ToString().Contains(_searchText, StringComparison.OrdinalIgnoreCase) || x.Domains.Count(d => d.Name.Contains(_searchText, StringComparison.OrdinalIgnoreCase)) > 0)
            // Bind to our ReadOnlyObservableCollection<T>
            .Bind(out _server)
            // Subscribe for changes
            .Subscribe();
    }
    
    private bool _isPagePaneOpen = true;
    public bool IsPagePaneOpen
    {
        get => _isPagePaneOpen;
        set => SetAndRaisePropertyChanged(ref _isPagePaneOpen, value);
    }
    
    private string _searchText = "";
    public string SearchText
    {
        get => _searchText;
        set
        {
            SetAndRaisePropertyChanged(ref _searchText, value);
            ServerService.SourceCache.Refresh();
        }
    }

    private Server _selectedServer;
    public Server SelectedServer
    {
        get => _selectedServer;
        set => SetAndRaisePropertyChanged(ref _selectedServer, value);
    }
    
    private string _json;
    public string Json
    {
        get => _json;
        set => SetAndRaisePropertyChanged(ref _json, value);
    }

    void selectionChanged(SelectionChangedEventArgs args)
    {
        this.SelectedServer = (args.Source as DataGrid).SelectedItem as Server;
        IsPagePaneOpen = true;

        var data = new Customers();
        foreach (var server in _server)
        {
            var customer = new Customer();
            customer.Name = server.Name;
            customer.Ip4 = server.Ipv4;
            customer.ApiKey = server.PscApiKey;
            foreach (var domain in server.Domains)
            {
                customer.Domains.Add(new Domain()
                {
                    DomainName = domain.Name
                });
            }
            data.Data.Add(customer);
        }
        
        Json = JsonConvert.SerializeObject(data);
    }
    
    public void SSH(Server server)
    {
        Process.Start(_settingsManager.CoreSettings.SSHClientExecutable,string.Format(_settingsManager.CoreSettings.SSHClientExecutableArgs, server.Ipv4, _settingsManager.CoreSettings.PrivateSSHKeyPath, server.Name));

    }
    
    public void SCP(Server server)
    {
        Process.Start(_settingsManager.CoreSettings.SCPClientExecutable,string.Format(_settingsManager.CoreSettings.SCPClientExecutableArgs, server.Ipv4, _settingsManager.CoreSettings.PrivateSSHKeyPath, server.Name));

    }

    void saveServerSettings()
    {
        ServerService.SaveSettings(SelectedServer);
    }
    
    void doAptUpdate()
    {
        foreach (var serv in Server)
        {
            if (serv.IsChecked)
            {
                ServerService.DoAptUpgrade(serv);
            }
        }
    }
    
    void doReboot()
    {
        foreach (var serv in Server)
        {
            if (serv.IsChecked)
            {
                ServerService.DoReboot(serv);
            }
        }
    }
    
    void doReScan()
    {
        foreach (var serv in Server)
        {
            if (serv.IsChecked)
            {
                ServerService.DoReScan(serv);
            }
        }
    }
}