#nullable enable
using eSuite.WorkBench.Commands;
using eSuite.WorkBench.Models;
using eSuite.WorkBench.Services;
using eSuite.WorkBench.WpfHelper;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Windows;

namespace eSuite.WorkBench
{
    public class MainWindowViewModel : ViewModelBase, IMainWindowViewModel
    {
        private readonly ICommandsService _commandsService;
        private readonly IDbService _dbService;
        private readonly IContainerRegistryClient _containerRegistryClient;
        private readonly IUpdateChecker _updateChecker;

        public SelectableObservableCollection<string> AvailableProxyTags { get; set; } =
            new SelectableObservableCollection<string>();

        public SelectableObservableCollection<string> AvailableWebUiTags { get; set; } =
            new SelectableObservableCollection<string>();

        public SelectableObservableCollection<string> AvailableApiTags { get; set; } =
            new SelectableObservableCollection<string>();

        public SelectableObservableCollection<string> AvailableDbMigratorTags { get; set; } =
            new SelectableObservableCollection<string>();
        public Dictionary<string, List<string>> ProxyBranchesVersions { get; set; } =
            new Dictionary<string, List<string>>();
        public Dictionary<string, List<string>> ApiBranchesVersions { get; set; } =
            new Dictionary<string, List<string>>();

        public Dictionary<string, List<string>> WebUiBranchesVersions { get; set; } =
            new Dictionary<string, List<string>>();

        public Dictionary<string, List<string>> DbMigratorBranchesVersions { get; set; } =
            new Dictionary<string, List<string>>();

        public SelectableObservableCollection<string> AvailableSchedulerTags { get; set; } = new SelectableObservableCollection<string>();

        public Dictionary<string, List<string>> SchedulerBranchesVersions { get; set; } =
            new Dictionary<string, List<string>>();

        public SelectableObservableCollection<string> AvailableMessageProcessorTags { get; set; } = new SelectableObservableCollection<string>();

        public Dictionary<string, List<string>> MessageProcessorBranchesVersions { get; set; } = new Dictionary<string, List<string>>();


        public Dictionary<string, List<string>> CombinedBranches { get; set; } = new Dictionary<string, List<string>>();

        public SelectableObservableCollection<string> DatabaseBackups { get; set; } =
            new SelectableObservableCollection<string>();

        public AsyncCommandBase StartContainersCommand { get; }
        public AsyncCommandBase StopContainersCommand { get; }
        public AsyncCommandBase BackupDatabaseCommand { get; }
        public AsyncCommandBase DeleteDatabaseCommand { get; }
        public AsyncCommandBase RestoreDatabaseCommand { get; }
        public AsyncCommandBase SelectBranchCommand { get; }
        public AsyncCommandBase DeleteBranchCommand { get; }
        public AsyncCommandBase GetTagListCommand { get; }
        public AsyncCommandBase LaunchSwaggerCommand { get; }
        public AsyncCommandBase LaunchWebUiCommand { get; }
        public AsyncCommandBase LaunchHealthZCommand { get; }

        public AsyncCommandBase ClearFeedBackCommand { get; }

        public SaveUserSettingsCommand SaveUserSettingsCommand { get; }

        public string SettingsLogin
        {
            get => _settingsLogin;
            set
            {
                if (value == _settingsLogin) return;
                OnPropertyChanging();
                _settingsLogin = value;
                OnPropertyChanged();
            }
        }

        public string SettingsPassword
        {
            get => _settingsPassword;
            set
            {
                if (value == _settingsPassword) return;
                OnPropertyChanging();
                _settingsPassword = value;
                OnPropertyChanged();
            }
        }

        public bool DeveloperMode
        {
            get => _developerMode;
            set
            {
                if (value == _developerMode) return;
                OnPropertyChanging();
                _developerMode = value;
                OnPropertyChanged();
            }
        }

        public string DevopsPersonalAccessKey
        {
            get => _devopsPersonalAccessKey;
            set
            {
                if (value == _devopsPersonalAccessKey) return;
                OnPropertyChanging();
                _devopsPersonalAccessKey = value;
                OnPropertyChanged();
            }
        }

        private string _feedbackOutput = string.Empty;

        public string FeedbackOutput
        {
            get => _feedbackOutput;

            set
            {
                if (value == _feedbackOutput)
                    return;
                OnPropertyChanging();
                _feedbackOutput = value;
                OnPropertyChanged();
            }
        }

        private ObservableCollection<Branch> _branches = new();
        private Branch? _selectedBranch;
        private bool _developerMode;
        private string _settingsPassword = string.Empty;
        private string _settingsLogin = string.Empty;
        private string _applicationTitle = string.Empty;
        private string _devopsPersonalAccessKey = string.Empty;

        public ObservableCollection<Branch> Branches
        {
            get => _branches;
            set
            {
                if (value == _branches)
                    return;
                OnPropertyChanging();
                _branches = value;
                OnPropertyChanged();
            }
        }

        public Branch? SelectedBranch
        {
            get => _selectedBranch;
            set
            {
                if (_selectedBranch == value)
                    return;
                OnPropertyChanging();
                _selectedBranch = value;
                OnPropertyChanged();
            }
        }

        public string ApplicationTitle
        {
            get => _applicationTitle;
            set
            {
                if (value == _applicationTitle) return;
                OnPropertyChanging();
                _applicationTitle = value;
                OnPropertyChanged();
            }
        }

        public MainWindowViewModel(
            ICommandsService commandsService,
            IDbService dbService,
            IContainerRegistryClient containerRegistryClient,
            IUpdateChecker updateChecker
        )
        {
            _commandsService = commandsService;
            _dbService = dbService;
            _containerRegistryClient = containerRegistryClient;
            _updateChecker = updateChecker;

            Properties.Settings.Default.Upgrade();
            SettingsLogin = Properties.Settings.Default.SqlServerAdminLogin;
            SettingsPassword = Properties.Settings.Default.SqlServerAdminPassword;
            DeveloperMode = Properties.Settings.Default.DeveloperMode;
            DevopsPersonalAccessKey = Properties.Settings.Default.DevopsPersonalAccessKey;

            ApplicationTitle = GetApplicationTitle();

            CheckForUpdates();

            FindDatabaseBackups();
            StartContainersCommand =
                new StartContainersCommand(this, _commandsService, DisplayExceptionWindow, AddFeedbackMessage);
            StopContainersCommand =
                new StopContainersCommand(this, _commandsService, DisplayExceptionWindow, AddFeedbackMessage);
            BackupDatabaseCommand = new BackupDatabaseCommand(_dbService, DisplayExceptionWindow, AddFeedbackMessage);
            DeleteDatabaseCommand =
                new DeleteDatabaseCommand(this, _dbService, DisplayExceptionWindow, AddFeedbackMessage);
            RestoreDatabaseCommand =
                new RestoreDatabaseCommand(this, _dbService, DisplayExceptionWindow, AddFeedbackMessage);
            SelectBranchCommand = new SelectBranchVersionCommand(this, DisplayExceptionWindow, AddFeedbackMessage);
            DeleteBranchCommand = new DeleteBranchVersionCommand(this, _containerRegistryClient, DisplayExceptionWindow, AddFeedbackMessage);
            GetTagListCommand = new GetTagListCommand(this, _containerRegistryClient, DisplayExceptionWindow,
                AddFeedbackMessage);
            SaveUserSettingsCommand = new SaveUserSettingsCommand(this, DisplayExceptionWindow, AddFeedbackMessage);
            LaunchSwaggerCommand =
                new LaunchSwaggerCommand(this, _commandsService, DisplayExceptionWindow, AddFeedbackMessage);
            LaunchWebUiCommand =
                new LaunchWebUiCommand(this, _commandsService, DisplayExceptionWindow, AddFeedbackMessage);
            LaunchHealthZCommand = new LaunchHealthzCommand(this, _commandsService, DisplayExceptionWindow, AddFeedbackMessage);
            ClearFeedBackCommand =
                new ClearFeedBackCommand(this, _commandsService, DisplayExceptionWindow, AddFeedbackMessage);
            
            GetTagListCommand.Execute(null);
        }

        private void CheckForUpdates()
        {
#if !DEBUG
            _updateChecker.CheckForUpdates(DevopsPersonalAccessKey);
#endif
        }

        public static string GetApplicationTitle()
        {
            var productName = string.Empty;

            var productAssembly = Assembly.GetEntryAssembly();
            if (productAssembly == null)
                throw new NullReferenceException("Unable to figure out the applications start assembly.");

            var thisAssemblyName = productAssembly.GetName();

            var assemblyVersion = thisAssemblyName.Version?.ToString() ?? string.Empty;

            var list = productAssembly.GetCustomAttributes();
            foreach (var attribute in list)
            {
                if (attribute is AssemblyProductAttribute productAttribute)
                {
                    productName = productAttribute.Product;
                    break;
                }
            }

            return $"{productName} {assemblyVersion}";
        }

        private void FindDatabaseBackups()
        {
            var backupFiles = _dbService.BackupsList();
            foreach (var file in backupFiles)
            {
                DatabaseBackups.Add(file);
            }
        }


        private void DisplayExceptionWindow(Exception ex)
        {
            MessageBox.Show("An unknown error occured.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
        }

        private void AddFeedbackMessage(object? sender, FeedbackEventArgs e)
        {
            FeedbackOutput += $"{e.Message}\n";
        }
    }
}

    
