using FI.FIC;
using FI.FIC.Contracts;
using FI.FIC.Contracts.DataObjects;
using FI.FIC.Contracts.DataObjects.BaseObject;
using FI.FIC.Contracts.DataObjects.BLObject;
using FI.FIC.Contracts.DataObjects.Enumeration;
using FI.FIC.Models;
using IronIntel.Contractor.Users;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace IronIntel.Contractor
{
    public class HostService
    {
        private FICUserInfo _User;
        private FICNetRequestObject _Request;
        public FICNetRequestObject Request
        {
            get { return _Request; }
            set
            {
                _Request = value;
                if (value == null)
                {
                    return;
                }
                _User = FICHostEnvironment.GetUserByLoginSessionID(value.SessionID);
            }
        }

        public static UserInfoItem[] GetAllUsers(bool hasAdmin = false)
        {
            //UserInfoItem[] users = UserManagement.GetAllUsers(hasAdmin);
            //List<UserInfoItem> ls = new List<UserInfoItem>();
            //foreach (UserInfoItem ui in users)
            //{
            //    ui.UserType = UserManagement.GetUserTypeByIID(ui.IID);
            //    ls.Add(ui);
            //}
            //return ls.ToArray();
            throw new NotImplementedException();
        }

        public string CurrentUserIID
        {
            get { return _User == null ? null : _User.IID; }
        }

        public string CurrentUserName
        {
            get { return _User == null ? null : _User.DisplayName; }
        }

        public string ClientLanguage
        {
            get { return _Request == null ? ResManager.DefaultLanguage : _Request.LanguageID; }
        }

        public string DeleteUserGroup(string iid)
        {
            try
            {
                UserManagement.DeleteGroup(iid);
            }
            catch (Exception ex)
            {
                SystemParams.WriteLog("ERROR", "DeleteUserGroup", ex.Message, ex.ToString());
                throw new Exception(ResManager.GetLanguage(ClientLanguage, "LHBIS_EXCEPTION_E0X6502704C")); // "Failed to delete the user group."
            }
            return null;
        }

        public UserManagementItem[] GetUsers()
        {
            //var users = GetAllUsers();
            //var items = new List<UserManagementItem>();

            //var groups = UserManagement.GetUserGroupMapping().Rows.Cast<DataRow>();

            //for (int i = 0; i < users.Length; i++)
            //{
            //    if (string.Compare(users[i].ID, "admin", true) == 0)
            //    {
            //        continue;
            //    }
            //    var item = ConvertFromFICUser(users[i]);
            //    // fill default param
            //    item.DefaultWspIID = UserParametersInfo.GetUserSystemParameter(EMUserDefaultInfoType.DefaultWorkSpace, users[i].IID);
            //    item.DefaultMobileWspIID = UserParametersInfo.GetUserSystemParameter(EMUserDefaultInfoType.DefaultWorkSpace4Mobile, users[i].IID);
            //    // fill groups
            //    var gs = groups
            //        .Where(g => g["USERID"].ToString().ToUpper() == users[i].IID.ToUpper())
            //        .Select(g => g["GROUPNAME"]);
            //    item.Groups = string.Join("; ", gs);

            //    items.Add(item);
            //}
            //return items.ToArray();
            throw new NotImplementedException();
        }

        private UserManagementItem ConvertFromFICUser(UserInfoItem user)
        {
            var item = new UserManagementItem
            {
                IID = user.IID,
                ID = user.ID,
                DisplayName = user.DisplayName,
                Email = user.Email,
                Mobile = user.Mobile,
                BusinessPhone = user.BusinessPhone,
                UserType = user.UserType,
                Enabled = user.Enabled,
                Active = user.Enabled ? "Yes" : "No",
                UserMode = user.UserMode
            };
            switch (user.UserType)
            {
                case FICUserTypes.Admin:
                case FICUserTypes.SuperAdmin:
                    item.UserLevel = "Admin";
                    break;
                case FICUserTypes.Common:
                    item.UserLevel = "User";
                    break;
                default:
                    item.UserLevel = "Read Only User";
                    break;
            }
            return item;
        }

        private static Regex reg_userid = new Regex("^[a-zA-Z0-9_-]+$");
        private static Regex reg_email = new Regex(@"^([a-zA-Z0-9]+[-_.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9-_]+\.)*[a-zA-Z]{2,4}$");

        private bool IsAdminOrSuper(FICUserTypes type)
        {
            return type == FICUserTypes.Admin || type == FICUserTypes.SuperAdmin;
        }
        private string VerifyPermission(string iid)
        {
            return VerifyPermission(new UserManagementItem
            {
                IID = iid,
                UserType = FICUserTypes.Readonly
            });
        }
        private string VerifyPermission(UserManagementItem user)
        {
            var currentUser = FICHostEnvironment.GetUserByIID(CurrentUserIID);
            var flag = false;
            if (string.IsNullOrEmpty(user.IID))
            {
                if (!IsAdminOrSuper(currentUser.UserType) &&
                    user.UserType == FICUserTypes.Admin)
                {
                    flag = true;
                }
            }
            else
            {
                var olduser = FICHostEnvironment.GetUserByIID(user.IID);
                //if (olduser.UserType == FICUserTypes.Admin)
                if (currentUser.UserType < user.UserType)
                {
                    flag = true;
                }
            }
            if (flag)
            {
                SystemParams.WriteLog("ERROR", "SaveUser", "user try to edit user with illegal permission.", string.Format("current user: {0}, {1}", CurrentUserIID, CurrentUserName));
                return ResManager.GetLanguage(ClientLanguage, "ERROR_LHBIS_FIC_BLC_BLWORKSPACE_A0034"); // "The user does not have the required access rights.";
            }
            return null;
        }

        public string SaveUser(FICUserInfo user, string password, string[] groups)
        {
            var item = new UserManagementItem
            {
                IID = user.IID,
                ID = user.ID,
                DisplayName = user.DisplayName,
                Mobile = user.Mobile,
                BusinessPhone = user.BusinessPhone,
                Email = user.Email,
                UserType = user.UserType,
                DefaultWspIID = user.DefaultWspIID,
                DefaultMobileWspIID = user.DefaultMobileWspIID,
                Enabled = user.Enabled,
                Password = password,
                GroupIIDs = groups
            };
            return SaveUser(item, null);
        }

        private string SaveUser(UserManagementItem user, string subject)
        {
            if (user == null)
            {
                return "User param is invalid.";
            }

            // 权限验证
            var r = VerifyPermission(user);
            if (r != null)
            {
                return r;
            }

            if (string.IsNullOrWhiteSpace(user.ID))
            {
                return ResManager.GetLanguage(ClientLanguage, "LHBIS_FIC_CLIENT_MODULES_USERMANAGERCTRL_A023"); // "User ID cannot be empty.";
            }
            if (!reg_email.Match(user.ID).Success && !reg_userid.Match(user.ID).Success)
            {
                return ResManager.GetLanguage(ClientLanguage, "LHBIS_FIC_CLIENT_MODULES_USERMANAGERCTRL_A056"); // "The user ID must contain only letters, numbers, underlines, minus signs or an email address.";
            }
            if (string.IsNullOrWhiteSpace(user.DisplayName))
            {
                return ResManager.GetLanguage(ClientLanguage, "LHBIS_FIC_CLIENT_MODULES_USERMANAGERCTRL_A024"); // "User name cannot be empty.";
            }
            if (!string.IsNullOrWhiteSpace(user.Email) && !reg_email.Match(user.Email).Success)
            {
                return ResManager.GetLanguage(ClientLanguage, "LHBIS_FIC_CLIENT_MODULES_USERMANAGERCTRL_A066"); // "Email address is invalid.";
            }
            user.ID = user.ID.Trim();
            if (user.ID.Length > 100)
            {
                user.ID = user.ID.Substring(0, 100);
            }
            if (user.DisplayName != null && user.DisplayName.Length > 100)
            {
                user.DisplayName = user.DisplayName.Substring(0, 100);
            }
            if (user.Password != null && user.Password.Length > 300)
            {
                user.Password = user.Password.Substring(0, 300);
            }
            if (user.Mobile != null && user.Mobile.Length > 50)
            {
                user.Mobile = user.Mobile.Substring(0, 50);
            }
            if (user.BusinessPhone != null && user.BusinessPhone.Length > 50)
            {
                user.BusinessPhone = user.BusinessPhone.Substring(0, 50);
            }

            // groups


            string result = SaveUser(new UserInfoItem
            {
                IID = user.IID,
                ID = user.ID,
                DisplayName = user.DisplayName,
                Enabled = user.Enabled,
                Mobile = user.Mobile,
                BusinessPhone = user.BusinessPhone,
                Email = user.Email,
                UserType = user.UserType,
                DefaultWspIID = user.DefaultWspIID,
                DefaultMobileWspIID = user.DefaultMobileWspIID
            }, user.Password, user.GroupIIDs, subject);
            if (result == null)
            {
                return "OK";
            }
            return result;
        }

        private string SaveUser(UserInfoItem user, string password, string[] groups, string subject)
        {
            //try
            //{
            //    if (string.IsNullOrEmpty(user.IID))
            //    {
            //        UserManagement.AddUser(user, password, groups);

            //        //UserManagement.AddUser(user, password, groups, subject, ClientLanguage);
            //    }
            //    else
            //    {
            //        UserManagement.EditUser(user, groups);
            //    }
            //    return null;
            //}
            //catch (Exception ex)
            //{
            //    return ex.Message;
            //}
            throw new NotImplementedException();
        }

        public string ResetPassword(string iid, string password)
        {
            // 权限验证
            //var r = VerifyPermission(iid);
            //if (r != null)
            //{
            //    return r;
            //}

            ////if (!string.IsNullOrEmpty(password))
            ////{
            ////    password = HttpUtility.HtmlDecode(password);
            ////}
            //UserManagement.ResetPassword(iid, string.IsNullOrEmpty(password), password);

            //return null;
            throw new NotImplementedException();
        }

        public string DeleteUser(string iid)
        {
            // 权限验证
            //var r = VerifyPermission(iid);
            //if (r != null)
            //{
            //    return r;
            //}

            //try
            //{
            //    UserManagement.DeleteUser(iid);
            //}
            //catch (Exception ex)
            //{
            //    FICHostEnvironment.WriteLog("ERROR", "", "DeleteUser", ex.Message, ex.ToString());
            //    throw new Exception(ResManager.GetLanguage("LHBIS_EXCEPTION_E0X65027021")); // "Failed to delete the user."
            //}
            //return null;
            throw new NotImplementedException();
        }

        public UserGroupSimple[] GetUserGroups(string iid)
        {
            UserGroupSimple[] groups = SearchLocalGroups(null);
            var selected = FICHostEnvironment.GetUserGroupIDByUserIID(iid);

            foreach (var g in groups)
            {
                if (selected.Contains(g.UserGroupID))
                {
                    g.IsSelected = true;
                }
            }
            return groups;
        }

        public UserGroupSimple[] GetAllGroups()
        {
            var groups = SearchLocalGroups(null);
            return groups;
        }

        public List<UserSimple> GetGroupMembers(string iid)
        {
            var users = FICHostEnvironment.GetUsers();
            if (string.IsNullOrEmpty(iid))
            {
                iid = Guid.Empty.ToString();
            }
            var selected = UserManagement.GetUserInfoByGoupid(iid);

            var list = new List<UserSimple>();
            foreach (var u in users)
            {
                var item = new UserSimple
                {
                    IID = u.IID,
                    UserID = u.ID,
                    UserName = u.DisplayName
                };
                var su = selected.FirstOrDefault((t) => t.IID.Equals(u.IID, StringComparison.OrdinalIgnoreCase));
                if (su != null)
                {
                    item.IsSelected = true;
                }
                list.Add(item);
            }
            return list;
        }

        public string SaveGroup(string gs)
        {
            //gs = HttpUtility.HtmlDecode(gs);
            var group = JsonConvert.DeserializeObject<UserGroupManagementItem>(gs);

            if (group == null)
            {
                return "Group param is invalid.";
            }
            if (string.IsNullOrWhiteSpace(group.Name))
            {
                return ResManager.GetLanguage(ClientLanguage, "LHBIS_FIC_CLIENT_MODULES_USERADDDIALOG_A004"); // "Group name cannot be empty.";
            }

            // users
            if (group.Name.Length > 100)
            {
                group.Name = group.Name.Substring(0, 100);
            }
            if (group.Description != null && group.Description.Length > 200)
            {
                group.Description = group.Description.Substring(0, 200);
            }

            string result = SaveGroup(new UserGroupSimple
            {
                UserGroupID = group.IID,
                UserGroupName = group.Name,
                Description = group.Description,
            }, group.UserIIDs);
            if (result == null)
            {
                return "OK";
            }
            return result;
        }

        private string SaveGroup(UserGroupSimple group, string[] users)
        {
            try
            {
                var add = string.IsNullOrEmpty(group.UserGroupID);
                bool isimport;
                if (!add)
                {
                    // import domain group
                    add = users == null && group.GroupMode == 1;
                    isimport = add;
                }
                else
                {
                    isimport = false;
                }
                UserGroupInfo ug = new UserGroupInfo();
                ug.ID = group.UserGroupID;
                ug.Name = group.UserGroupName;
                ug.Notes = group.Description;

                List<UserInfo> userList = new List<UserInfo>();
                if (users != null)
                {
                    foreach (string u in users)
                    {
                        userList.Add(new UserInfo() { IID = u });
                    }
                }
                ug.Users = userList.ToArray();

                if (add)
                {
                    UserManagement.AddGroup(ug);
                }
                else
                {
                    UserManagement.UpdateGroup(ug);
                }
                return null;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        public object[] GetUsersAndGroups()
        {
            // get users
            var users = FICHostEnvironment.GetUsers().Where(u => u.UserType < FICUserTypes.Admin);
            var groups = SearchLocalGroups("");

            return new object[]
            {
                users,
                groups
            };
        }

        public UserGroupSimple[] SearchLocalGroups(string prefix)
        {
            return UserManagement.SearchLocalGroups(prefix).OrderBy(m => m.UserGroupName).ToArray();
        }

        public UserSimple[] GetPermissionUsers()
        {
            List<UserSimple> userSimples = new List<UserSimple>();

            UserInfoItem[] userInfos = UserManagement.GetPermissionUsers();

            foreach (var userInfo in userInfos)
            {
                UserSimple user = new UserSimple();
                user.IID = userInfo.IID;
                user.UserID = userInfo.ID;
                user.UserName = userInfo.DisplayName;
                userSimples.Add(user);
            }

            return userSimples.OrderBy(m => m.UserID).ToArray();
        }

        public UserPermissionData[] GetUserOrGroupPermission(string UserOrGroup, string objIID)
        {
            return UserManagement.GetUserOrGroupPermission(UserOrGroup, objIID, CurrentUserIID, ClientLanguage);
        }

        #region - System Options -

        public void SaveConnectorConfigs(string[] configs)
        {
            if (configs != null)
            {
                SystemParams.SetFICStringParameter("ConnectorServer", configs[0] ?? "");
                SystemParams.SetFICStringParameter("ConnectorToken", configs[1] ?? "");
            }
        }

        public void SaveLDAPConnector(string[] configs)
        {
            if (configs != null)
            {
                SystemParams.SetFICStringParameter("LdapAgentID", configs[0] ?? "");
                SystemParams.SetFICStringParameter("LdapAgentToken", configs[1] ?? "");
            }
        }

        public void SaveRedisConfigs(bool enabled, string token)
        {
            if (token != null)
            {
                token = token.Replace('\n', ';');
            }
            SystemParams.SetFICStringParameter("RedisEnabled", enabled ? "Yes" : "No");
            SystemParams.SetFICStringParameter("RedisToken", token);
        }

        public object GetRedisConfigs()
        {
            return new
            {
                Enabled = SystemParams.RedisEnabled,
                RedisToken = SystemParams.RedisToken
            };
        }

        #endregion
    }
}
