using HRD.LDAPService.JWT;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json.Serialization;

namespace HRD.LDAPService
{
    public class LdapUser
    {
        private const string PASSWORD_HASH_SHORT = "PasswordHashShort";

        public bool IsRealLDAPUser { get; set; }

        public LdapUser()
        {
        }

        public LdapUser(string loginName)
        {
            LoginName = loginName;
        }

        public LdapUser(string loginname, int userId, string password, int departmentId, string extendedDepartmentIdList, List<KeyValuePair<string, string>> extendedAttributesList = null) : base()
        {
            LoginName = loginname;
            UserId = userId;
            Password = password;
            DepartmentId = departmentId;
            ExtendedDepartmentIdList = extendedDepartmentIdList;
            ExtendedAttributesList = extendedAttributesList == null ? new List<KeyValuePair<string, string>>() : extendedAttributesList;
        }

        public LdapUser(string loginname, int userId, string password)
        {
            LoginName = loginname;
            UserId = userId;
            Password = password;
        }

        #region Ldap Fields

        public Guid? LdapGuid { get; internal set; }
        public string LdapName { get; set; }
        public string LdapSurname { get; set; }

        #endregion Ldap Fields

        public int DepartmentId { get; set; }
        public bool IsValidatCredentials { get; set; }

        public string Email
        {
            get; set; // { return $"{LoginName}@hensel-recycling.com"; }
        }

        public string ExtendedDepartmentIdList { get; set; }
        public DateTime JwtExpiredOn { get; set; }

        [Required]
        public string LoginName { get; set; }

        [JsonIgnore]
        public string Password { get; set; }

        [JsonIgnore]
        public string PasswordHash { get; set; }

        public List<KeyValuePair<string, string>> ExtendedAttributesList { get; set; } = new List<KeyValuePair<string, string>>();
        public List<JwtRole> RoleList { get; set; } = new List<JwtRole>();
        public string Token { get; set; }
        public int UserId { get; set; }
        public int BadLogonCount { get; set; }
        public DateTime? LastBadPasswordAttempt { get; internal set; }

        public string PasswordHashShort
        {
            get
            {
                if (PasswordHash?.Length <= 10) { return string.Empty; };

                return PasswordHash.Substring(PasswordHash.Length - 10);
            }
        }

        public string GetLastBadPasswordAttemptAsLocalTime()
        {
            if (LastBadPasswordAttempt == null)
            {
                return string.Empty;
            }

            return ((DateTime)LastBadPasswordAttempt).ToLocalTime().ToLongTimeString();
        }

        public void AddPasswordHash(string passwordHash)
        {
            PasswordHash = passwordHash;

            if (!ExistsExtendedAttributeValue(PASSWORD_HASH_SHORT))
            {
                AddExtendedAttribute(PASSWORD_HASH_SHORT, PasswordHashShort);
            }
        }

        public string GetExtendedAttributePasswordHash()
        {
            return GetExtendedAttributeValue(PASSWORD_HASH_SHORT);
        }

        public bool ExistsExtendedAttributeValue(string key)
        {
            foreach (var item in ExtendedAttributesList)
            {
                if (item.Key == key) { return true; }
            }

            return false;
        }

        public string GetExtendedAttributeValue(string key)
        {
            foreach (var item in ExtendedAttributesList)
            {
                if (item.Key == key) { return item.Value; }
            }

            return string.Empty;
        }

        public string GetAccountLockoutTimeAsLocalTime()
        {
            if (AccountLockoutTime == null)
            {
                return string.Empty;
            }

            return ((DateTime)AccountLockoutTime).ToLocalTime().ToLongTimeString();
        }

        public bool IsAccountLockedOut { get; internal set; }
        public DateTime? AccountLockoutTime { get; internal set; }
        public bool Enabled { get; set; }

        public static bool IsJwtGlobalsRole(string roleName)
        {
            //TODO: Import them from db or config (etc. appsettigns.json)
            return string.Equals(roleName, JwtGlobals.ROLE_USER, StringComparison.OrdinalIgnoreCase)
                || string.Equals(roleName, JwtGlobals.ROLE_DEPARTMENTUSER, StringComparison.OrdinalIgnoreCase)
                || string.Equals(roleName, JwtGlobals.ROLE_DEPARTMENTMASTER, StringComparison.OrdinalIgnoreCase)
                || string.Equals(roleName, JwtGlobals.ROLE_MASTER, StringComparison.OrdinalIgnoreCase)
                || string.Equals(roleName, JwtGlobals.ROLE_ADMIN, StringComparison.OrdinalIgnoreCase)
                || string.Equals(roleName, JwtGlobals.ROLE_DD_ADMIN, StringComparison.OrdinalIgnoreCase);
        }

        public void AddExtendedAttribute(string key, string value)
        {
            ExtendedAttributesList.Add(new KeyValuePair<string, string>(key, value));
        }

        public void AddRole(JwtRole jwtRole)
        {
            if (!RoleList.Exists(x => x.Role == jwtRole.Role && x.Group == jwtRole.Group))
            {
                RoleList.Add(jwtRole);
            }
        }

        public void AddRole(string role)
        {
            if (!string.IsNullOrEmpty(role) && !RoleList.Exists(x => x.Role == role))
            {
                RoleList.Add(new JwtRole(role));
            }
        }

        public List<int> DepartmentIdListAll()
        {
            List<int> list = new List<int>() { DepartmentId };

            if (!string.IsNullOrEmpty(ExtendedDepartmentIdList))
            {
                List<int> extendetList = ExtendedDepartmentIdList.Split(',').Select(x => int.Parse(x.Trim())).ToList();

                list = list.Union(extendetList).ToList();
            }
            return list;
        }

        public bool IsAdmin()
        {
            return IsExistsRole(JwtGlobals.ROLE_ADMIN);
        }

        public bool IsDepartmentMaster()
        {
            return IsExistsRole(JwtGlobals.ROLE_DEPARTMENTMASTER);
        }

        public bool IsDepartmentUser()
        {
            return IsExistsRole(JwtGlobals.ROLE_DEPARTMENTUSER);
        }

        public bool IsExistsRole(string role)
        {
            return RoleList.Exists(x => String.Equals(x.Role, role, StringComparison.OrdinalIgnoreCase));
        }

        public bool IsMaster()
        {
            return IsExistsRole(JwtGlobals.ROLE_MASTER);
        }

        public bool IsUser()
        {
            return IsExistsRole(JwtGlobals.ROLE_USER);
        }

        public bool IsValid()
        {
            if (IsRealLDAPUser)
            {
                return !string.IsNullOrEmpty(LoginName)
                    //&& RoleList.Count > 0
                    && (LdapGuid != null)
                    && Enabled
                    && IsValidatCredentials;
            }
            else
            {
                return !string.IsNullOrEmpty(LoginName)
                    && Enabled
                    && IsValidatCredentials;
            }
        }

        public string RoleListAsString(EN_LdapRoleListFilter filter = EN_LdapRoleListFilter.All)
        {
            List<string> resultList = new List<string>();
            foreach (var item in RoleList)
            {
                switch (filter)
                {
                    case EN_LdapRoleListFilter.All:
                        resultList.Add(item.Role);
                        break;

                    case EN_LdapRoleListFilter.OnlyRoleList:
                        if (IsJwtGlobalsRole(item.Role)){ resultList.Add(item.Role); }
                        break;

                    case EN_LdapRoleListFilter.OnlyWebAppRoleList:
                        if (!IsJwtGlobalsRole(item.Role)) { resultList.Add(item.Role); }
                        break;

                    default:
                        break;
                }
            }
            return string.Join(",", resultList);
        }

        public override string ToString()
        {
            return $"{this.LoginName}; Roles: {RoleList.Count}; ExtendedDepartmentIdList: {ExtendedDepartmentIdList}, ExtendedAttributesList: {ExtendedAttributesList} ";
        }
    }
}