using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Aitex.Core.RT.Log;
using MECF.Framework.UI.Client.ClientBase;
using MECF.Framework.UI.Client.ClientBase.Dialog;
using MECF.Framework.UI.Core.Accounts;
using OpenSEMI.ClientBase;
using OpenSEMI.ClientBase.Command;

namespace MECF.Framework.UI.Client.CenterViews.Configs.Accounts
{
    public sealed class AccountViewModel : BaseModel
    {
        #region Variables

        private ObservableCollection<AccountItem> _AccountsList = new();
        private AccountItem _treeSelectedAccount = null;
        private CtrlMode _controlMode = CtrlMode.VIEW;
        private PasswordBox _newPasswordBox;
        private PasswordBox _confirmPasswordBox;
        
        private ICommand _btnSaveAccountCommand;
        private ICommand _btnAddAccountCommand;
        private ICommand _btnCloneAccountCommand;
        private ICommand _btnDeleteAccountCommand;
        private ICommand _btnCancelAccountCommand;

        #endregion
        
        #region Property
        
        public AccountItem TreeSelectedAccount
        {
            get => _treeSelectedAccount;
            set { _treeSelectedAccount = value; NotifyOfPropertyChange(); }
        }

        
        public CtrlMode ControlMode
        {
            get => _controlMode;
            set { _controlMode = value; NotifyOfPropertyChange(); }
        }

        
        public ObservableCollection<AccountItem> AccountList => _AccountsList;
        

        #region command define
        
        
        public ICommand BtnSaveAccountCommand
        {
            get
            {
                if (_btnSaveAccountCommand == null)
                    _btnSaveAccountCommand = new BaseCommand<object>(OnBtnSaveAccountCommand);
                return _btnSaveAccountCommand;
            }
        }

        
        public ICommand BtnAddAccountCommand
        {
            get
            {
                if (_btnAddAccountCommand == null)
                    _btnAddAccountCommand = new BaseCommand<object>(OnBtnAddAccountCommand);
                return _btnAddAccountCommand;
            }
        }

        
        public ICommand BtnCloneAccountCommand
        {
            get
            {
                if (_btnCloneAccountCommand == null)
                    _btnCloneAccountCommand = new BaseCommand<object>(OnBtnCloneAccountCommand);
                return _btnCloneAccountCommand;
            }
        }

        
        public ICommand BtnDeleteAccountCommand
        {
            get
            {
                if (_btnDeleteAccountCommand == null)
                    _btnDeleteAccountCommand = new BaseCommand<object>(OnBtnDeleteAccountCommand);
                return _btnDeleteAccountCommand;
            }
        }

        
        public ICommand BtnCancelAccountCommand
        {
            get
            {
                if (_btnCancelAccountCommand == null)
                    _btnCancelAccountCommand = new BaseCommand<object>(OnBtnCancelAccountCommand);
                return _btnCancelAccountCommand;
            }
        }
        #endregion
        #endregion

        #region Constructors

        public AccountViewModel()
        {
            DisplayName = "Account";
        }

        #endregion

        #region ViewModel Operations

        protected override void OnViewLoaded(object view)
        {
            base.OnViewLoaded(view);
            var av = view as AccountView;
            _newPasswordBox = av.pwNewPassword;
            _confirmPasswordBox = av.pwConfirmPassword;
        }

        protected override void OnActivate()
        {
            AccountManagerClient.Instance.Initialize();
            RefreshAccountList();
        }

        protected override void OnDeactivate(bool close)
        {
            if (ControlMode == CtrlMode.EDIT && IsPermission)
            {
                if (DialogBox.Confirm("The data has been modified. Do you want to save the change(s)?"))
                {
                    if (SaveChanged(out var reason))
                    {
                        ControlMode = CtrlMode.VIEW;
                        DialogBox.ShowInfo("Saving successfully.");
                    }
                    else
                    {
                        DialogBox.ShowError($"Saving failed, {reason}");
                    }
                }
            }
            base.OnDeactivate(close);
        }

        #endregion

        #region Methods

        public void ChangePassword()
        {
            /*if (TreeSelectedAccount == null)
            {
                DialogBox.ShowError("No account selected.");
                return;
            }
            
            var dlg = new AccountPasswordChangeDialog(TreeSelectedAccount.AccountID);
            if (dlg.ShowDialog() != true) 
                return;
            
            if (ret.ActSucc)
            {
                DialogBox.ShowInfo("Password changed successfully.");
            }
            else
            {
                DialogBox.ShowError($"Password change failed, {ret.Description}");
            }*/
        }
        
        private void RefreshAccountList()
        {
            _AccountsList.Clear();
            _treeSelectedAccount = null;

            var accounts = AccountManagerClient.Instance.GetAllAccounts();
            if (accounts == null || accounts.Count == 0) return;

            foreach (var acc in accounts)
            {
                var treeAccount = AccountManagerClient.Instance.CloneAccount(acc);
                if (treeAccount != null)
                {
                    if (treeAccount.AccountName == BaseApp.Instance.UserContext.LoginName)
                    {
                        treeAccount.IsEnableChangeAccountName = false;
                    }
                    _AccountsList.Add(treeAccount);
                }
            }

            TreeSelectedAccount = _AccountsList.FirstOrDefault();
            TreeSelectedAccount.IsSelected = true;
            ControlMode = CtrlMode.VIEW;
        }

        public void OnPasswordChanged(object sender, RoutedEventArgs args)
        {
            if(_treeSelectedAccount == null)
                return;
            
            if (sender is PasswordBox pb)
            {
                switch (pb.Tag)
                {
                    case "NewPassword":
                        _treeSelectedAccount.NewPassword = pb.Password;
                        break;
                    
                    case "ConfirmPassword":
                        _treeSelectedAccount.ConfirmPassword = pb.Password;
                        break;
                }

                if (ControlMode != CtrlMode.EDIT)
                    ControlMode = CtrlMode.EDIT;
            }
        }

        
        public void OnAccountChanged()
        {
            if (ControlMode == CtrlMode.EDIT)
                return;

            //check account to set the mode from view to edit
            if (_treeSelectedAccount != null && _treeSelectedAccount.IsAccountChanged())
                ControlMode = CtrlMode.EDIT;
        }

        private bool SaveChanged(out string reason)
        {
            reason = "";
            if (string.IsNullOrWhiteSpace(TreeSelectedAccount.DisplayAccountName))
            {
                reason = "Account Name cannot be empty.";
                //TreeSelectedAccount.DisplayAccountName = "NewUser";
                return false;
            }

            if (IsAccountExists(TreeSelectedAccount))
            {
                reason = "Account already exists.";
                return false;
            }

            TreeSelectedAccount.NewPassword = _newPasswordBox.Password;
            TreeSelectedAccount.ConfirmPassword = _confirmPasswordBox.Password;

            if (string.IsNullOrWhiteSpace(TreeSelectedAccount.NewPassword) ||
                string.IsNullOrWhiteSpace(TreeSelectedAccount.ConfirmPassword))
            {
                reason = "Password cannot be empty.";
                return false;
            }

            if (TreeSelectedAccount.NewPassword != TreeSelectedAccount.ConfirmPassword)
            {
                reason = "The password does not match.";
                return false;
            }

            if (!string.IsNullOrEmpty(TreeSelectedAccount.DisplayEmail))
            {
                var reg = @"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";
                var r = new Regex(reg);
                if (!r.IsMatch(TreeSelectedAccount.DisplayEmail))
                {
                    reason = "The email is invalid.";
                    return false;
                }
            }

            TreeSelectedAccount.AccountName = TreeSelectedAccount.DisplayAccountName;
            TreeSelectedAccount.FirstName = TreeSelectedAccount.DisplayFirstName;
            TreeSelectedAccount.LastName = TreeSelectedAccount.DisplayLastName;
            TreeSelectedAccount.Email = TreeSelectedAccount.DisplayEmail;
            TreeSelectedAccount.Description = TreeSelectedAccount.DisplayDescription;
            TreeSelectedAccount.AccountTextSaved = TreeSelectedAccount.FirstNameTextSaved =
                TreeSelectedAccount.LastNameTextSaved = TreeSelectedAccount.EmailTextSaved = true;

            var isRoleSelected = false;
            foreach (var entity in TreeSelectedAccount.RoleColleciton)
            {
                if (entity.DisplayRoleStatus)
                {
                    isRoleSelected = true;
                }

                entity.RoleStatus = entity.DisplayRoleStatus;
            }

            if (!isRoleSelected)
            {
                reason = "Please set role information for this account.";
                return false;
            }

            try
            {
                AccountManagerClient.Instance.SaveAccount(TreeSelectedAccount);
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            _newPasswordBox.Clear();
            _confirmPasswordBox.Clear();
            return true;
        }

        private bool IsAccountExists(AccountItem account)
        {
            if (AccountList == null || AccountList.Count == 0)
                return false;

            var sameNameList = AccountList.Where(t => t.DisplayAccountName == account.DisplayAccountName);
            if (sameNameList.Count() <= 1)
                return false;

            return true;
        }

        private void OnBtnAddAccountCommand(object arg)
        {
            var newAccount = AccountManagerClient.Instance.CreateAccount();
            if (newAccount != null)
            {
                _AccountsList.Add(newAccount);
                TreeSelectedAccount = newAccount;
                TreeSelectedAccount.IsSelected = true;
            }
            ControlMode = CtrlMode.EDIT;
        }

        private void OnBtnDeleteAccountCommand(object arg)
        {
            if (_treeSelectedAccount == null) return;

            if (!DialogBox.Confirm("Are you sure that you want to delete this account?"))
            {
                return;
            }

            if (BaseApp.Instance.UserContext.LoginName == _treeSelectedAccount.AccountName)
            {
                DialogBox.ShowError("The action cannot be completed because {0} is currently in use.", "the account");
                return;
            }

            AccountManagerClient.Instance.DeleteAccount(TreeSelectedAccount.AccountID);
            RefreshAccountList();
        }

        private void OnBtnCloneAccountCommand(object arg)
        {
            if (_treeSelectedAccount != null)
            {
                var newAccount = AccountManagerClient.Instance.CreateAccount(_treeSelectedAccount);
                if (newAccount != null)
                {
                    newAccount.DisplayAccountName = newAccount.AccountName = "Copy of " + newAccount.DisplayAccountName;
                    _AccountsList.Add(newAccount);
                    TreeSelectedAccount = newAccount;
                    TreeSelectedAccount.IsSelected = true;
                    ControlMode = CtrlMode.EDIT;
                }
            }
        }

        private void OnBtnSaveAccountCommand(object arg)
        {
            if (!TreeSelectedAccount.IsValid)
            {
                DialogBox.ShowWarning("Input error.");
                return;
            }

            if (SaveChanged(out var reason))
            {
                ControlMode = CtrlMode.VIEW;
                DialogBox.ShowInfo("Saving successfully.");
            }
            else
                DialogBox.ShowError($"Saving failed, {reason}");
        }

        private void OnBtnCancelAccountCommand(object arg)
        {
            RefreshAccountList();
            _newPasswordBox.Clear();
            _confirmPasswordBox.Clear();
            ControlMode = CtrlMode.VIEW;
        }

        #endregion        
    }
}
