using LHDN.CRM.BC.Repositories;
using LHDN.CRM.Models.Models;
using LHDN.CRM.Models.ViewModels;
using System.Collections.Generic;
using System.Linq;
using LHDN.CRM.BC.Common;
using System.Web;
using System.Security.Principal;
using LHDN.CRM.BC.Filters;
using System.Data;
using System;
using System.Transactions;
using System.Collections;
using System.Threading;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices;

//using System.Collections.Specialized;
//using System.Collections;
//using System.Web.Configuration;

namespace LHDN.CRM.BC.Services
{
    public class UserProfileService
    {
        UserRepository userRepo = new Repositories.UserRepository();

        public string DisplayName
        {
            get
            {
                return GetCurrentUserDisplayName();
            }
        }

        public string LoginID
        {
            get
            {
                return GetCurrentUserLoginID();
            }
        }

        public string Email
        {
            get
            {
                return GetCurrentUserEmail();
            }
        }

        public int UnitID
        {
            get
            {
                return GetCurrentUserUnitID();
            }
        }

        public string UnitName
        {
            get
            {
                return GetCurrentUserUnitName();
            }
        }

        public string UPTimeStamp
        {
            get
            {
                return GetUPTimeStamp();
            }
        }

        public List<RoleInfo> RoleGroups
        {
            get
            {
                return GetCurrentUserRoleGroups();
            }
        }

        public List<string> Roles
        {
            get
            {
                return GetCurrentUserRoles();
            }
        }

        public List<TindakanSusulanViewModel> RoleTindakanSusulan
        {
            get
            {
                return GetCurrentUserRoleTindakanSusulan();
            }
        }

        public WorkflowUserViewModel Manager
        {
            get
            {
                return GetCurrentUserManager();
            }
        }

        public UserInfoViewModel UserInfo
        {
            get { return GetUserByLoginID(); }
        }

        public UserInfoViewModel GetUserByLoginID()
        {
            string strLoginID = GetCurrentAuthenticatedLoginID();

            return GetUserByLoginID(strLoginID);
        }

        public UserInfoViewModel GetLoginInfoandInitializePrincipal()
        {
            string strLoginID = GetCurrentAuthenticatedLoginID();
            string strCacheName = Utilities.GetUserCacheName(strLoginID);
            UserInfoViewModel user;

            if (!CachingService.TryGet<UserInfoViewModel>(strCacheName, out user))
            {
                //UserProfileService userSvc = new UserProfileService();
                //var users = userSvc.GetUserPrincipalByLoginID(strLoginID);
                //HttpContext.Current.User = users;
            }
            return GetUserByLoginID(strLoginID);
        }

        public UserInfoViewModel GetUserByLoginID(string username)
        {
            string strCacheName = Utilities.GetUserCacheName(username);
            UserInfoViewModel user;
            //IPrincipal iUser = null;
            // if (HttpContext.Current.Session != null && HttpContext.Current.Session[strSessionName] != null)
            if (!CachingService.TryGet<UserInfoViewModel>(strCacheName, out user))
            {
                CachingService.TryGetOrAdd<UserInfoViewModel>(strCacheName, () => userRepo.GetUserByLoginID(username), out user, 3600);
            }

            return user;
        }

        public UserInfoViewModel UpdateUserCacheByLoginID(string username)
        {
            string strCacheName = Utilities.GetUserCacheName(username);
            UserInfoViewModel user = new UserInfoViewModel();
            //IPrincipal iUser = null;
            // if (HttpContext.Current.Session != null && HttpContext.Current.Session[strSessionName] != null)

            if (CachingService.TrySetOrUpdate<UserInfoViewModel>(strCacheName, () => userRepo.GetUserByLoginID(username), out user, 3600))
            {
                //LogWriter.LogMessage("Updated user 1: " + user?.LastUpdatedDateTime + " - " + user?.DisplayName);
                CachingService.TryGet<UserInfoViewModel>(strCacheName, out user);
                //LogWriter.LogMessage("Updated user 2: " + user?.LastUpdatedDateTime + " - " + user?.DisplayName);
            }
            return user;
        }

        public bool RemoveUserCacheByLoginID(string username)
        {
            string strCacheName = Utilities.GetUserCacheName(username);
            UserInfoViewModel user = new UserInfoViewModel();
            //IPrincipal iUser = null;
            // if (HttpContext.Current.Session != null && HttpContext.Current.Session[strSessionName] != null)
            return CachingService.Clear(strCacheName);

        }

        public IPrincipal GetUserPrincipalByLoginID(string username)
        {
            // string strCacheName = Utilities.GetUserCacheName(username);

            string strCacheName = Utilities.GetUserCacheName(username);
            UserInfoViewModel user;
            IPrincipal iUser = null;

            user = GetUserByLoginID(username);

            return iUser;
        }

        // public List<UserRoleListViewModel> GetUserRoleListing(UserRoleListViewModel paging, out int intCount)
        public List<UserRoleListViewModel> GetUserRoleListing()
        {
            DataSet ds = userRepo.GetUserRoleListing();

            List<UserRoleListViewModel> lst = new List<UserRoleListViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                //    if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                lst = userRepo.DataTableToList<UserRoleListViewModel>(ds.Tables[0]).ToList();
                //    if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0)
                //        intCount = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());
            }

            return lst;
        }

        public UserRoleMatrix GetUserRoleMatrix()
        {
            return userRepo.GetUserRoleMatrix();
        }

        public List<TaskCategory> GetFuncTaskList(int intFunctionalRoleID)
        {
            return userRepo.GetFuncTaskList(intFunctionalRoleID);
        }

        public UserRoleDetailViewModel GetUserRoleDetails(int intFunctionalRoleID)
        {
            UserRoleDetailViewModel role = new UserRoleDetailViewModel();
            role = userRepo.GetUserRoleDetails(intFunctionalRoleID);
            if (role == null) role = new UserRoleDetailViewModel();

            role.TaskCategory = GetFuncTaskList(intFunctionalRoleID);

            // Flag main header Select All True if every element is selected
            if (role.TaskCategory.Where(x => x.SelectAll).Count() == role.TaskCategory.Count)
            {
                role.SelectAll = true;
            }
            else
            {
                role.SelectAll = false;
            }

            role.RoleUnits = userRepo.GetUserRoleMembersUnits(intFunctionalRoleID);

            return role;
        }

        public List<AuditDetailViewModel> SaveRoleDetails(UserRoleDetailViewModel roleDetails, bool blnIsUpdate, string strActionBy, DateTime dtTrxDateTime, out int intFunctionalRoleID, out UserCacheViewModel objUserNameCache)
        {
            List<AuditDetailViewModel> adtDetail = new List<AuditDetailViewModel>();
            bool blnIsUpdateTasks = false;
            bool blnIsUpdateMember = false;
            bool blnIsUpdateActiveStatus = false;
            List<RoleMember> lstAddedUser = new List<RoleMember>();
            List<RoleMember> lstDeletedUser = new List<RoleMember>();
            List<RoleMember> lstExistingUser = new List<RoleMember>();
            int intAddedUser = 0;
            int intRemovedUser = 0;
            objUserNameCache = new UserCacheViewModel();

            if (blnIsUpdate)
            {
                // Retrieve orginal records for audit and change history 
                UserRoleDetailViewModel oriRoleDetail = new UserRoleDetailViewModel();
                oriRoleDetail = GetUserRoleDetails(roleDetails.FunctionalRoleID);

                // Check for update conflict
                if (!Utilities.CompareByteArray(roleDetails.ChangeStamp, oriRoleDetail.ChangeStamp))
                {
                    throw new UpdateConflictException();
                }

                #region "Audit"                
                if (oriRoleDetail.RoleName != roleDetails.RoleName)
                {
                    adtDetail.Add(Utilities.GetAuditDetail("Role Name", oriRoleDetail.RoleName, roleDetails.RoleName));
                }

                if (oriRoleDetail.IsActive != roleDetails.IsActive)
                {
                    adtDetail.Add(Utilities.GetAuditDetail("Is Active", oriRoleDetail.IsActive.ToString(), roleDetails.IsActive.ToString()));
                    blnIsUpdateActiveStatus = true;
                }
                #region "Functional task Audit"              
                // Functional Task
                List<FunctionalTask> lstOriTasks = new List<FunctionalTask>();
                List<FunctionalTask> lstNewTasks = new List<FunctionalTask>();
                lstOriTasks = oriRoleDetail.TaskCategory.SelectMany(x => x.FunctionalTasks)
                                .Select(a => new FunctionalTask { FunctionalTaskID = a.FunctionalTaskID, FunctionalTaskName = a.FunctionalTaskName, Selected = a.Selected })
                                .Where(b => b.Selected == true).ToList();
                lstNewTasks = roleDetails.TaskCategory.SelectMany(x => x.FunctionalTasks)
                                .Select(a => new FunctionalTask { FunctionalTaskID = a.FunctionalTaskID, FunctionalTaskName = a.FunctionalTaskName, Selected = a.Selected })
                                .Where(b => b.Selected == true).ToList();
                string strOld = "Selected Functional Tasks : " + Environment.NewLine;
                string strNew = "Selected Functional Tasks : " + Environment.NewLine;
                string strAuditFormat = "{0} {1}";
                int intOldTaskCount = lstOriTasks.Count();
                if (intOldTaskCount != lstNewTasks.Count() ||
                    lstOriTasks.Join(lstNewTasks, a => a.FunctionalTaskID, b => b.FunctionalTaskID,
                        (a, b) => new FunctionalTask
                        {
                            FunctionalTaskID = a.FunctionalTaskID,
                            FunctionalTaskName = a.FunctionalTaskName,
                            Selected = a.Selected
                        })
                        .ToList().Count() != intOldTaskCount)
                {
                    foreach (FunctionalTask funcTask in lstOriTasks)
                    {
                        strOld += string.Format(strAuditFormat, funcTask.FunctionalTaskName, Environment.NewLine);
                    }

                    foreach (FunctionalTask funcTask in lstNewTasks)
                    {
                        strNew += string.Format(strAuditFormat, funcTask.FunctionalTaskName, Environment.NewLine);
                    }
                    adtDetail.Add(Utilities.GetAuditDetail("Functional Tasks", strOld, strNew));
                    blnIsUpdateTasks = true;
                }
                #endregion

                #region "User Role Membership Audit"              
                // Functional Task
                List<RoleMember> lstOriMembers = new List<RoleMember>();
                List<RoleMember> lstNewMembers = new List<RoleMember>();
                lstOriMembers = oriRoleDetail.RoleUnits.SelectMany(x => x.RoleMembers)
                                .Select(a => new RoleMember
                                {
                                    UnitID = a.UnitID,
                                    DisplayName = a.DisplayName,
                                    UserProfileID = a.UserProfileID
                                }).ToList();
                lstNewMembers = roleDetails.RoleUnits.SelectMany(x => x.RoleMembers)
                                .Select(a => new RoleMember
                                {
                                    UnitID = a.UnitID,
                                    DisplayName = a.DisplayName,
                                    UserProfileID = a.UserProfileID
                                }).ToList();
                string strOldMembers = "";
                string strNewmembers = "";
                string strAuditMembersFormat = "{0} {1}";
                int intOldMemberCount = lstOriMembers.Count();
                if (intOldMemberCount != lstNewMembers.Count() ||
                    lstOriMembers.Join(lstNewMembers, a => new { a.UnitID, a.UserProfileID },
                                                      b => new { b.UnitID, b.UserProfileID },
                                            (a, b) => new RoleMember
                                            {
                                                UnitID = a.UnitID,
                                                UserProfileID = a.UserProfileID
                                            })
                                            .ToList().Count() != intOldMemberCount)
                {
                    foreach (RoleMember member in lstOriMembers)
                    {
                        RoleUnit unit = oriRoleDetail.RoleUnits.Where(x => x.UnitID == member.UnitID).FirstOrDefault();
                        if (unit != null)
                        {
                            string strUnitName = unit.UnitName + " (" + unit.BranchName + ")  : ";
                            strOldMembers += string.Format(strAuditMembersFormat, strUnitName + member.DisplayName, Environment.NewLine);
                        }
                    }

                    foreach (RoleMember member in lstNewMembers)
                    {
                        RoleUnit unit = roleDetails.RoleUnits.Where(x => x.UnitID == member.UnitID).FirstOrDefault();
                        if (unit != null)
                        {
                            string strUnitName = unit.UnitName + " (" + unit.BranchName + ")  : ";
                            strNewmembers += string.Format(strAuditMembersFormat, strUnitName + member.DisplayName, Environment.NewLine);
                        }
                    }
                    adtDetail.Add(Utilities.GetAuditDetail("User Role Memberships", strOldMembers, strNewmembers));
                    blnIsUpdateMember = true;

                    lstAddedUser = lstNewMembers.Except(lstOriMembers, new RoleMemberComparer()).ToList();
                    lstDeletedUser = lstOriMembers.Except(lstNewMembers, new RoleMemberComparer()).ToList();

                    intAddedUser = lstAddedUser != null ? lstAddedUser.Count() : 0;
                    intRemovedUser = lstDeletedUser != null ? lstDeletedUser.Count() : 0;

                }
                #endregion
                #endregion

            }

            using (var scope = new TransactionScope(TransactionScopeOption.Required))
            {
                if (blnIsUpdate)
                {
                    userRepo.UpdateProfileDateByRole(roleDetails.FunctionalRoleID, dtTrxDateTime);

                    intFunctionalRoleID = userRepo.UpdateFunctionalRoleDetails(roleDetails, strActionBy, dtTrxDateTime);
                }
                else
                {
                    intFunctionalRoleID = userRepo.InsertFunctionalRoleDetails(roleDetails, strActionBy, dtTrxDateTime);
                    roleDetails.FunctionalRoleID = intFunctionalRoleID;

                    userRepo.UpdateProfileDateByRole(roleDetails.FunctionalRoleID, dtTrxDateTime);
                }

                scope.Complete();
            }

            // Update user cache item if any
            //if (blnIsUpdate)
            //{
            //var thread = new Thread(() =>
            //{

            objUserNameCache.roleDetails = roleDetails;
            objUserNameCache.AddedUser = intAddedUser;
            objUserNameCache.RemovedUser = intRemovedUser;
            objUserNameCache.AddedUserList = lstAddedUser;
            objUserNameCache.DeletedUserList = lstDeletedUser;
            objUserNameCache.IsUpdateActiveStatus = blnIsUpdateActiveStatus;
            objUserNameCache.IsUpdateMember = blnIsUpdateMember;
            objUserNameCache.IsUpdateTasks = blnIsUpdateTasks;

            UpdateUserCache(objUserNameCache);
            //});
            //thread.Start();
            //}

            return adtDetail;
        }

        public void UpdateUserCache(UserCacheViewModel objUser)
        {
            UserRoleDetailViewModel roleDetails = objUser.roleDetails;
            //LogWriter.LogMessage("Start Update Cache");
            Dictionary<string, UserInfoViewModel> diUserRoles = CachingService.ContainsKey<UserInfoViewModel>(Constant.Sessions.LoginInfo);
            if (objUser.IsUpdateTasks)
            {
                //LogWriter.LogMessage("Update Task Cache");

                //LogWriter.LogMessage("Cachec Dictionary : " + diUserRoles.Count.ToString());
                // Update affected member
                foreach (var obj in diUserRoles)
                {
                    string strKey = obj.Key;
                    UserInfoViewModel user = obj.Value;

                    //LogWriter.LogMessage("Cache Key : " + strKey);
                    if (user.RoleGroups.Any(x => x.Role.Contains(roleDetails.RoleName)))
                    {
                        UpdateUserCacheByLoginID(user.LoginID);
                        //LogWriter.LogMessage("Updated cache : " + strKey + " " + user.LoginID);
                    }
                }
            }
            if ((objUser.IsUpdateMember && (objUser.AddedUser != 0 || objUser.RemovedUser != 0)) || objUser.IsUpdateActiveStatus)
            {
                List<RoleMember> lstExistingMember = roleDetails.RoleUnits.SelectMany(x => x.RoleMembers)
                    .Select(a => new RoleMember
                    {
                        UnitID = a.UnitID,
                        DisplayName = a.DisplayName,
                        UserProfileID = a.UserProfileID
                    }).ToList();

                //LogWriter.LogMessage("Update Active status cache : " + lstExistingMember.Count.ToString());
                foreach (RoleMember member in lstExistingMember)
                {
                    foreach (var obj in diUserRoles)
                    {
                        string strKey = obj.Key;
                        UserInfoViewModel user = obj.Value;

                        //LogWriter.LogMessage("Update Active status cache existing member: " + strKey);
                        if (user.UserProfileID == member.UserProfileID)
                        {
                            UpdateUserCacheByLoginID(user.LoginID);

                            //LogWriter.LogMessage("Updated cache : " + strKey + " " + user.LoginID);
                        }
                    }
                }

                // Update removed member
                foreach (RoleMember member in objUser.AddedUserList)
                {
                    foreach (var obj in diUserRoles)
                    {
                        string strKey = obj.Key;
                        UserInfoViewModel user = obj.Value;
                        //LogWriter.LogMessage("Update added member: " + strKey);
                        if (user.UserProfileID == member.UserProfileID)
                        {
                            UpdateUserCacheByLoginID(user.LoginID);

                            //LogWriter.LogMessage("Updated cache : " + strKey + " " + user.LoginID);
                        }
                    }
                }

                foreach (RoleMember member in objUser.DeletedUserList)
                {
                    foreach (var obj in diUserRoles)
                    {
                        string strKey = obj.Key;
                        UserInfoViewModel user = obj.Value;
                        //LogWriter.LogMessage("Update deleted member: " + strKey);
                        if (user.UserProfileID == member.UserProfileID)
                        {
                            UpdateUserCacheByLoginID(user.LoginID);

                            //LogWriter.LogMessage("Updated cache : " + strKey + " " + user.LoginID);
                        }
                    }
                }

            }
        }

        public bool FindDuplicateRoleName(UserRoleDetailViewModel roleDetail)
        {
            bool blnIsDuplicate = false;
            int intCount = userRepo.FindDuplicateRoleName(roleDetail);
            if (intCount > 0) blnIsDuplicate = true;
            return blnIsDuplicate;
        }

        public List<PeoplePickerViewModel> SearchUsersByKeyword(PeoplePickerViewModel obj)
        {
            List<PeoplePickerViewModel> lst = new List<PeoplePickerViewModel>();
            lst = userRepo.SearchUsersByKeyword(obj);
            return lst;
        }

        private string GetCurrentUserDisplayName()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.DisplayName : "";
        }

        private string GetCurrentUserLoginID()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.LoginID : "";
        }

        private int GetCurrentUserUnitID()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.Unit.UnitID : 0;
        }

        private string GetCurrentUserUnitName()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.Unit.UnitName : "";
        }

        private string GetCurrentUserEmail()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.Email : "";
        }

        private string GetUPTimeStamp()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? string.Format("{0}_{1}", user.LoginID, user.LastUpdatedDateTime.ToString("yyyy-MM-dd HH:mm:ss")) : "";
        }

        private List<RoleInfo> GetCurrentUserRoleGroups()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.RoleGroups : null;
        }

        private List<string> GetCurrentUserRoles()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.RolesObj.Select(a => a.RoleCode.ToString()).ToList() : null;
        }

        private WorkflowUserViewModel GetCurrentUserManager()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.Manager : null;
        }

        private string GetCurrentAuthenticatedLoginID()
        {
            //return GetDemoUser();

            //Uncomment  for windows/basic authentication
            return HttpContext.Current.User.Identity.Name;
        }

        private string GetDemoUser()
        {
            // demo
            var browser = HttpContext.Current.Request.Browser;
            //var userAgent = HttpContext.Current.Request.UserAgent;
            //var browser = new HttpBrowserCapabilities { Capabilities = new Hashtable { { string.Empty, userAgent } } };
            //var factory = new BrowserCapabilitiesFactory();
            //factory.ConfigureBrowserCapabilities(new NameValueCollection(), browser);
            string strUser;
            //strUser = HttpContext.Current.Request.Headers["DemoUser"].ToString();
            if (browser.Id.ToUpper() == "CHROME")
            {

                if (HttpContext.Current.Request.UserAgent.Contains("Edge"))
                {
                    //strUser = "Kaunter Agent";
                    strUser = @"hasil\farisalif";
                }
                else
                {
                    //strUser = "HCL Agent";
                    strUser = @"hasil\pikyee_isat";
                }
                //if (Request.Cookies.Count > 1)
                //    strUser = "HCL Agent";
                //else     // Private mode
                //    strUser = "Kaunter Agent";
            }
            else if (browser.Browser.ToUpper() == "FIREFOX")
            {
                strUser = @"hasil\farisalif";
            }
            else if (browser.Browser.ToUpper() == "INTERNETEXPLORER")
            {
                strUser = @"hasil\yinying_isat";
            }
            else
            {
                strUser = @"hasil\yinying_isat";
            }

            return strUser;
        }

        private string GetUserEmailByLoginID(string LoginName)
        {
            UserInfoViewModel user = userRepo.GetUserEmailByLoginID(LoginName);

            return user != null ? user.Email : "";
        }

        public List<BranchListViewModel> GetBranchByHierarchy(int intUnitID)
        {
            return userRepo.GetBranchByHierarchy(intUnitID);
        }
        private List<TindakanSusulanViewModel> GetCurrentUserRoleTindakanSusulan()
        {
            UserInfoViewModel user = GetUserByLoginID();

            return user != null ? user.RoleTindakanSusulan : null;
        }

        public DropdownViewModel GetUserGroupHierarcyOptions()
        {
            DropdownViewModel ddlVM = new DropdownViewModel();

            ddlVM.WorkflowAssignToSeksyenOption = AdminService.Units.Where(x => x.HierarchyType == (int)Constant.LookupParamSys.HierarchyTypeSeksyen && x.IsActive == true)
                .Select(x => new WorkflowUserViewModel
                {
                    ID = x.UnitID.ToString(),
                    DisplayName = x.UnitName,
                    ParentUnitID = x.ParentUnitID,
                    AdditionalInfo = x.AdditionalInfo,
                    HierarchyType = x.HierarchyType,
                    ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                    AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                    SeksyenID = x.SeksyenID,
                    JabatanID = x.JabatanID,
                    CawanganID = x.CawanganID
                }).OrderBy(x => x.DisplayName).ToList();

            ddlVM.WorkflowAssignToJabatanOption = AdminService.Units.Where(x => x.HierarchyType == (int)Constant.LookupParamSys.HierarchyTypeJabatan && x.IsActive == true)
                .Select(x => new WorkflowUserViewModel
                {
                    ID = x.UnitID.ToString(),
                    DisplayName = x.UnitName,
                    ParentUnitID = x.ParentUnitID,
                    AdditionalInfo = x.AdditionalInfo,
                    HierarchyType = x.HierarchyType,
                    ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                    AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                    SeksyenID = x.SeksyenID,
                    JabatanID = x.JabatanID,
                    CawanganID = x.CawanganID
                }).OrderBy(x => x.DisplayName).ToList();

            ddlVM.WorkflowAssignToCawanganOption = AdminService.Units.Where(x => x.HierarchyType == (int)Constant.LookupParamSys.HierarchyTypeCawangan && x.IsActive == true)
                .Select(x => new WorkflowUserViewModel
                {
                    ID = x.UnitID.ToString(),
                    DisplayName = x.UnitName,
                    ParentUnitID = x.ParentUnitID,
                    AdditionalInfo = x.AdditionalInfo,
                    HierarchyType = x.HierarchyType,
                    ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                    AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                    SeksyenID = x.SeksyenID,
                    JabatanID = x.JabatanID,
                    CawanganID = x.CawanganID
                }).OrderBy(x => x.DisplayName).ToList();

            ddlVM.WorkflowAssignToUnitOption = AdminService.Units.Where(x => x.HierarchyType == (int)Constant.LookupParamSys.HierarchyTypeUnit && x.IsActive == true)
                .Select(x => new WorkflowUserViewModel
                {
                    ID = x.UnitID.ToString(),
                    DisplayName = x.UnitName,
                    ParentUnitID = x.ParentUnitID,
                    AdditionalInfo = x.AdditionalInfo,
                    HierarchyType = x.HierarchyType,
                    ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                    AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                    SeksyenID = x.SeksyenID,
                    JabatanID = x.JabatanID,
                    CawanganID = x.CawanganID
                }).OrderBy(x => x.DisplayName).ToList();

            //Chew 03-01-2020 
            ddlVM.UserJawatan = AdminService.LookupParams.Where(x => x.LookupCode == Constant.LookupCode.UsrJawatan && x.IsActive == true)
                .Select(x => new DropdownDetailViewModel
                {
                    Value = x.LookupParamID,
                    Text = x.ParamDesc,

                }).OrderBy(x => x.Value).ToList();

            ddlVM.FunctionalRoleOptions = AdminService.FunctionalRole;

            ddlVM.UserWorkflowStatusOption = AdminService.LookupParamSys.Where(x => x.LookupCode == "UserWorkflowStatus" && x.LookupParamSysID !=67)
            .Select(x => new DropdownDetailViewModel
            {
                Value = x.LookupParamSysID,
                Text = x.ParamDesc,
            }).ToList();

            ddlVM.UserJenisPermohonanOption = AdminService.LookupParamSys.Where(x => x.LookupCode == "JenisPermohonanCode")
              .Select(x => new DropdownDetailViewModel
              {
                  Value = x.LookupParamSysID,
                  Text = x.ParamDesc,
              }).ToList();


            return ddlVM;

        }


        public List<WorkflowUserViewModel> SearchUserByUnitID(int iUnitID)
        {
            List<WorkflowUserViewModel> lstUser = userRepo.SearchUserByUnitID(iUnitID);


            return lstUser;

        }


        public List<WorkflowUserViewModel> SearchUserByName(string strName)
        {
            List<WorkflowUserViewModel> lstUser = userRepo.SearchUserByName(strName);


            return lstUser;

        }

        public List<WorkflowUserViewModel> SearchUnitByName(string strName)
        {
            List<WorkflowUserViewModel> lstUnit = AdminService.Units.Where(x => x.IsActive == true && x.UnitName.ToLower().Contains(strName.ToLower()))
                                                                 .Select(x => new WorkflowUserViewModel
                                                                 {
                                                                     ID = x.UnitID.ToString(),
                                                                     DisplayName = x.UnitName,
                                                                     ParentUnitID = x.ParentUnitID,
                                                                     AdditionalInfo = x.AdditionalInfo,
                                                                     HierarchyType = x.HierarchyType,
                                                                     ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                                                                     AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                                                                     UnitTypeID = x.UnitTypeID,
                                                                     SeksyenID = x.SeksyenID,
                                                                     JabatanID = x.JabatanID,
                                                                     CawanganID = x.CawanganID
                                                                 }).OrderBy(x => x.DisplayName).ToList();

            return lstUnit;

        }
        public List<UserRoleListViewModel> SearchRoleByName(string strName)
        {
            List<UserRoleListViewModel> lstUser = userRepo.SearchRoleByName(strName);


            return lstUser;

        }

        public List<UserProfileViewModel> GetUserProfileList(UserProfilePagedListViewModel paging, out int intCount)
        {
            intCount = 0;
            //List<UserProfileViewModel> lstUser = new List<UserProfileViewModel>() ;
            //lstUser = userRepo.GetAdminUserProfileList();
            //return lstUser;

            DataSet ds = userRepo.GetUserProfileList(paging.SortExpression, paging.PageIndex, paging.Length, paging.UserDislayName, paging.ManagerUserProfileID, paging.UnitID);

            List<UserProfileViewModel> lstUserProfileVM = new List<UserProfileViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstUserProfileVM = userRepo.DataTableToList<UserProfileViewModel>(ds.Tables[0]).ToList();
                if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0)
                    intCount = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());
            }

            return lstUserProfileVM;

        }

        public UserProfileViewModel GetUserProfileDetailsByID(int intUserProfileId)
        {
            UserProfileViewModel lstUser = userRepo.GetUserProfileDetailsByID(intUserProfileId);

            return lstUser;
        }

        public UserProfileUpdateViewModel UpdateUserProfileDetail(UserProfileUpdateViewModel model, out string strDirectManagerEmail)
        {

            List<ChangeHistoryUpdateViewModel> lst = new List<ChangeHistoryUpdateViewModel>();
            UserProfileUpdateViewModel data = new UserProfileUpdateViewModel();
            UserRequestProfileViewModel userRequestmodel = new UserRequestProfileViewModel();
            bool blnIsDeactivated = false;
            strDirectManagerEmail = string.Empty;
            UserProfileViewModel oriUserProfileDetails = GetUserProfileDetailsByID(Convert.ToInt32(model.UserProfile.UserProfileID));

            if (oriUserProfileDetails == null)
            {
                //Get ChangeHistory
                foreach (ChangeHistoryUpdateViewModel changeHistoryItem in model.ChangeHistory)
                {
                    //Get object original value
                    string strOriValue = string.Empty;
                    if (changeHistoryItem.FieldName.IndexOf('_') > 0)
                    {
                        var obj = Utilities.GetPropertyValue(oriUserProfileDetails, changeHistoryItem.FieldName);
                        if (obj != null)
                        {
                            switch (obj.GetType().Name)
                            {
                                case "DateTime":
                                    strOriValue = Convert.ToDateTime(obj).ToString("dd MMM yyyy");
                                    break;
                                case "Boolean":
                                    bool flag = (bool)obj;
                                    if (flag == true)
                                    {
                                        blnIsDeactivated = true;
                                        strOriValue = "Yes";
                                    }
                                    else
                                        strOriValue = "No";
                                    break;
                                case "Decimal":
                                    strOriValue = String.Format("{0:N}", Convert.ToDouble(obj));
                                    break;
                                default:
                                    strOriValue = obj.ToString();
                                    break;
                            }
                        }
                    }
                    else
                    {
                        strOriValue = "";
                    }

                    changeHistoryItem.OldValue = strOriValue;
                    changeHistoryItem.IsChanged = !(changeHistoryItem.OldValue == changeHistoryItem.NewValue);

                }
            }
            else
            {
                //Get ChangeHistory
                foreach (ChangeHistoryUpdateViewModel changeHistoryItem in model.ChangeHistory)
                {
                    //Get object original value
                    string strOriValue = string.Empty;
                    if (changeHistoryItem.FieldName.IndexOf('_') > 0)
                    {
                        var obj = Utilities.GetPropertyValue(oriUserProfileDetails, changeHistoryItem.FieldName);
                        if (obj != null)
                        {
                            switch (obj.GetType().Name)
                            {
                                case "DateTime":
                                    strOriValue = Convert.ToDateTime(obj).ToString("dd MMM yyyy");
                                    break;
                                case "Boolean":
                                    bool flag = (bool)obj;
                                    if (flag == true)
                                    {
                                        blnIsDeactivated = true;
                                        strOriValue = "Yes";
                                    }
                                    else
                                        strOriValue = "No";
                                    break;
                                case "Decimal":
                                    strOriValue = String.Format("{0:N}", Convert.ToDouble(obj));
                                    break;
                                default:
                                    strOriValue = obj.ToString();
                                    break;
                            }
                        }
                    }
                    else
                    {
                        var obj = Utilities.GetPropertyValue(oriUserProfileDetails, changeHistoryItem.FieldName);
                        strOriValue = obj == null ? "" : obj.ToString();
                    }


                    changeHistoryItem.OldValue = strOriValue;

                    changeHistoryItem.IsChanged = !(changeHistoryItem.OldValue == changeHistoryItem.NewValue);

                }

                model.UserProfile.CreatedBy = oriUserProfileDetails.CreatedBy;
                model.UserProfile.CreatedDateTime = oriUserProfileDetails.CreatedDateTime;
            }

            if (model.UserProfile.ActiveCondition == 64 || model.UserProfile.ActiveCondition == 65 || model.UserProfile.ActiveCondition == 66)
            {
                model.UserProfile.IsActive = false;
            }

            using (var scope = new TransactionScope(TransactionScopeOption.Required))
            {
                //Check if user change default unit or not
                if (oriUserProfileDetails != null)
                {
                    if (oriUserProfileDetails.UnitID != model.UserProfile.UnitID)
                    {
                        int OriUnitID = oriUserProfileDetails.UserFunctionRoles.Select(x => x.UnitID).FirstOrDefault();
                        userRepo.DeleteAllRoleForDefaultUnitRole(model.UserProfile, OriUnitID);
                        userRequestmodel = userRepo.UpdateEscalateCaseToDirectManagerInUserProfile(oriUserProfileDetails.UserProfileID,model.UserProfile.UnitID);
                        if(userRequestmodel !=null)
                        {
                            if (userRequestmodel.ManagerUserProfileID > 0)
                            {
                                strDirectManagerEmail = userRequestmodel.Email;

                            }
                        }
                       
                    }
                }

                    data.UserProfile = userRepo.UpdateUserProfileDetail(model.UserProfile);
                if (data.UserProfile.UserProfileID > 0)
                {
                    // Remove current Default Role from db
                    if (model.UserProfile.RemoveDefaultRolesID != null && model.UserProfile.RemoveDefaultRolesID !="0")
                    {
                        userRepo.DeleteRolesForUser(data.UserProfile, model.UserProfile.RemoveDefaultRolesID, true);
                    }

                    //Delete additional Unit and roles if the user remove current additional unit.
                    if (model.UserProfile.RemoveUnitAndRoles != null)
                    {
                        userRepo.DeleteUnitAndRole(data.UserProfile, model.UserProfile.RemoveUnitAndRoles);
                    }

                    // Add Default roles And Unit to role member ID
                    string multipleRole = model.UserProfile.DefaultRolesID;
                    if (multipleRole != null)
                    {
                        int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                        foreach (var i in result)
                        {
                            userRepo.UpdateRolesForUser(data.UserProfile, i, true);
                        }
                    }

                    //If have addition roles and unit
                    //if(model.UserProfile.AdditionalUnitID > 0 && model.UserProfile.AdditionalRolesID !=null)
                    if (model.UserProfile.UserAdditionalUnitAndRoles != null)
                    {
                        // If add new unit and peranan
                        if (model.UserProfile.UserAdditionalUnitAndRoles.Count > 0)
                        {
                            foreach (var a in model.UserProfile.UserAdditionalUnitAndRoles)
                            {
                                data.UserProfile.AdditionalUnitID = Convert.ToInt32(a.ID);
                                data.UserProfile.ManagerUserProfileID = Convert.ToInt64(a.ManagerId);
                                foreach (var b in a.UnitRoleFunctionalID)
                                {
                                    multipleRole = b.FunctionalRoleID.ToString();
                                    if (multipleRole != null)
                                    {
                                        int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                                        foreach (var i in result)
                                        {
                                            userRepo.UpdateRolesForUser(data.UserProfile, i, false);
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            // if add additional roles for that unit
                            if (model.UserProfile.AdditionalRolesID != null)
                            {
                                data.UserProfile.AdditionalUnitID = model.UserProfile.AdditionalUnitID;
                                multipleRole = model.UserProfile.AdditionalRolesID.ToString();
                                data.UserProfile.ManagerUserProfileID = model.UserProfile.AdditionalManagerID;
                                if (multipleRole != null)
                                {
                                    int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                                    foreach (var i in result)
                                    {
                                        userRepo.UpdateRolesForUser(data.UserProfile, i, false);
                                    }
                                }

                            }

                        }

                        // Remove current Default Role from db
                        if (model.UserProfile.RemoveAdditionalRolesID != null)
                        {
                            data.UserProfile.RemoveAdditionalUnitID = model.UserProfile.RemoveAdditionalUnitID;
                            userRepo.DeleteRolesForUser(data.UserProfile, model.UserProfile.RemoveAdditionalRolesID, false);
                        }
                    }

                    //Remove Manager for Unit Tambahan
                    if (model.UserProfile.RemoveUnitAdditionManager != null)
                    {
                        if (model.UserProfile.RemoveUnitAdditionManager.Count > 0)
                        {
                            long UserProfileID = oriUserProfileDetails.UserProfileID;

                            foreach (var a in model.UserProfile.RemoveUnitAdditionManager)
                            {
                                int lgManagerUserProfileID = Convert.ToInt32(a.ManagerId);
                                int intManagerUnitID = Convert.ToInt32(a.ID);  //UnitID 
                                userRepo.UpdateAdditionUnitMangerIDByID(lgManagerUserProfileID, intManagerUnitID, UserProfileID,true); //true is from user profile screen

                            }
                        }
                    }

                    //Update Manager For Unit Tambahan
                    if (model.UserProfile.ChangeUnitAdditionManager != null)
                    {
                        if (model.UserProfile.ChangeUnitAdditionManager.Count > 0)
                        {
                            long UserProfileID = oriUserProfileDetails.UserProfileID;

                            foreach (var a in model.UserProfile.ChangeUnitAdditionManager)
                            {
                                int lgManagerUserProfileID = Convert.ToInt32(a.AdditionUnitManagerId);
                                int intManagerUnitID = Convert.ToInt32(a.ID);  //UnitID 
                                userRepo.UpdateAdditionUnitMangerIDByID(lgManagerUserProfileID, intManagerUnitID, UserProfileID,true);  //true is from user profile screen

                            }
                        }
                    }

                    //Check User Active Condition
                    if (model.UserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Active)
                    {
                        model.UserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Active);
                    }
                    else if (model.UserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Inactive)
                    {
                        model.UserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Inactive);
                    }
                    else if (model.UserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Dormant)
                    {
                        model.UserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Dormant);
                    }
                    else
                    {
                        model.UserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Expiry);
                    }

                    UserActiveConditionViewModel OriUserActiveCondition = userRepo.GetExistingUserActiveCondition(data.UserProfile.UserProfileID);

                    if (OriUserActiveCondition != null)
                    {
                        model.UserProfile.ActivePeriodID = OriUserActiveCondition.ActivePeriodID;
                        userRepo.UpdateUserProfileActiveCondition(model.UserProfile);
                    }
                    else
                    {
                        model.UserProfile.UserProfileID = data.UserProfile.UserProfileID;
                        userRepo.UpdateUserProfileActiveCondition(model.UserProfile);
                    }

                   UserRequestProfileViewModel objUserRequestModel = userRepo.UpdateWFProfileDetailByUserProfileID(model.UserProfile.UserProfileID);
                    if(objUserRequestModel.WFUserProfileID > 0)
                    {
                        WFUserFunctionalRoleMember objWFUserRoleMember = userRepo.GetExistingWFUserFunctionalRoleMember(objUserRequestModel.WFUserProfileID);
                        if(objWFUserRoleMember !=null)
                        {
                            objUserRequestModel.WFUserFunctionalRoleMemberID = objWFUserRoleMember.FunctionalRoleMemberID;
                            userRepo.UpdateWFUserFunctionalRoleMemberByID(objUserRequestModel, model.UserProfile.UserProfileID);
                        }
                        else
                        {
                            objUserRequestModel.WFUserFunctionalRoleMemberID = 0;
                            userRepo.UpdateWFUserFunctionalRoleMemberByID(objUserRequestModel, model.UserProfile.UserProfileID);
                        }
                         
                        UserWFActiveConditionViewModel objUserActiveCondition = userRepo.GetExistingWFUserActiveCondition(objUserRequestModel.WFUserProfileID);
                        if(objUserActiveCondition !=null)
                        {
                            objUserRequestModel.WFActivePeriodID = objUserActiveCondition.WFActivePeriodID;
                            userRepo.UpdateWFUserActiveConditionByID(objUserRequestModel, model.UserProfile.UserProfileID);
                        }
                        else
                        {
                            objUserRequestModel.WFActivePeriodID = 0;
                            userRepo.UpdateWFUserActiveConditionByID(objUserRequestModel, model.UserProfile.UserProfileID);
                        }
                    }

                }
                scope.Complete();
            }

            if(data.UserProfile.UserProfileID > 0)
            {
                UserRequestProfileViewModel oriWFUserProfileDetails = new UserRequestProfileViewModel();
                oriWFUserProfileDetails.UserProfileID = data.UserProfile.UserProfileID;
                oriWFUserProfileDetails.LoginID = data.UserProfile.LoginID;
                oriWFUserProfileDetails.Email = data.UserProfile.Email;
                oriWFUserProfileDetails.DisplayName = data.UserProfile.DisplayName;

                //Add and Remove Reviewer For Main Unit.
                string FunctionalTaskCode = Constant.Authentication.Administration.ReviewUserProfileCreationUpdate;
                oriWFUserProfileDetails.UnitID = data.UserProfile.UnitID;
                UserRequestProfileViewModel WFNewReviewerUser = userRepo.GetNewAddedRevieobjUserwerByUser(oriWFUserProfileDetails, FunctionalTaskCode);
                if (WFNewReviewerUser != null)
                {
                    List<UserWorkFlowViewModel> oriUserwfModel = new List<UserWorkFlowViewModel>();
                    bool IsDelete = false;
                    int WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                    oriUserwfModel = userRepo.GetExistingUserWorkFlowByID(oriWFUserProfileDetails, WFStatusID, IsDelete);
                    if (oriUserwfModel != null && oriUserwfModel.Count > 0)
                    {
                        UserWorkFlowViewModel oriAssignUserWfModel = new UserWorkFlowViewModel();

                        foreach (UserWorkFlowViewModel objOriWFUser in oriUserwfModel)
                        {
                            oriAssignUserWfModel = userRepo.GetExistingAssignUserByWorkFlowByID(objOriWFUser.WorkflowID, oriWFUserProfileDetails.LoginID);
                            if (oriAssignUserWfModel == null)
                            {
                                UserWorkFlowViewModel userWFModel = new UserWorkFlowViewModel();
                                userWFModel.WorkflowID = objOriWFUser.WorkflowID;
                                userWFModel.AssignToLogin = oriWFUserProfileDetails.LoginID;
                                userWFModel.AssignToName = oriWFUserProfileDetails.DisplayName;
                                userWFModel.AssignToEmail = oriWFUserProfileDetails.Email;
                                userWFModel.CreatedBy = Constant.System.Name;
                                userWFModel.CreatedDateTime = DateTime.Now;
                                userWFModel.LastUpdatedBy = Constant.System.Name;
                                userWFModel.LastUpdatedDateTime = DateTime.Now;

                                userRepo.InsertUserWorkflowAssignUser(userWFModel);
                            }
                        }
                    }
                }
                else
                {
                    bool IsDelete = true;
                    List<UserWorkFlowViewModel> oriUserwfModel = new List<UserWorkFlowViewModel>();
                    int WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                    oriUserwfModel = userRepo.GetExistingUserWorkFlowByID(oriWFUserProfileDetails, WFStatusID, IsDelete);
                    if (oriUserwfModel != null && oriUserwfModel.Count > 0)
                    {
                        UserWorkFlowViewModel oriAssignUserWfModel = new UserWorkFlowViewModel();

                        foreach (UserWorkFlowViewModel objOriWFUser in oriUserwfModel)
                        {
                            oriAssignUserWfModel = userRepo.GetExistingAssignUserByWorkFlowByID(objOriWFUser.WorkflowID, oriWFUserProfileDetails.LoginID);
                            if (oriAssignUserWfModel != null)
                            {
                                UserWorkFlowViewModel userWFModel = new UserWorkFlowViewModel();
                                userWFModel.WorkflowID = objOriWFUser.WorkflowID;
                                userWFModel.AssignToLogin = oriWFUserProfileDetails.LoginID;
                                userWFModel.CreatedBy = Constant.System.Name;
                                userWFModel.LastUpdatedBy = Constant.System.Name;

                                userRepo.DeleteUserWorkflowAssignUser(userWFModel);
                            }

                        }

                    }
                }

                //Add and Remove Reviewer Roles in Additional Unit
                FunctionalTaskCode = Constant.Authentication.Administration.ReviewUserProfileCreationUpdate;
                List<UserRequestProfileViewModel> lstAdditionalUnitID = userRepo.GetNewAddedReviewerForAdditionUnitByUser(oriWFUserProfileDetails, FunctionalTaskCode);
                if (lstAdditionalUnitID != null && lstAdditionalUnitID.Count > 0)
                {
                    foreach (UserRequestProfileViewModel objReviewerUser in lstAdditionalUnitID)
                    {
                        oriWFUserProfileDetails.UnitID = objReviewerUser.AdditionalUnitID;
                        WFNewReviewerUser = userRepo.GetNewAddedRevieobjUserwerByUser(oriWFUserProfileDetails, FunctionalTaskCode);
                        if (WFNewReviewerUser != null)
                        {
                            List<UserWorkFlowViewModel> oriUserwfModel = new List<UserWorkFlowViewModel>();
                            bool IsDelete = false;

                            int WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                            oriUserwfModel = userRepo.GetExistingUserWorkFlowByID(oriWFUserProfileDetails, WFStatusID, IsDelete);
                            if (oriUserwfModel != null && oriUserwfModel.Count > 0)
                            {
                                UserWorkFlowViewModel oriAssignUserWfModel = new UserWorkFlowViewModel();

                                foreach (UserWorkFlowViewModel objOriWFUser in oriUserwfModel)
                                {
                                    oriAssignUserWfModel = userRepo.GetExistingAssignUserByWorkFlowByID(objOriWFUser.WorkflowID, oriWFUserProfileDetails.LoginID);
                                    if (oriAssignUserWfModel == null)
                                    {
                                        UserWorkFlowViewModel userWFModel = new UserWorkFlowViewModel();
                                        userWFModel.WorkflowID = objOriWFUser.WorkflowID;
                                        userWFModel.AssignToLogin = oriWFUserProfileDetails.LoginID;
                                        userWFModel.AssignToName = oriWFUserProfileDetails.DisplayName;
                                        userWFModel.AssignToEmail = oriWFUserProfileDetails.Email;
                                        userWFModel.CreatedBy = Constant.System.Name;
                                        userWFModel.CreatedDateTime = DateTime.Now;
                                        userWFModel.LastUpdatedBy = Constant.System.Name;
                                        userWFModel.LastUpdatedDateTime = DateTime.Now;

                                        userRepo.InsertUserWorkflowAssignUser(userWFModel);
                                    }
                                }
                            }
                        }
                        else
                        {
                            bool IsDelete = true;
                            List<UserWorkFlowViewModel> oriUserwfModel = new List<UserWorkFlowViewModel>();

                            int WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                            oriUserwfModel = userRepo.GetExistingUserWorkFlowByID(oriWFUserProfileDetails, WFStatusID, IsDelete);
                            if (oriUserwfModel != null && oriUserwfModel.Count > 0)
                            {
                                UserWorkFlowViewModel oriAssignUserWfModel = new UserWorkFlowViewModel();

                                foreach (UserWorkFlowViewModel objOriWFUser in oriUserwfModel)
                                {
                                    oriAssignUserWfModel = userRepo.GetExistingAssignUserByWorkFlowByID(objOriWFUser.WorkflowID, oriWFUserProfileDetails.LoginID);
                                    if (oriAssignUserWfModel != null)
                                    {
                                        UserWorkFlowViewModel userWFModel = new UserWorkFlowViewModel();
                                        userWFModel.WorkflowID = objOriWFUser.WorkflowID;
                                        userWFModel.AssignToLogin = oriWFUserProfileDetails.LoginID;
                                        userWFModel.CreatedBy = Constant.System.Name;
                                        userWFModel.LastUpdatedBy = Constant.System.Name;

                                        userRepo.DeleteUserWorkflowAssignUser(userWFModel);
                                    }

                                }

                            }
                        }
                    }

                    //Remove Unit Tambahan For Reviewer Roles
                    if (model.UserProfile.RemoveUnitAndRoles != null)
                    {
                        bool IsDelete = true;
                        List<UserWorkFlowViewModel> oriUserwfModel = new List<UserWorkFlowViewModel>();

                        int[] intAddUnitID = model.UserProfile.RemoveUnitAndRoles.Split(",").Select(int.Parse).ToArray();
                        foreach (var unitID in intAddUnitID)
                        {
                            oriWFUserProfileDetails.UnitID = unitID;
                            int WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                            oriUserwfModel = userRepo.GetExistingUserWorkFlowByID(oriWFUserProfileDetails, WFStatusID, IsDelete);
                            if (oriUserwfModel != null && oriUserwfModel.Count > 0)
                            {
                                UserWorkFlowViewModel oriAssignUserWfModel = new UserWorkFlowViewModel();

                                foreach (UserWorkFlowViewModel objOriWFUser in oriUserwfModel)
                                {
                                    oriAssignUserWfModel = userRepo.GetExistingAssignUserByWorkFlowByID(objOriWFUser.WorkflowID, oriWFUserProfileDetails.LoginID);
                                    if (oriAssignUserWfModel != null)
                                    {
                                        UserWorkFlowViewModel userWFModel = new UserWorkFlowViewModel();
                                        userWFModel.WorkflowID = objOriWFUser.WorkflowID;
                                        userWFModel.AssignToLogin = oriWFUserProfileDetails.LoginID;
                                        userWFModel.CreatedBy = Constant.System.Name;
                                        userWFModel.LastUpdatedBy = Constant.System.Name;

                                        userRepo.DeleteUserWorkflowAssignUser(userWFModel);
                                    }

                                }

                            }
                        }
                    }
                }
                else
                {
                    //Remove Unit Tambahan For Reviewer Roles if no Additional unit left
                    if (model.UserProfile.RemoveUnitAndRoles !=null)
                    {
                        bool IsDelete = true;
                        List<UserWorkFlowViewModel> oriUserwfModel = new List<UserWorkFlowViewModel>();

                        int[] intAddUnitID = model.UserProfile.RemoveUnitAndRoles.Split(",").Select(int.Parse).ToArray();
                        foreach (var unitID in intAddUnitID)
                        {
                            oriWFUserProfileDetails.UnitID = unitID;
                            int WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                            oriUserwfModel = userRepo.GetExistingUserWorkFlowByID(oriWFUserProfileDetails, WFStatusID, IsDelete);
                            if (oriUserwfModel != null && oriUserwfModel.Count > 0)
                            {
                                UserWorkFlowViewModel oriAssignUserWfModel = new UserWorkFlowViewModel();

                                foreach (UserWorkFlowViewModel objOriWFUser in oriUserwfModel)
                                {
                                    oriAssignUserWfModel = userRepo.GetExistingAssignUserByWorkFlowByID(objOriWFUser.WorkflowID, oriWFUserProfileDetails.LoginID);
                                    if (oriAssignUserWfModel != null)
                                    {
                                        UserWorkFlowViewModel userWFModel = new UserWorkFlowViewModel();
                                        userWFModel.WorkflowID = objOriWFUser.WorkflowID;
                                        userWFModel.AssignToLogin = oriWFUserProfileDetails.LoginID;
                                        userWFModel.CreatedBy = Constant.System.Name;
                                        userWFModel.LastUpdatedBy = Constant.System.Name;

                                        userRepo.DeleteUserWorkflowAssignUser(userWFModel);
                                    }

                                }

                            }
                        }
                    }
      
                }

            }
           
            //Check user still in inactive,dormant and active and will assign back to previous manager.
            if (model.UserProfile.ActiveCondition == 64 || model.UserProfile.ActiveCondition == 65 || model.UserProfile.ActiveCondition == 66)
            {
                userRequestmodel = userRepo.UpdateEscalateCaseToDirectManagerInUserProfile(oriUserProfileDetails.UserProfileID, model.UserProfile.UnitID);
                if (userRequestmodel != null)
                {
                    if (userRequestmodel.ManagerUserProfileID > 0)
                    {
                        strDirectManagerEmail = userRequestmodel.Email;

                    }
                }
            }

            // Update user in cache
            if (data?.UserProfile?.UserProfileID > 0)
            {
                if (blnIsDeactivated && model.UserProfile.UserProfileID != 0)
                    RemoveUserCacheByLoginID(data.UserProfile.LoginID);
                else if (!blnIsDeactivated && model.UserProfile.UserProfileID != 0)
                    UpdateUserCacheByLoginID(data.UserProfile.LoginID);
            }
            data.ChangeHistory = model.ChangeHistory;

            return data;
        }
        public List<UnitTypeViewModel> SearchUnitTypeByName(string strName)
        {
            List<UnitTypeViewModel> lstUser = userRepo.SearchUnitTypeByName(strName);


            return lstUser;

        }

        public UserRequestProfileViewModel GetUserRequestProfileDetailByID(int intWFUserProfileId, UserInfoViewModel currentUser = null)
        {
            UserRequestProfileViewModel lstUser = userRepo.GetUserRequestProfileDetailByID(intWFUserProfileId);
            if (lstUser != null)
            {
                if (lstUser.UserWorkFlow != null)
                {
                    var objWfUser = lstUser.UserWorkFlow.wfUser.Where(s => s.AssignToLogin == currentUser.LoginID).FirstOrDefault();
                    if (objWfUser != null)
                    {
                        if (objWfUser.AssignToLogin.ToLower() == currentUser.LoginID.ToLower())
                        {
                            lstUser.IsCurrentUserLogin = true;
                            lstUser.IsOtherUserLogin = false;
                        }
                        else if (objWfUser.AssignToLogin.ToLower() != currentUser.LoginID.ToLower() &&
                                  objWfUser.AssignBy.ToLower() != currentUser.LoginID.ToLower())
                        {
                            lstUser.IsOtherUserLogin = true;
                        }
                    }
                    else
                    {
                        if (lstUser.UserWorkFlow.AssignBy.ToLower() == currentUser.LoginID.ToLower())
                        {
                            lstUser.IsOtherUserLogin = false;
                        }
                        else
                        {
                            lstUser.IsOtherUserLogin = true;
                        }
                    }
                }

            }
            else
            {
                throw new NotFoundException("User Request is deleted or not found!");
            }

            return lstUser;
        }

        public UserRequestProfileViewModel GetExistingUserRequestProfileDetailByID(int intWFUserProfileId, UserInfoViewModel currentUser = null)
        {
            UserRequestProfileViewModel lstUser = userRepo.GetUserRequestProfileDetailByID(intWFUserProfileId);
            if (lstUser != null)
            {
                if (lstUser.UserWorkFlow != null)
                {
                    var objWfUser = lstUser.UserWorkFlow.wfUser.Where(s => s.AssignToLogin == currentUser.LoginID).FirstOrDefault();
                    if (objWfUser != null)
                    {
                        if (objWfUser.AssignToLogin.ToLower() == currentUser.LoginID.ToLower())
                        {
                            lstUser.IsCurrentUserLogin = true;
                            lstUser.IsOtherUserLogin = false;
                        }
                        else if (objWfUser.AssignToLogin.ToLower() != currentUser.LoginID.ToLower() &&
                                  objWfUser.AssignBy.ToLower() != currentUser.LoginID.ToLower())
                        {
                            lstUser.IsOtherUserLogin = true;
                        }
                    }
                    else
                    {
                        if (lstUser.UserWorkFlow.AssignBy.ToLower() == currentUser.LoginID.ToLower())
                        {
                            lstUser.IsOtherUserLogin = false;
                        }
                        else
                        {
                            lstUser.IsOtherUserLogin = true;
                        }
                    }
                }

            }

            return lstUser;
        }

        public UserRequestProfileUpdateViewModel UpdateWorkflowUserProfileDetail(UserRequestProfileUpdateViewModel model, out string strAssignToEmail, UserInfoViewModel currentUser = null)
        {
            List<ChangeHistoryUpdateViewModel> lst = new List<ChangeHistoryUpdateViewModel>();
            UserRequestProfileUpdateViewModel data = new UserRequestProfileUpdateViewModel();
            UserProfileViewModel oriUserProfileDetails = new UserProfileViewModel();
            bool blnIsDeactivated = false;
            strAssignToEmail = string.Empty;
            UserRequestProfileViewModel oriWFUserProfileDetails = GetExistingUserRequestProfileDetailByID(Convert.ToInt32(model.WFUserProfile.WFUserProfileID), currentUser);
            //UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
            UserWorkFlowViewModel userwfModel = new UserWorkFlowViewModel();
            if (oriWFUserProfileDetails == null)
            {
                //Get ChangeHistory
                foreach (ChangeHistoryUpdateViewModel changeHistoryItem in model.ChangeHistory)
                {
                    //Get object original value
                    string strOriValue = string.Empty;
                    if (changeHistoryItem.FieldName.IndexOf('_') > 0)
                    {
                        var obj = Utilities.GetPropertyValue(oriWFUserProfileDetails, changeHistoryItem.FieldName);
                        if (obj != null)
                        {
                            switch (obj.GetType().Name)
                            {
                                case "DateTime":
                                    strOriValue = Convert.ToDateTime(obj).ToString("dd MMM yyyy");
                                    break;
                                case "Boolean":
                                    bool flag = (bool)obj;
                                    if (flag == true)
                                    {
                                        blnIsDeactivated = true;
                                        strOriValue = "Yes";
                                    }
                                    else
                                        strOriValue = "No";
                                    break;
                                case "Decimal":
                                    strOriValue = String.Format("{0:N}", Convert.ToDouble(obj));
                                    break;
                                default:
                                    strOriValue = obj.ToString();
                                    break;
                            }
                        }
                    }
                    else
                    {
                        strOriValue = "";
                    }

                    changeHistoryItem.OldValue = strOriValue;
                    changeHistoryItem.IsChanged = !(changeHistoryItem.OldValue == changeHistoryItem.NewValue);

                }

                model.WFUserProfile.JenisPermohonanTypeID = (int)Constant.UserWorkflow.UserJenisPermohonanType.Baru;
            }
            else
            {
                //Get ChangeHistory
                foreach (ChangeHistoryUpdateViewModel changeHistoryItem in model.ChangeHistory)
                {
                    //Get object original value
                    string strOriValue = string.Empty;
                    if (changeHistoryItem.FieldName.IndexOf('_') > 0)
                    {
                        var obj = Utilities.GetPropertyValue(oriWFUserProfileDetails, changeHistoryItem.FieldName);
                        if (obj != null)
                        {
                            switch (obj.GetType().Name)
                            {
                                case "DateTime":
                                    strOriValue = Convert.ToDateTime(obj).ToString("dd MMM yyyy");
                                    break;
                                case "Boolean":
                                    bool flag = (bool)obj;
                                    if (flag == true)
                                    {
                                        blnIsDeactivated = true;
                                        strOriValue = "Yes";
                                    }
                                    else
                                        strOriValue = "No";
                                    break;
                                case "Decimal":
                                    strOriValue = String.Format("{0:N}", Convert.ToDouble(obj));
                                    break;
                                default:
                                    strOriValue = obj.ToString();
                                    break;
                            }
                        }
                    }
                    else
                    {
                        var obj = Utilities.GetPropertyValue(oriWFUserProfileDetails, changeHistoryItem.FieldName);
                        strOriValue = obj == null ? "" : obj.ToString();
                    }


                    changeHistoryItem.OldValue = strOriValue;

                    changeHistoryItem.IsChanged = !(changeHistoryItem.OldValue == changeHistoryItem.NewValue);

                }

                model.WFUserProfile.CreatedBy = oriWFUserProfileDetails.CreatedBy;
                model.WFUserProfile.CreatedByName = oriWFUserProfileDetails.CreatedByName;
                model.WFUserProfile.WFStatusID = oriWFUserProfileDetails.WFStatusID;
                model.WFUserProfile.WFStatusDesc = oriWFUserProfileDetails.WFStatusDesc;

                if (oriWFUserProfileDetails.CreatedByEmail != null)
                {
                    model.WFUserProfile.CreatedByEmail = oriWFUserProfileDetails.CreatedByEmail;
                }
                else
                {
                    model.WFUserProfile.CreatedByEmail = currentUser.Email;
                }

                if (oriWFUserProfileDetails.CreatedByName != null)
                {
                    model.WFUserProfile.CreatedByName = oriWFUserProfileDetails.CreatedByName;
                }
                else
                {
                    model.WFUserProfile.CreatedByName = currentUser.DisplayName;
                }

                model.WFUserProfile.CreatedDateTime = oriWFUserProfileDetails.CreatedDateTime;
                if (oriWFUserProfileDetails.ReviewBy != null && oriWFUserProfileDetails.ReviewByName != null && oriWFUserProfileDetails.ReviewByEmail != null
                    && oriWFUserProfileDetails.ReviewedDateTime != null)
                {
                    model.WFUserProfile.ReviewBy = oriWFUserProfileDetails.ReviewBy;
                    model.WFUserProfile.ReviewByName = oriWFUserProfileDetails.ReviewByName;
                    model.WFUserProfile.ReviewByEmail = oriWFUserProfileDetails.ReviewByEmail;
                    model.WFUserProfile.ReviewedDateTime = oriWFUserProfileDetails.ReviewedDateTime;
                }

                if(oriWFUserProfileDetails.UserProfileID > 0)
                {
                    model.WFUserProfile.JenisPermohonanTypeID = (int)Constant.UserWorkflow.UserJenisPermohonanType.Kemaskini;
                }
                else
                {
                    model.WFUserProfile.JenisPermohonanTypeID = (int)Constant.UserWorkflow.UserJenisPermohonanType.Baru;
                }
             
            }

            if(oriWFUserProfileDetails !=null)
            {
                if (oriWFUserProfileDetails.UserProfileID != null && oriWFUserProfileDetails.UserProfileID > 0)
                {
                    oriUserProfileDetails = GetUserProfileDetailsByID(Convert.ToInt32(oriWFUserProfileDetails.UserProfileID));
                }

                if (oriUserProfileDetails.ManagerUserProfileID == null && oriWFUserProfileDetails.UserProfileID != null && (model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Inactive || model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Dormant || model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Expiry))
                {
                    data.WFUserProfile = model.WFUserProfile;
                    data.WFUserProfile.WFUserProfileID = -1;
                }
                else
                if (oriUserProfileDetails.ManagerUserProfileID == null && oriWFUserProfileDetails.UserProfileID != null && oriUserProfileDetails.UnitID != model.WFUserProfile.UnitID)
                {
                    data.WFUserProfile = model.WFUserProfile;
                    data.WFUserProfile.WFUserProfileID = -1;
                }
                else
                {
                    using (var scope = new TransactionScope(TransactionScopeOption.Required))
                    {
                        //Check if user change default unit or not
                        if (oriWFUserProfileDetails != null)
                        {
                            if (oriWFUserProfileDetails.UnitID != model.WFUserProfile.UnitID)
                            {
                                int OriUnitID = oriWFUserProfileDetails.UserFunctionRoles.Select(x => x.UnitID).FirstOrDefault();
                                userRepo.DeleteWFAllRoleForDefaultUnitRole(model.WFUserProfile, OriUnitID);
                            }
                        }

                        if(model.WFUserProfile.UserProfileID > 0 || model.WFUserProfile.UserProfileID != null)
                        {
                            if (model.WFUserProfile.WFStatusID == null || model.WFUserProfile.WFStatusID == (int)Constant.UserWorkflow.UserWorkflowStatus.Selesai || model.WFUserProfile.WFStatusID == (int)Constant.UserWorkflow.UserWorkflowStatus.Draft)
                            {
                                if (model.WFUserProfile.IsSendApproval)
                                {
                                    model.WFUserProfile.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Draft;
                                    model.WFUserProfile.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Draft);
                                }
                                else if(model.WFUserProfile.IsSubmitButtonClick && model.WFUserProfile.IsSendApproval == false)
                                {
                                    // Enhancement without JOC Approved
                                    model.WFUserProfile.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Diluluskan;
                                    model.WFUserProfile.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Diluluskan);
                
                                    UserWorkFlowViewModel modelUserWF = new UserWorkFlowViewModel();
                                    modelUserWF.WFUserProfileID = model.WFUserProfile.WFUserProfileID;
                                    modelUserWF.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.User;
                                    modelUserWF.AssignBy = currentUser.LoginID;
                                    modelUserWF.AssignByName = currentUser.DisplayName;
                                    modelUserWF.AssignByEmail = currentUser.Email;
                                    modelUserWF.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Diluluskan;
                                    modelUserWF.DecisionID = (int)Constant.UserWorkflow.UserWorkflowDecision.Approved;
                                    modelUserWF.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Diluluskan);
                                    DateTime now = DateTime.Now;

                                    if (model.WFUserProfile.Remarks != null && model.WFUserProfile.Remarks != "")
                                    {
                                        modelUserWF.ClosedRemarks = Constant.UserWorkflow.UserWFRemarks.ApprovalRemark + " : " + model.WFUserProfile.Remarks;
                                    }
                                    else
                                    {
                                        modelUserWF.ClosedRemarks = Constant.UserWorkflow.UserWFRemarks.ApprovalRemark;
                                    }

                                    modelUserWF.WFPrevStageStatusID = model.WFUserProfile.WFStatusID.Value;

                                    userRepo.UpdateWorkFlowHistoryForApprovedStatus(modelUserWF, now);

                                    userwfModel.WFUserProfileID = oriWFUserProfileDetails.WFUserProfileID;
                                    userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Diluluskan;
                                    userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Diluluskan);
                                    userwfModel.RequestedBy = currentUser.LoginID;
                                    userwfModel.RequestedByName = currentUser.DisplayName;
                                    userwfModel.RequestedByEmail = currentUser.Email;
                                    userwfModel.RequestedDateTime = DateTime.Now;
                                    userwfModel.ReviewBy = "Sistem";
                                    userwfModel.ReviewByName = "Sistem";
                                    userwfModel.ReviewByEmail = "noreply@hasil.gov.my";
                                    userwfModel.ReviewedDateTime = model.WFUserProfile.LastUpdatedDateTime;
                                    userwfModel.ApprovedByName = "Sistem";
                                    userwfModel.ApprovedBy = "Sistem";
                                    userwfModel.ApprovedByEmail = "noreply@hasil.gov.my";
                                    userwfModel.ApprovedDateTime = model.WFUserProfile.LastUpdatedDateTime;
                                    userwfModel.LastUpdatedBy = currentUser.LoginID;
                                    userwfModel.LastUpdatedByEmail = currentUser.Email;
                                    userwfModel.LastUpdatedByName = currentUser.DisplayName;
                                    userwfModel.LastUpdatedDateTime = model.WFUserProfile.LastUpdatedDateTime;

                                    userRepo.UpdateWFUserProfileForAssign(userwfModel);

                                    //Remove Unit Tambahan For Reviewer Roles if no Additional unit left
                                    if (model.WFUserProfile.RemoveUnitAndRoles != null && model.WFUserProfile.RemoveUnitAndRoles != "0")
                                    {
                                        bool IsDelete = true;
                                        List<UserWorkFlowViewModel> oriUserwfModel = new List<UserWorkFlowViewModel>();

                                        int[] intAddUnitID = model.WFUserProfile.RemoveUnitAndRoles.Split(",").Select(int.Parse).ToArray();
                                        foreach (var unitID in intAddUnitID)
                                        {
                                            oriWFUserProfileDetails.UnitID = unitID;
                                            int WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                                            oriUserwfModel = userRepo.GetExistingUserWorkFlowByID(oriWFUserProfileDetails, WFStatusID, IsDelete);
                                            if (oriUserwfModel != null && oriUserwfModel.Count > 0)
                                            {
                                                UserWorkFlowViewModel oriAssignUserWfModel = new UserWorkFlowViewModel();

                                                foreach (UserWorkFlowViewModel objOriWFUser in oriUserwfModel)
                                                {
                                                    oriAssignUserWfModel = userRepo.GetExistingAssignUserByWorkFlowByID(objOriWFUser.WorkflowID, oriWFUserProfileDetails.LoginID);
                                                    if (oriAssignUserWfModel != null)
                                                    {
                                                        UserWorkFlowViewModel userWFModel = new UserWorkFlowViewModel();
                                                        userWFModel.WorkflowID = objOriWFUser.WorkflowID;
                                                        userWFModel.AssignToLogin = oriWFUserProfileDetails.LoginID;
                                                        userWFModel.CreatedBy = Constant.System.Name;
                                                        userWFModel.LastUpdatedBy = Constant.System.Name;

                                                        userRepo.DeleteUserWorkflowAssignUser(userWFModel);
                                                    }

                                                }

                                            }
                                        }
                                    }

                                }
                                else
                                {
                                    model.WFUserProfile.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Draft;
                                    model.WFUserProfile.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Draft);
                                }
                            }
                        }                     

                       data.WFUserProfile = userRepo.UpdateWFUserProfileDetail(model.WFUserProfile);
                        if (data.WFUserProfile.WFUserProfileID > 0)
                        {
                            data.WFUserProfile.CreatedBy = currentUser.LoginID;
                            data.WFUserProfile.CreatedDateTime = DateTime.Now;
                            data.WFUserProfile.CreatedBy = currentUser.LoginID;
                            data.WFUserProfile.LastUpdatedDateTime = DateTime.Now;

                            // Remove current Default Role from db
                            if (model.WFUserProfile.RemoveDefaultRolesID != null)
                            {
                                userRepo.DeleteWFRolesForUser(data.WFUserProfile, model.WFUserProfile.RemoveDefaultRolesID, true);
                            }

                            //Delete additional Unit and roles if the user remove current additional unit.
                            if (model.WFUserProfile.RemoveUnitAndRoles != null)
                            {
                                userRepo.DeleteWFUnitAndRole(data.WFUserProfile, model.WFUserProfile.RemoveUnitAndRoles);
                            }

                            // Add Default roles And Unit to role member ID
                            string multipleRole = model.WFUserProfile.DefaultRolesID;
                            if (multipleRole != null)
                            {
                                int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                                foreach (var i in result)
                                {
                                    userRepo.UpdateWFRolesForUser(data.WFUserProfile, i, true);
                                }
                            }

                            //If have addition roles and unit
                            //if(model.UserProfile.AdditionalUnitID > 0 && model.UserProfile.AdditionalRolesID !=null)
                            if (model.WFUserProfile.UserAdditionalUnitAndRoles != null)
                            {
                                // If add new unit and peranan
                                if (model.WFUserProfile.UserAdditionalUnitAndRoles.Count > 0)
                                {
                                    foreach (var a in model.WFUserProfile.UserAdditionalUnitAndRoles)
                                    {
                                        data.WFUserProfile.AdditionalUnitID = Convert.ToInt32(a.ID);
                                        data.WFUserProfile.ManagerUserProfileID = Convert.ToInt64(a.ManagerId);
                                        foreach (var b in a.UnitRoleFunctionalID)
                                        {
                                            multipleRole = b.FunctionalRoleID.ToString();
                                            if (multipleRole != null)
                                            {
                                                int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                                                foreach (var i in result)
                                                {
                                                    userRepo.UpdateWFRolesForUser(data.WFUserProfile, i, false);
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    // if add additional roles for that unit
                                    if (model.WFUserProfile.AdditionalRolesID != null)
                                    {
                                        data.WFUserProfile.AdditionalUnitID = model.WFUserProfile.AdditionalUnitID;
                                        multipleRole = model.WFUserProfile.AdditionalRolesID.ToString();
                                        data.WFUserProfile.ManagerUserProfileID = model.WFUserProfile.AdditionalManagerID;
                                        if (multipleRole != null)
                                        {
                                            int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                                            foreach (var i in result)
                                            {
                                                userRepo.UpdateWFRolesForUser(data.WFUserProfile, i, false);
                                            }
                                        }

                                    }

                                }

                                // Remove current Role in additional roles and unit from db
                                if (model.WFUserProfile.RemoveAdditionalRolesID != null && model.WFUserProfile.RemoveAdditionalRolesID != "0")
                                {
                                    data.WFUserProfile.RemoveAdditionalUnitID = model.WFUserProfile.RemoveAdditionalUnitID;
                                    userRepo.DeleteWFRolesForUser(data.WFUserProfile, model.WFUserProfile.RemoveAdditionalRolesID, false);
                                }
                            }

                            //Remove Manager for Unit Tambahan
                            if(model.WFUserProfile.RemoveUnitAdditionManager !=null)
                            {
                                if (model.WFUserProfile.RemoveUnitAdditionManager.Count > 0)
                                {
                                    long WFUserProfileID = oriWFUserProfileDetails.WFUserProfileID;

                                    foreach (var a in model.WFUserProfile.RemoveUnitAdditionManager)
                                    {
                                        int lgManagerUserProfileID = Convert.ToInt32(a.ManagerId);
                                        int intManagerUnitID = Convert.ToInt32(a.ID);  //UnitID 
                                        userRepo.UpdateAdditionUnitMangerIDByID(lgManagerUserProfileID, intManagerUnitID, WFUserProfileID,false); //false is from user request screen

                                    }
                                }
                            }

                            //Update Manager For Unit Tambahan
                            if(model.WFUserProfile.ChangeUnitAdditionManager != null)
                            {
                                if(model.WFUserProfile.ChangeUnitAdditionManager.Count > 0)
                                {
                                    long WFUserProfileID = oriWFUserProfileDetails.WFUserProfileID;

                                    foreach (var a in model.WFUserProfile.ChangeUnitAdditionManager)
                                    {
                                        int lgManagerUserProfileID = Convert.ToInt32(a.AdditionUnitManagerId);
                                        int intManagerUnitID = Convert.ToInt32(a.ID);  //UnitID 
                                        userRepo.UpdateAdditionUnitMangerIDByID(lgManagerUserProfileID, intManagerUnitID, WFUserProfileID,false);

                                    }
                                }
                            }

                            //Check User Active Condition
                            if (model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Active)
                            {
                                model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Active);
                            }
                            else if (model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Inactive)
                            {
                                model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Inactive);
                            }
                            else if (model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Dormant)
                            {
                                model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Dormant);
                            }
                            else
                            {
                                model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Expiry);
                            }

                            UserWFActiveConditionViewModel OriWFUserActiveCondition = userRepo.GetExistingWFUserActiveCondition(data.WFUserProfile.WFUserProfileID);

                            if (OriWFUserActiveCondition != null)
                            {
                                model.WFUserProfile.WFActivePeriodID = OriWFUserActiveCondition.WFActivePeriodID;
                                userRepo.UpdateWFUserActiveCondition(model.WFUserProfile);
                            }
                            else
                            {
                                model.WFUserProfile.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                userRepo.UpdateWFUserActiveCondition(model.WFUserProfile);
                            }

                            if(model.WFUserProfile.IsSendApproval)
                            {
                                //Submit For Review button click
                                if (model.WFUserProfile.IsSubmitReviewAction)
                            {
                                UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
                                oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                                if (oriuserwfModel != null)
                                {
                                    if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Draft)
                                    {
                                        oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                        oriuserwfModel.CompletedDate = DateTime.Now;
                                        oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Ditolak);
                                        oriuserwfModel.ClosedRemarks = "";

                                    }

                                    DateTime now = DateTime.Now;
                                    userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                                }

                                //Insert for User Workflow for Review
                                var CurrentUserUnitID = model.WFUserProfile.CurrentUserUnitID;
                                string strFunctionalTaskCode = Constant.Authentication.Administration.ReviewUserProfileCreationUpdate;
                                List<UserWorkFlowViewModel> lstReviewUser = new List<UserWorkFlowViewModel>();
                                var UnitDetail = AdminService.Units.Where(s => s.UnitID == CurrentUserUnitID).FirstOrDefault();
                                if(UnitDetail !=null && UnitDetail.HierarchyType == 37) // check for unit level
                                {
                                    var parentUnitDetail = AdminService.Units.Where(s => s.UnitID == UnitDetail.ParentUnitID).FirstOrDefault();
                                    if(parentUnitDetail != null)
                                    {
                                       model.WFUserProfile.CurrentUserUnitName = parentUnitDetail.UnitName;
                                    }     
                                }

                                lstReviewUser = userRepo.GetReviewerUserProfileById(CurrentUserUnitID, strFunctionalTaskCode, true);
                                if (lstReviewUser.Count > 0)
                                {
                                    userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                    userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Add.ToString();
                                    userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Add);
                                    userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.Unit; ;
                                    userwfModel.StartDate = DateTime.Now;
                                    if (model.WFUserProfile.Remarks != null && model.WFUserProfile.Remarks != "")
                                    {
                                        userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingReviewRemark + " : " + " " + model.WFUserProfile.Remarks;
                                    }
                                    else
                                    {
                                        userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingReviewRemark;
                                    }

                                    userwfModel.AssignBy = currentUser.LoginID;
                                    userwfModel.AssignByName = currentUser.DisplayName;
                                    userwfModel.AssignByEmail = currentUser.Email;
                                    userwfModel.CreatedBy = model.WFUserProfile.CreatedBy;
                                    userwfModel.CreatedDateTime = DateTime.Now;
                                    userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                    userwfModel.LastUpdatedDateTime = model.WFUserProfile.LastUpdatedDateTime;
                                    userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                                    userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.PendingReview);
                                    userwfModel.AssignToLogin = CurrentUserUnitID.ToString();
                                    userwfModel.AssignToName = "Pegawai Penyemak, " + model.WFUserProfile.CurrentUserUnitName;
                                    userwfModel.AssignToEmail = "";
                                    userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Draft;
                                    UserWorkFlowViewModel objWorkflow = userRepo.InsertUserWorkflow(userwfModel);
                                    if (objWorkflow.WorkflowID > 0)
                                    {
                                        userwfModel.WorkflowID = objWorkflow.WorkflowID;
                                        foreach (var detail in lstReviewUser)
                                        {
                                            userwfModel.AssignToEmail = detail.AssignToEmail;
                                            userwfModel.AssignToName = detail.AssignToName;
                                            userwfModel.AssignToLogin = detail.AssignToLogin;
                                            userRepo.InsertUserWorkflowAssignUser(userwfModel);
                                            strAssignToEmail += detail.AssignToEmail + ",";
                                        }

                                        userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                        userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                        userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                        userwfModel.LastUpdatedDateTime = DateTime.Now;
                                        userwfModel.ReviewBy = "";
                                        userwfModel.ReviewByName = "";
                                        userwfModel.ReviewByEmail = "";
                                        userwfModel.ApprovedBy = "";
                                        userwfModel.ApprovedByName = "";
                                        userwfModel.ApprovedByEmail = "";
                                        userwfModel.RequestedBy = currentUser.LoginID;
                                        userwfModel.RequestedByName = currentUser.DisplayName;
                                        userwfModel.RequestedByEmail = currentUser.Email;
                                        userwfModel.RequestedDateTime = DateTime.Now;

                                        userRepo.UpdateWFUserProfileForAssign(userwfModel);
                                    }
                                }
                                else
                                {
                                    //if no review user found inside review group.
                                    data.WFUserProfile.WFStatusID = -1;
                                    data.WFUserProfile.ActiveCondition = model.WFUserProfile.ActiveCondition;
                                }
                            }
                            //Submit For Approval button click
                            else if (model.WFUserProfile.IsSubmitApprovalAction)
                            {
                                string strFunctionalTaskCode = Constant.Authentication.Administration.ApproveUserProfileCreationUpdate;
                                List<UserWorkFlowViewModel> lstApproveUser = new List<UserWorkFlowViewModel>();
                                lstApproveUser = userRepo.GetReviewerUserProfileById(0, strFunctionalTaskCode, false);
                                if (lstApproveUser.Count > 0)
                                {
                                    foreach (var obj in lstApproveUser)
                                    {
                                        var ApprovalUnitName = AdminService.Units.Where(x => x.UnitID == obj.UnitID).Select(x => x.UnitName).FirstOrDefault();
                                        userwfModel.AssignToLogin = obj.UnitID.ToString();
                                        userwfModel.AssignToName = "Pegawai Pelulus";
                                    }

                                    //Insert to workflow history
                                    UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
                                    oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                                    if (oriuserwfModel != null)
                                    {
                                        if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Reviewed)
                                        {
                                            oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                            oriuserwfModel.CompletedDate = DateTime.Now;
                                            oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.PendingReview);
                                            oriuserwfModel.ClosedRemarks = "";

                                        }

                                        DateTime now = DateTime.Now;
                                        userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                                    }

                                    //Insert into workflow table
                                    userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                    userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Update.ToString();
                                    userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Update);
                                    userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.Unit;
                                    userwfModel.StartDate = DateTime.Now;
                                    if (model.WFUserProfile.Remarks != null && model.WFUserProfile.Remarks != "")
                                    {
                                        userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingApprovalRemark + " : " + model.WFUserProfile.Remarks;
                                    }
                                    else
                                    {
                                        userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingApprovalRemark;
                                    }

                                    userwfModel.AssignBy = currentUser.LoginID;
                                    userwfModel.AssignByName = currentUser.DisplayName;
                                    userwfModel.AssignByEmail = currentUser.Email;
                                    userwfModel.CreatedBy = currentUser.LoginID;
                                    userwfModel.CreatedDateTime = DateTime.Now;
                                    userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                    userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                    userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                    userwfModel.LastUpdatedDateTime = DateTime.Now;
                                    userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingApproval;
                                    userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                                    userwfModel.AssignToEmail = "";
                                    userwfModel.ReviewBy = currentUser.LoginID;
                                    userwfModel.ReviewByName = currentUser.DisplayName;
                                    userwfModel.ReviewByEmail = currentUser.Email;
                                    userwfModel.ReviewedDateTime = DateTime.Now;
                                    userwfModel.ApprovedBy = "";
                                    userwfModel.ApprovedByName = "";
                                    userwfModel.ApprovedByEmail = "";
                                    userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                                    userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                                    userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                                    if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                                    {
                                        userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                                    }

                                    //userwfModel.ApprovedDateTime = (DateTime?)DBNull;

                                    UserWorkFlowViewModel objWorkflow = userRepo.InsertUserWorkflow(userwfModel);
                                    if (objWorkflow.WorkflowID > 0)
                                    {
                                        userwfModel.WorkflowID = objWorkflow.WorkflowID;
                                        userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.PendingApproval);
                                        userwfModel.WFStatusID = objWorkflow.WFStatusID;
                                        foreach (var detail in lstApproveUser)
                                        {
                                            userwfModel.AssignToEmail = detail.AssignToEmail;
                                            userwfModel.AssignToName = detail.AssignToName;
                                            userwfModel.AssignToLogin = detail.AssignToLogin;
                                            userRepo.InsertUserWorkflowAssignUser(userwfModel);
                                            strAssignToEmail += detail.AssignToEmail + ",";
                                        }

                                        //userwfModel.IsSubmitApproval = true;
                                        userRepo.UpdateWFUserProfileForAssign(userwfModel);
                                    }
                                }
                                else
                                {
                                    //if no approver user found inside Approver group.
                                    data.WFUserProfile.WFStatusID = -2;
                                    data.WFUserProfile.ActiveCondition = model.WFUserProfile.ActiveCondition;
                                }
                            }
                            //Approval button click
                            else if (model.WFUserProfile.IsApproveAction)
                            {
                                UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
                                userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Diluluskan;
                                userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Diluluskan);
                                userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingApproval;
                                userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                userwfModel.LastUpdatedDateTime = DateTime.Now;
                                userwfModel.ReviewBy = model.WFUserProfile.ReviewBy;
                                userwfModel.ReviewByName = model.WFUserProfile.ReviewByName;
                                userwfModel.ReviewByEmail = model.WFUserProfile.ReviewByEmail;
                                userwfModel.ReviewedDateTime = model.WFUserProfile.ReviewedDateTime;
                                userwfModel.ApprovedBy = currentUser.LoginID;
                                userwfModel.ApprovedByName = currentUser.DisplayName;
                                userwfModel.ApprovedByEmail = currentUser.Email;
                                userwfModel.ApprovedDateTime = DateTime.Now;
                                userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                                userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                                userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                                if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                                {
                                    userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                                }

                                oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                                if (oriuserwfModel != null)
                                {
                                    if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Approved)
                                    {
                                        oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                        oriuserwfModel.CompletedDate = DateTime.Now;
                                        oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Diluluskan);

                                    }

                                    if (model.WFUserProfile.Remarks != null && model.WFUserProfile.Remarks != "")
                                    {
                                        oriuserwfModel.ClosedRemarks = Constant.UserWorkflow.UserWFRemarks.ApprovalRemark + " : " + model.WFUserProfile.Remarks;
                                    }
                                    else
                                    {
                                        oriuserwfModel.ClosedRemarks = Constant.UserWorkflow.UserWFRemarks.ApprovalRemark;
                                    }

                                    oriuserwfModel.AssignBy = model.WFUserProfile.LastUpdatedBy;
                                    oriuserwfModel.AssignByName = model.WFUserProfile.LastUpdatedByName;
                                    oriuserwfModel.AssignByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                    DateTime now = DateTime.Now;
                                    userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                                }

                                userRepo.UpdateWFUserProfileForAssign(userwfModel);
                                //strAssignToEmail = userwfModel.ReviewByEmail + "," + oriWFUserProfileDetails.Email + "," + userwfModel.RequestedByEmail;
                            }
                            //Reject Button Click
                            else if (model.WFUserProfile.IsRejectAction)
                            {
                                UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();

                                oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                                if (oriuserwfModel != null)
                                {
                                    if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Rejected)
                                    {
                                        oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                        oriuserwfModel.CompletedDate = DateTime.Now;
                                        oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Ditolak);
                                        oriuserwfModel.ClosedRemarks = "";

                                    }

                                    DateTime now = DateTime.Now;
                                    userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                                }

                                UserWorkFlowViewModel oriUserwfHistoryModel = new UserWorkFlowViewModel();
                                oriUserwfHistoryModel = userRepo.GetExistingUserWorkFlowHistoryByID(data.WFUserProfile.WFUserProfileID);
                                if (oriUserwfHistoryModel != null)
                                {
                                    model.WFUserProfile.IsRejectByApprovalAction = true;
                                }

                                // When Reject by Approval People
                                if (model.WFUserProfile.ReviewBy != null)
                                {
                                    userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                    userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Update.ToString();
                                    userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Update);
                                    userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.User;
                                    userwfModel.StartDate = DateTime.Now;
                                    userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.RejectRemark + model.WFUserProfile.Remarks;
                                    userwfModel.AssignBy = currentUser.LoginID;
                                    userwfModel.AssignByName = currentUser.DisplayName;
                                    userwfModel.AssignByEmail = currentUser.Email;
                                    userwfModel.CreatedBy = currentUser.LoginID;
                                    userwfModel.CreatedDateTime = DateTime.Now;
                                    userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                    userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                    userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                    userwfModel.LastUpdatedDateTime = DateTime.Now;
                                    userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Ditolak;
                                    userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingApproval;
                                    userwfModel.AssignToEmail = oriUserwfHistoryModel.AssignByEmail;
                                    userwfModel.AssignToLogin = oriUserwfHistoryModel.AssignBy;
                                    userwfModel.AssignToName = oriUserwfHistoryModel.AssignByName;
                                    userwfModel.ReviewBy = oriuserwfModel.AssignBy;
                                    userwfModel.ReviewByName = oriuserwfModel.AssignByName;
                                    userwfModel.ReviewByEmail = oriuserwfModel.AssignByEmail;
                                    userwfModel.ReviewedDateTime = oriuserwfModel.CreatedDateTime;
                                    userwfModel.ApprovedBy = currentUser.LoginID;
                                    userwfModel.ApprovedByName = currentUser.DisplayName;
                                    userwfModel.ApprovedByEmail = currentUser.Email;
                                    userwfModel.ApprovedDateTime = DateTime.Now;
                                    userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                                    userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                                    userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                                    if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                                    {
                                        userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                                    }
                                    strAssignToEmail = userwfModel.AssignToEmail;
                                }
                                // When Reject by Review People
                                else
                                {
                                    userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                    userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Update.ToString();
                                    userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Update);
                                    userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.User;
                                    userwfModel.StartDate = DateTime.Now;
                                    userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.RejectRemark + model.WFUserProfile.Remarks;
                                    userwfModel.AssignBy = currentUser.LoginID;
                                    userwfModel.AssignByName = currentUser.DisplayName;
                                    userwfModel.AssignByEmail = currentUser.Email;
                                    userwfModel.CreatedBy = currentUser.LoginID;
                                    userwfModel.CreatedDateTime = DateTime.Now;
                                    userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                    userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                    userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                    userwfModel.LastUpdatedDateTime = DateTime.Now;
                                    userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Ditolak;
                                    userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                                    userwfModel.AssignToEmail = oriWFUserProfileDetails.LastUpdatedByEmail;
                                    userwfModel.AssignToLogin = oriWFUserProfileDetails.LastUpdatedBy;
                                    userwfModel.AssignToName = oriWFUserProfileDetails.LastUpdatedByName;
                                    userwfModel.ReviewBy = currentUser.LoginID;
                                    userwfModel.ReviewByName = currentUser.DisplayName;
                                    userwfModel.ReviewByEmail = currentUser.Email;
                                    userwfModel.ReviewedDateTime = DateTime.Now;
                                    userwfModel.ApprovedBy = "";
                                    userwfModel.ApprovedByName = "";
                                    userwfModel.ApprovedByEmail = "";
                                    userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                                    userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                                    userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                                    if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                                    {
                                        userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                                    }
                                    strAssignToEmail = userwfModel.AssignToEmail;

                                }

                                UserWorkFlowViewModel objWorkflow = userRepo.InsertUserWorkflow(userwfModel);
                                if (objWorkflow.WorkflowID > 0)
                                {
                                    userwfModel.WorkflowID = objWorkflow.WorkflowID;
                                    userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Ditolak);
                                    userwfModel.WFStatusID = objWorkflow.WFStatusID;

                                    userRepo.InsertUserWorkflowAssignUser(userwfModel);

                                }

                                userRepo.UpdateWFUserProfileForAssign(userwfModel);
                            }
                                data.WFUserProfile.IsSendApproval = true;
                            }
                            else
                            {
                                data.WFUserProfile.IsSendApproval = false;
                            }
                        }
                        scope.Complete();
                    }

                        // Update user in cache
                        if (data?.WFUserProfile?.WFUserProfileID > 0)
                    {
                        if (blnIsDeactivated && model.WFUserProfile.WFUserProfileID != 0)
                            RemoveUserCacheByLoginID(data.WFUserProfile.LoginID);
                        else if (!blnIsDeactivated && model.WFUserProfile.WFUserProfileID != 0)
                            UpdateUserCacheByLoginID(data.WFUserProfile.LoginID);
                    }
                }
            }
            else
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required))
                {
                    //Check if user change default unit or not
                    if (oriWFUserProfileDetails != null)
                    {
                        if (oriWFUserProfileDetails.UnitID != model.WFUserProfile.UnitID)
                        {
                            int OriUnitID = oriWFUserProfileDetails.UserFunctionRoles.Select(x => x.UnitID).FirstOrDefault();
                            userRepo.DeleteWFAllRoleForDefaultUnitRole(model.WFUserProfile, OriUnitID);
                        }
                    }

                    if (model.WFUserProfile.WFStatusID == null || model.WFUserProfile.WFStatusID == (int)Constant.UserWorkflow.UserWorkflowStatus.Selesai)
                    {
                        model.WFUserProfile.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Draft;
                        model.WFUserProfile.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Draft);
                    }

                    data.WFUserProfile = userRepo.UpdateWFUserProfileDetail(model.WFUserProfile);
                    if (data.WFUserProfile.WFUserProfileID > 0)
                    {
                        data.WFUserProfile.CreatedBy = currentUser.LoginID;
                        data.WFUserProfile.CreatedDateTime = DateTime.Now;
                        data.WFUserProfile.CreatedBy = currentUser.LoginID;
                        data.WFUserProfile.LastUpdatedDateTime = DateTime.Now;

                        // Remove current Default Role from db
                        if (model.WFUserProfile.RemoveDefaultRolesID != null)
                        {
                            userRepo.DeleteWFRolesForUser(data.WFUserProfile, model.WFUserProfile.RemoveDefaultRolesID, true);
                        }

                        //Delete additional Unit and roles if the user remove current additional unit.
                        if (model.WFUserProfile.RemoveUnitAndRoles != null)
                        {
                            userRepo.DeleteWFUnitAndRole(data.WFUserProfile, model.WFUserProfile.RemoveUnitAndRoles);
                        }

                        // Add Default roles And Unit to role member ID
                        string multipleRole = model.WFUserProfile.DefaultRolesID;
                        if (multipleRole != null)
                        {
                            int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                            foreach (var i in result)
                            {
                                userRepo.UpdateWFRolesForUser(data.WFUserProfile, i, true);
                            }
                        }

                        //If have addition roles and unit
                        //if(model.UserProfile.AdditionalUnitID > 0 && model.UserProfile.AdditionalRolesID !=null)
                        if (model.WFUserProfile.UserAdditionalUnitAndRoles != null)
                        {
                            if (model.WFUserProfile.UserAdditionalUnitAndRoles.Count > 0)
                            {
                                foreach (var a in model.WFUserProfile.UserAdditionalUnitAndRoles)
                                {
                                    data.WFUserProfile.AdditionalUnitID = Convert.ToInt32(a.ID);
                                    data.WFUserProfile.ManagerUserProfileID = Convert.ToInt64(a.ManagerId);
                                    foreach (var b in a.UnitRoleFunctionalID)
                                    {
                                        multipleRole = b.FunctionalRoleID.ToString();
                                        if (multipleRole != null)
                                        {
                                            int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                                            foreach (var i in result)
                                            {
                                                userRepo.UpdateWFRolesForUser(data.WFUserProfile, i, false);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (model.WFUserProfile.AdditionalRolesID != null)
                                {
                                    data.WFUserProfile.AdditionalUnitID = model.WFUserProfile.AdditionalUnitID;
                                    multipleRole = model.WFUserProfile.AdditionalRolesID.ToString();
                                    data.WFUserProfile.ManagerUserProfileID = model.WFUserProfile.AdditionalManagerID;
                                    if (multipleRole != null)
                                    {
                                        int[] result = multipleRole.Split("||").Select(int.Parse).ToArray();
                                        foreach (var i in result)
                                        {
                                            userRepo.UpdateWFRolesForUser(data.WFUserProfile, i, false);
                                        }
                                    }

                                }

                            }

                            // Remove current Role in additional roles and unit from db
                            if (model.WFUserProfile.RemoveAdditionalRolesID != null && model.WFUserProfile.RemoveAdditionalRolesID !="0")
                            {
                                data.WFUserProfile.RemoveAdditionalUnitID = model.WFUserProfile.RemoveAdditionalUnitID;
                                userRepo.DeleteWFRolesForUser(data.WFUserProfile, model.WFUserProfile.RemoveAdditionalRolesID, false);
                            }
                        }

                        //Check User Active Condition
                        if (model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Active)
                        {
                            model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Active);
                        }
                        else if (model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Inactive)
                        {
                            model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Inactive);
                        }
                        else if (model.WFUserProfile.ActiveCondition == (int)Constant.UserWorkflow.UserWFActiveCondition.Dormant)
                        {
                            model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Dormant);
                        }
                        else
                        {
                            model.WFUserProfile.ActiveConditionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActiveCondition.Expiry);
                        }

                        UserWFActiveConditionViewModel OriWFUserActiveCondition = userRepo.GetExistingWFUserActiveCondition(data.WFUserProfile.WFUserProfileID);

                        if (OriWFUserActiveCondition != null)
                        {
                            model.WFUserProfile.WFActivePeriodID = OriWFUserActiveCondition.WFActivePeriodID;
                            userRepo.UpdateWFUserActiveCondition(model.WFUserProfile);
                        }
                        else
                        {
                            model.WFUserProfile.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                            userRepo.UpdateWFUserActiveCondition(model.WFUserProfile);
                        }

                        //Submit For Review button click
                        if (model.WFUserProfile.IsSubmitReviewAction)
                        {
                            UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
                            oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                            if (oriuserwfModel != null)
                            {
                                if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Draft)
                                {
                                    oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                    oriuserwfModel.CompletedDate = DateTime.Now;
                                    oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Ditolak);
                                    oriuserwfModel.ClosedRemarks = "";

                                }

                                DateTime now = DateTime.Now;
                                userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                            }

                            //Insert for User Workflow for Review
                            var CurrentUserUnitID = model.WFUserProfile.CurrentUserUnitID;
                            string strFunctionalTaskCode = Constant.Authentication.Administration.ReviewUserProfileCreationUpdate;
                            List<UserWorkFlowViewModel> lstReviewUser = new List<UserWorkFlowViewModel>();
                            var UnitDetail = AdminService.Units.Where(s => s.UnitID == CurrentUserUnitID).FirstOrDefault();
                            if (UnitDetail != null && UnitDetail.HierarchyType == 37)
                            {
                                var parentUnitDetail = AdminService.Units.Where(s => s.UnitID == UnitDetail.ParentUnitID).FirstOrDefault();
                                if (parentUnitDetail != null)
                                {
                                    model.WFUserProfile.CurrentUserUnitName = parentUnitDetail.UnitName;
                                }
                            }
                            lstReviewUser = userRepo.GetReviewerUserProfileById(CurrentUserUnitID, strFunctionalTaskCode, true);
                            if (lstReviewUser.Count > 0)
                            {
                                userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Add.ToString();
                                userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Add);
                                userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.Unit; ;
                                userwfModel.StartDate = DateTime.Now;
                                if (model.WFUserProfile.Remarks != null && model.WFUserProfile.Remarks != "")
                                {
                                    userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingReviewRemark + " : " + " " + model.WFUserProfile.Remarks;
                                }
                                else
                                {
                                    userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingReviewRemark;
                                }

                                userwfModel.AssignBy = currentUser.LoginID;
                                userwfModel.AssignByName = currentUser.DisplayName;
                                userwfModel.AssignByEmail = currentUser.Email;
                                userwfModel.CreatedBy = model.WFUserProfile.CreatedBy;
                                userwfModel.CreatedDateTime = DateTime.Now;
                                userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                userwfModel.LastUpdatedDateTime = model.WFUserProfile.LastUpdatedDateTime;
                                userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                                userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.PendingReview);
                                userwfModel.AssignToLogin = CurrentUserUnitID.ToString();
                                userwfModel.AssignToName = "Pegawai Penyemak, " + model.WFUserProfile.CurrentUserUnitName;
                                userwfModel.AssignToEmail = "";
                                userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Draft;
                                UserWorkFlowViewModel objWorkflow = userRepo.InsertUserWorkflow(userwfModel);
                                if (objWorkflow.WorkflowID > 0)
                                {
                                    userwfModel.WorkflowID = objWorkflow.WorkflowID;
                                    foreach (var detail in lstReviewUser)
                                    {
                                        userwfModel.AssignToEmail = detail.AssignToEmail;
                                        userwfModel.AssignToName = detail.AssignToName;
                                        userwfModel.AssignToLogin = detail.AssignToLogin;
                                        userRepo.InsertUserWorkflowAssignUser(userwfModel);
                                        strAssignToEmail += detail.AssignToEmail + ",";
                                    }

                                    userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                    userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                    userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                    userwfModel.LastUpdatedDateTime = DateTime.Now;
                                    userwfModel.ReviewBy = "";
                                    userwfModel.ReviewByName = "";
                                    userwfModel.ReviewByEmail = "";
                                    userwfModel.ApprovedBy = "";
                                    userwfModel.ApprovedByName = "";
                                    userwfModel.ApprovedByEmail = "";
                                    userwfModel.RequestedBy = currentUser.LoginID;
                                    userwfModel.RequestedByName = currentUser.DisplayName;
                                    userwfModel.RequestedByEmail = currentUser.Email;
                                    userwfModel.RequestedDateTime = DateTime.Now;

                                    userRepo.UpdateWFUserProfileForAssign(userwfModel);
                                }
                            }
                            else
                            {
                                //if no review user found inside review group.
                                data.WFUserProfile.WFStatusID = -1;
                                data.WFUserProfile.ActiveCondition = model.WFUserProfile.ActiveCondition;
                            }
                        }
                        //Submit For Approval button click
                        else if (model.WFUserProfile.IsSubmitApprovalAction)
                        {
                            string strFunctionalTaskCode = Constant.Authentication.Administration.ApproveUserProfileCreationUpdate;
                            List<UserWorkFlowViewModel> lstApproveUser = new List<UserWorkFlowViewModel>();
                            lstApproveUser = userRepo.GetReviewerUserProfileById(0, strFunctionalTaskCode, false);
                            if (lstApproveUser.Count > 0)
                            {
                                foreach (var obj in lstApproveUser)
                                {
                                    var ApprovalUnitName = AdminService.Units.Where(x => x.UnitID == obj.UnitID).Select(x => x.UnitName).FirstOrDefault();
                                    userwfModel.AssignToLogin = obj.UnitID.ToString();
                                    userwfModel.AssignToName = "Pegawai Pelulus";
                                }

                                //Insert to workflow history
                                UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
                                oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                                if (oriuserwfModel != null)
                                {
                                    if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Reviewed)
                                    {
                                        oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                        oriuserwfModel.CompletedDate = DateTime.Now;
                                        oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.PendingReview);
                                        oriuserwfModel.ClosedRemarks = "";

                                    }

                                    DateTime now = DateTime.Now;
                                    userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                                }

                                //Insert into workflow table
                                userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Update.ToString();
                                userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Update);
                                userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.Unit;
                                userwfModel.StartDate = DateTime.Now;
                                if (model.WFUserProfile.Remarks != null && model.WFUserProfile.Remarks != "")
                                {
                                    userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingApprovalRemark + " : " + model.WFUserProfile.Remarks;
                                }
                                else
                                {
                                    userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.PendingApprovalRemark;
                                }

                                userwfModel.AssignBy = currentUser.LoginID;
                                userwfModel.AssignByName = currentUser.DisplayName;
                                userwfModel.AssignByEmail = currentUser.Email;
                                userwfModel.CreatedBy = currentUser.LoginID;
                                userwfModel.CreatedDateTime = DateTime.Now;
                                userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                userwfModel.LastUpdatedDateTime = DateTime.Now;
                                userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingApproval;
                                userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                                userwfModel.AssignToEmail = "";
                                userwfModel.ReviewBy = currentUser.LoginID;
                                userwfModel.ReviewByName = currentUser.DisplayName;
                                userwfModel.ReviewByEmail = currentUser.Email;
                                userwfModel.ReviewedDateTime = DateTime.Now;
                                userwfModel.ApprovedBy = "";
                                userwfModel.ApprovedByName = "";
                                userwfModel.ApprovedByEmail = "";
                                userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                                userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                                userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                                if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                                {
                                    userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                                }

                                //userwfModel.ApprovedDateTime = (DateTime?)DBNull;

                                UserWorkFlowViewModel objWorkflow = userRepo.InsertUserWorkflow(userwfModel);
                                if (objWorkflow.WorkflowID > 0)
                                {
                                    userwfModel.WorkflowID = objWorkflow.WorkflowID;
                                    userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.PendingApproval);
                                    userwfModel.WFStatusID = objWorkflow.WFStatusID;
                                    foreach (var detail in lstApproveUser)
                                    {
                                        userwfModel.AssignToEmail = detail.AssignToEmail;
                                        userwfModel.AssignToName = detail.AssignToName;
                                        userwfModel.AssignToLogin = detail.AssignToLogin;
                                        userRepo.InsertUserWorkflowAssignUser(userwfModel);
                                        strAssignToEmail += detail.AssignToEmail + ",";
                                    }

                                    //userwfModel.IsSubmitApproval = true;
                                    userRepo.UpdateWFUserProfileForAssign(userwfModel);
                                }
                            }
                            else
                            {
                                //if no approver user found inside Approver group.
                                data.WFUserProfile.WFStatusID = -2;
                                data.WFUserProfile.ActiveCondition = model.WFUserProfile.ActiveCondition;
                            }
                        }
                        //Approval button click
                        else if (model.WFUserProfile.IsApproveAction)
                        {
                            UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
                            userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Diluluskan;
                            userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Diluluskan);
                            userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingApproval;
                            userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                            userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                            userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                            userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                            userwfModel.LastUpdatedDateTime = DateTime.Now;
                            userwfModel.ReviewBy = model.WFUserProfile.ReviewBy;
                            userwfModel.ReviewByName = model.WFUserProfile.ReviewByName;
                            userwfModel.ReviewByEmail = model.WFUserProfile.ReviewByEmail;
                            userwfModel.ReviewedDateTime = model.WFUserProfile.ReviewedDateTime;
                            userwfModel.ApprovedBy = currentUser.LoginID;
                            userwfModel.ApprovedByName = currentUser.DisplayName;
                            userwfModel.ApprovedByEmail = currentUser.Email;
                            userwfModel.ApprovedDateTime = DateTime.Now;
                            userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                            userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                            userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                            if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                            {
                                userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                            }

                            oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                            if (oriuserwfModel != null)
                            {
                                if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Approved)
                                {
                                    oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                    oriuserwfModel.CompletedDate = DateTime.Now;
                                    oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Diluluskan);

                                }

                                if (model.WFUserProfile.Remarks != null && model.WFUserProfile.Remarks != "")
                                {
                                    oriuserwfModel.ClosedRemarks = Constant.UserWorkflow.UserWFRemarks.ApprovalRemark + " : " + model.WFUserProfile.Remarks;
                                }
                                else
                                {
                                    oriuserwfModel.ClosedRemarks = Constant.UserWorkflow.UserWFRemarks.ApprovalRemark;
                                }

                                oriuserwfModel.AssignBy = model.WFUserProfile.LastUpdatedBy;
                                oriuserwfModel.AssignByName = model.WFUserProfile.LastUpdatedByName;
                                oriuserwfModel.AssignByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                DateTime now = DateTime.Now;
                                userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                            }

                            userRepo.UpdateWFUserProfileForAssign(userwfModel);
                            //strAssignToEmail = userwfModel.ReviewByEmail + "," + oriWFUserProfileDetails.Email + "," + userwfModel.RequestedByEmail;
                        }
                        //Reject Button Click
                        else if (model.WFUserProfile.IsRejectAction)
                        {
                            UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();

                            oriuserwfModel = userRepo.GetExistingUserWorkFlow(data.WFUserProfile.WFUserProfileID);
                            if (oriuserwfModel != null)
                            {
                                if (model.WFUserProfile.UserWorkFlow.DecisionID == (int)Constant.UserWorkflow.UserWorkflowDecision.Rejected)
                                {
                                    oriuserwfModel.DecisionID = model.WFUserProfile.UserWorkFlow.DecisionID;
                                    oriuserwfModel.CompletedDate = DateTime.Now;
                                    oriuserwfModel.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Ditolak);
                                    oriuserwfModel.ClosedRemarks = "";

                                }

                                DateTime now = DateTime.Now;
                                userRepo.InsertUserWorkflowHistory(oriuserwfModel, now);
                            }

                            UserWorkFlowViewModel oriUserwfHistoryModel = new UserWorkFlowViewModel();
                            oriUserwfHistoryModel = userRepo.GetExistingUserWorkFlowHistoryByID(data.WFUserProfile.WFUserProfileID);
                            if (oriUserwfHistoryModel != null)
                            {
                                model.WFUserProfile.IsRejectByApprovalAction = true;
                            }

                            // When Reject by Approval People
                            if (model.WFUserProfile.ReviewBy != null)
                            {
                                userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Update.ToString();
                                userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Update);
                                userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.User;
                                userwfModel.StartDate = DateTime.Now;
                                userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.RejectRemark + model.WFUserProfile.Remarks;
                                userwfModel.AssignBy = currentUser.LoginID;
                                userwfModel.AssignByName = currentUser.DisplayName;
                                userwfModel.AssignByEmail = currentUser.Email;
                                userwfModel.CreatedBy = currentUser.LoginID;
                                userwfModel.CreatedDateTime = DateTime.Now;
                                userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                userwfModel.LastUpdatedDateTime = DateTime.Now;
                                userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Ditolak;
                                userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingApproval;
                                userwfModel.AssignToEmail = oriUserwfHistoryModel.AssignByEmail;
                                userwfModel.AssignToLogin = oriUserwfHistoryModel.AssignBy;
                                userwfModel.AssignToName = oriUserwfHistoryModel.AssignByName;
                                userwfModel.ReviewBy = oriuserwfModel.AssignBy;
                                userwfModel.ReviewByName = oriuserwfModel.AssignByName;
                                userwfModel.ReviewByEmail = oriuserwfModel.AssignByEmail;
                                userwfModel.ReviewedDateTime = oriuserwfModel.CreatedDateTime;
                                userwfModel.ApprovedBy = currentUser.LoginID;
                                userwfModel.ApprovedByName = currentUser.DisplayName;
                                userwfModel.ApprovedByEmail = currentUser.Email;
                                userwfModel.ApprovedDateTime = DateTime.Now;
                                userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                                userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                                userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                                if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                                {
                                    userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                                }
                                strAssignToEmail = userwfModel.AssignToEmail;
                            }
                            // When Reject by Review People
                            else
                            {
                                userwfModel.WFUserProfileID = data.WFUserProfile.WFUserProfileID;
                                userwfModel.ActionType = Constant.UserWorkflow.UserWFActionType.Update.ToString();
                                userwfModel.ActionTypeDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWFActionType.Update);
                                userwfModel.AssignToTypeID = (int)Constant.UserWorkflow.UserAssignToType.User;
                                userwfModel.StartDate = DateTime.Now;
                                userwfModel.Remarks = Constant.UserWorkflow.UserWFRemarks.RejectRemark + model.WFUserProfile.Remarks;
                                userwfModel.AssignBy = currentUser.LoginID;
                                userwfModel.AssignByName = currentUser.DisplayName;
                                userwfModel.AssignByEmail = currentUser.Email;
                                userwfModel.CreatedBy = currentUser.LoginID;
                                userwfModel.CreatedDateTime = DateTime.Now;
                                userwfModel.LastUpdatedBy = model.WFUserProfile.LastUpdatedBy;
                                userwfModel.LastUpdatedByName = model.WFUserProfile.LastUpdatedByName;
                                userwfModel.LastUpdatedByEmail = model.WFUserProfile.LastUpdatedByEmail;
                                userwfModel.LastUpdatedDateTime = DateTime.Now;
                                userwfModel.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.Ditolak;
                                userwfModel.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.PendingReview;
                                userwfModel.AssignToEmail = oriWFUserProfileDetails.LastUpdatedByEmail;
                                userwfModel.AssignToLogin = oriWFUserProfileDetails.LastUpdatedBy;
                                userwfModel.AssignToName = oriWFUserProfileDetails.LastUpdatedByName;
                                userwfModel.ReviewBy = currentUser.LoginID;
                                userwfModel.ReviewByName = currentUser.DisplayName;
                                userwfModel.ReviewByEmail = currentUser.Email;
                                userwfModel.ReviewedDateTime = DateTime.Now;
                                userwfModel.ApprovedBy = "";
                                userwfModel.ApprovedByName = "";
                                userwfModel.ApprovedByEmail = "";
                                userwfModel.RequestedBy = oriWFUserProfileDetails.RequestedBy;
                                userwfModel.RequestedByName = oriWFUserProfileDetails.RequestedByName;
                                userwfModel.RequestedByEmail = oriWFUserProfileDetails.RequestedByEmail;
                                if (oriWFUserProfileDetails.RequestedDateTime.HasValue)
                                {
                                    userwfModel.RequestedDateTime = oriWFUserProfileDetails.RequestedDateTime.Value;
                                }
                                strAssignToEmail = userwfModel.AssignToEmail;

                            }

                            UserWorkFlowViewModel objWorkflow = userRepo.InsertUserWorkflow(userwfModel);
                            if (objWorkflow.WorkflowID > 0)
                            {
                                userwfModel.WorkflowID = objWorkflow.WorkflowID;
                                userwfModel.WFStatusDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowStatus.Ditolak);
                                userwfModel.WFStatusID = objWorkflow.WFStatusID;

                                userRepo.InsertUserWorkflowAssignUser(userwfModel);

                            }

                            userRepo.UpdateWFUserProfileForAssign(userwfModel);
                        }
                    }
                    scope.Complete();
                }

                    // Update user in cache
                    if (data?.WFUserProfile?.WFUserProfileID > 0)
                {
                    if (blnIsDeactivated && model.WFUserProfile.WFUserProfileID != 0)
                        RemoveUserCacheByLoginID(data.WFUserProfile.LoginID);
                    else if (!blnIsDeactivated && model.WFUserProfile.WFUserProfileID != 0)
                        UpdateUserCacheByLoginID(data.WFUserProfile.LoginID);
                }
            }
           


            data.ChangeHistory = model.ChangeHistory;

            return data;
        }

        public List<UserRequestProfileViewModel> GetWorkflowUserProfileList(WorkflowUserProfilePagedListViewModel paging, out int intCount)
        {
            intCount = 0;

            DataSet ds = userRepo.GetWorkflowUserProfileList(paging.SortExpression, paging.PageIndex, paging.Length, paging.UserDislayName, paging.ManagerUserProfileID, paging.UnitID,paging.WFStatusID,paging.JenisPermohonanType);

            List<UserRequestProfileViewModel> lstUserProfileVM = new List<UserRequestProfileViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstUserProfileVM = userRepo.DataTableToList<UserRequestProfileViewModel>(ds.Tables[0]).ToList();
                if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0)
                    intCount = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());
            }

            return lstUserProfileVM;

        }

        public List<UserProfileViewModel> CheckDuplicateByLoginID(string strName)
        {
            List<UserProfileViewModel> lstUser = userRepo.CheckDuplicateByLoginID(strName);

            return lstUser;

        }



        public List<UserRequestProfileViewModel> CheckWFUserDuplicateLogin(string strName)
        {
            List<UserRequestProfileViewModel> lstUser = userRepo.CheckWFUserDuplicateLogin(strName);

            return lstUser;

        }


        public ADUserInfoViewModel GetUserFromAD(string strEmail)
        {
            ADUserInfoViewModel user = new ADUserInfoViewModel();
            using (var context = new PrincipalContext(ContextType.Domain, "hasil.lhdnm.gov"))
            {
                UserPrincipal up = new UserPrincipal(context);
                up.EmailAddress = strEmail;

                PrincipalSearcher srch = new PrincipalSearcher(up);                
                foreach (var found in srch.FindAll())
                {
                    DirectoryEntry directoryEntry = found.GetUnderlyingObject() as DirectoryEntry;
                    user.LoginID = "hasil\\" + found.SamAccountName.ToLower();
                    user.DisplayName = directoryEntry.Properties["DisplayName"].Value.ToString();
                    user.Gred = directoryEntry.Properties["Title"].Value.ToString();
                    user.NRIC = directoryEntry.Properties["EmployeeID"].Value.ToString();
                }                
            }

            return user;
        }

        public List<UserRequestDashboardViewModel> GetDashboardMyPendingUserRequest(string strAssignTo, UserRequestDashboardViewModel paging, out int intCount)
        {
            intCount = 0;
            DataSet ds = userRepo.GetDashboardMyPendingUserRequest(strAssignTo, paging);

            List<UserRequestDashboardViewModel> lstDashBoardAssignFrom = new List<UserRequestDashboardViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstDashBoardAssignFrom = userRepo.DataTableToList<UserRequestDashboardViewModel>(ds.Tables[0]).ToList();
                if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0)
                    intCount = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());
            }

            return lstDashBoardAssignFrom;

        }

        public List<UserRequestDashboardViewModel> GetDashboardMyCreatedUserRequest(string strAssignFrom, UserRequestDashboardViewModel paging, out int intCount)
        {
            intCount = 0;
            DataSet ds = userRepo.GetDashboardMyCreatedUserRequest(strAssignFrom, paging);

            List<UserRequestDashboardViewModel> lstDashBoardAssignFrom = new List<UserRequestDashboardViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstDashBoardAssignFrom = userRepo.DataTableToList<UserRequestDashboardViewModel>(ds.Tables[0]).ToList();
                if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0)
                    intCount = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());
            }

            return lstDashBoardAssignFrom;

        }

        public UserRequestProfileViewModel CancelRequestWFUserProfile(UserRequestProfileUpdateViewModel modal)
        {
            UserRequestProfileViewModel model = new UserRequestProfileViewModel();

            using (var scope = new TransactionScope(TransactionScopeOption.Required))
            {
                if(modal.WFUserProfile.UserProfileID > 0)
                {
                    UserWorkFlowViewModel oriuserwfModel = new UserWorkFlowViewModel();
                    oriuserwfModel = userRepo.GetExistingUserWorkFlow(modal.WFUserProfile.WFUserProfileID);
                    if (oriuserwfModel != null)
                    {
                        DateTime now = DateTime.Now;
                        modal.WFUserProfile.UserWorkFlow.StartDate = oriuserwfModel.StartDate;

                        modal.WFUserProfile.WFStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.CancelRequest;
                        modal.WFUserProfile.UserWorkFlow.DecisionID = (int)Constant.UserWorkflow.UserWorkflowDecision.CancelRequested;
                        modal.WFUserProfile.UserWorkFlow.DecisionDesc = Utilities.GetEnumDescription(Constant.UserWorkflow.UserWorkflowDecision.CancelRequested);
                        modal.WFUserProfile.UserWorkFlow.WFPrevStageStatusID = (int)Constant.UserWorkflow.UserWorkflowStatus.CancelRequest;
                        if (modal.WFUserProfile.UserWorkFlow.Remarks == null)
                        {
                            modal.WFUserProfile.UserWorkFlow.Remarks = "";
                        }
                        userRepo.InsertUserWFHistoryForCancelRequest(modal, now);
                    }

                }
           
                model = userRepo.CancelRequestWFUserProfile(modal.WFUserProfile);
                scope.Complete();
            }

 
            return model;
        }

        public List<WorkflowUserViewModel> SearchUserRequestUnitByName(string strName, int UnitID, long WFUserProfileID)
        {
            List<WorkflowUserViewModel> lstUnit = new List<WorkflowUserViewModel>();
            if (WFUserProfileID == 0)
            {
                var parentunit = AdminService.Units.Where(x => x.IsActive == true && x.UnitID == UnitID).Select(x => x.ParentUnitID).FirstOrDefault();
                if(parentunit !=null)
                {
                    int ParentUnitID = (int)parentunit;
                    lstUnit = AdminService.Units.Where(x => x.IsActive == true && (x.ParentUnitID == UnitID || x.ParentUnitID == ParentUnitID) && x.UnitName.ToLower().Contains(strName.ToLower()))
                                                           .Select(x => new WorkflowUserViewModel
                                                           {
                                                               ID = x.UnitID.ToString(),
                                                               DisplayName = x.UnitName,
                                                               ParentUnitID = x.ParentUnitID,
                                                               AdditionalInfo = x.AdditionalInfo,
                                                               HierarchyType = x.HierarchyType,
                                                               ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                                                               AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                                                               UnitTypeID = x.UnitTypeID,
                                                               SeksyenID = x.SeksyenID,
                                                               JabatanID = x.JabatanID,
                                                               CawanganID = x.CawanganID
                                                           }).OrderBy(x => x.DisplayName).ToList();
                }
                else
                {
                    lstUnit = AdminService.Units.Where(x => x.IsActive == true && x.UnitName.ToLower().Contains(strName.ToLower()))
                                           .Select(x => new WorkflowUserViewModel
                                           {
                                               ID = x.UnitID.ToString(),
                                               DisplayName = x.UnitName,
                                               ParentUnitID = x.ParentUnitID,
                                               AdditionalInfo = x.AdditionalInfo,
                                               HierarchyType = x.HierarchyType,
                                               ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                                               AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                                               UnitTypeID = x.UnitTypeID,
                                               SeksyenID = x.SeksyenID,
                                               JabatanID = x.JabatanID,
                                               CawanganID = x.CawanganID
                                           }).OrderBy(x => x.DisplayName).ToList();
                }

            }
            else
            {

                lstUnit = AdminService.Units.Where(x => x.IsActive == true && x.UnitName.ToLower().Contains(strName.ToLower()))
                                                                     .Select(x => new WorkflowUserViewModel
                                                                     {
                                                                         ID = x.UnitID.ToString(),
                                                                         DisplayName = x.UnitName,
                                                                         ParentUnitID = x.ParentUnitID,
                                                                         AdditionalInfo = x.AdditionalInfo,
                                                                         HierarchyType = x.HierarchyType,
                                                                         ManagerFunctionRoleID = x.ManagerFunctionRoleID,
                                                                         AssignToType = Convert.ToInt16(Constant.LookupParamSys.AssignToTypeUnit),
                                                                         UnitTypeID = x.UnitTypeID,
                                                                         SeksyenID = x.SeksyenID,
                                                                         JabatanID = x.JabatanID,
                                                                         CawanganID = x.CawanganID
                                                                     }).OrderBy(x => x.DisplayName).ToList();
            }


            return lstUnit;

        }
    }

}
