using Newtonsoft.Json;
using System;
using WK_KLI_LAPS_Service.App_Data;
using WK_KLI_LAPS_Service.Hub;
using WK_KLI_LAPS_Service.Models.Master;

namespace WK_KLI_LAPS_Service.Controllers.Master.User
{
    public interface IUserService
    {
        userModel Authenticate(string username, string password);
        object GetAll();
        object GetRequestTypes();
        object GetById(int id);
        Int64 Logout(Int64 logid);
        Int64 Pendinglots(Int64 userid);
        userModel Add(userModel user);
        Int64 Addloginhistory(loginhistoryModel history);
        void Update(userModel user, string mode);
        void Delete(userModel user);
        void Resetpassword(userModel user);
        void Changepassword(userModel user);
        bool FindbyMailId_user(string mailid);
        object GetActiveUsers();
        object GetByuserId(int id);
        bool FindbyMailId_userupdate(string mailid, int userid);
        object GetByRoleId(userModel user);
        object GetUsersByDepartment(int departmentid);
        object GetUserRights(int id);
        object GetUserPending(int id);
        object Add_Mailfolder(usermailfoldermapping_model mailfolder);

        object GetMailFolderLst();

        object Add_userMailfolder(usermailfoldermapping_model mailfolder);
        object Update_userMailfolder(usermailfoldermapping_model mailfolder);
        object Update_foldername(usermailfoldermapping_model mailfolder);
        object Delete_mailfoldermapping(usermailfoldermapping_model mailfolder);

    }
    public class UserService : IUserService
    {
        UserRepository oUserRepository = new UserRepository();
        MasterRepository oMasterRepository = new MasterRepository();
        CommonRepository oCommonRepository = new CommonRepository();

        public userModel Authenticate(string Emailid, string password)
        {
            if (string.IsNullOrEmpty(Emailid) || string.IsNullOrEmpty(password))
                return null;
            var user = (userModel)oUserRepository.FindByEmail(Emailid);

            // check if username exists						   
            if (user == null)
                return null;

            // check if password is correct
            if (!VerifyPasswordHash(password, user.passwordhash, user.passwordsalt))
                return null;

            // authentication successful
            return user;
        }

        public object GetAll()
        {
            return oUserRepository.FindAll();
        }

        public object GetRequestTypes()
        {
            return oMasterRepository.GetAll("requesttype");
        }

        public object GetById(int id)
        {
            return oUserRepository.FindByID(id);
        }

        public object GetByuserId(int id)
        {
            return oUserRepository.FindByIdForUser(id);
        }



        public void Resetpassword(userModel user)
        {

            byte[] passwordHash, passwordSalt;
            CreatePasswordHash(user.password, out passwordHash, out passwordSalt);
            user.passwordhash = passwordHash;
            user.passwordsalt = passwordSalt;
            oUserRepository.Update(user, "resetpassword");

        }
        public void Changepassword(userModel user)
        {

            byte[] passwordHash, passwordSalt;
            CreatePasswordHash(user.password, out passwordHash, out passwordSalt);
            user.passwordhash = passwordHash;
            user.passwordsalt = passwordSalt;
            oUserRepository.Update(user, "changepassword");

        }
        public userModel Add(userModel user)
        {

            if (user.userrequest == 1)
            {
                oUserRepository.Add(user, "requestinsert");
            }
            else
            {
                byte[] passwordHash, passwordSalt;
                CreatePasswordHash(user.password, out passwordHash, out passwordSalt);
                user.passwordhash = passwordHash;
                user.passwordsalt = passwordSalt;
                oUserRepository.Add(user, "insert");
            }
            return user;
        }

        public void Update(userModel userParam, string mode)
        {


            var user = oUserRepository.FindByID(userParam.userid);

            if (user == null)
                throw new Exception("User not found");


            if (userParam.password != null || userParam.password != "")
            {
                byte[] passwordHash, passwordSalt;
                CreatePasswordHash(userParam.password, out passwordHash, out passwordSalt);
                userParam.passwordhash = passwordHash;
                userParam.passwordsalt = passwordSalt;
            }
            oUserRepository.Update(userParam, mode);

        }



        public void Delete(userModel user)
        {

            //var user_ = oUserRepository.FindByIdForUser(user.userid);
            //var s = JsonConvert.SerializeObject(user_);
            //JObject jObject = JObject.Parse(s);
            //var users = (dynamic)jObject.SelectToken("j");
            //user_ = JArray.Parse(users.Value)[0];
            //if (user_ != null)
            //{
            //    oUserRepository.Remove(user);

            //}
            oUserRepository.Remove(user);
        }


        private static void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
        {
            if (password == null) throw new ArgumentNullException("password");
            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentException("Value cannot be empty or whitespace only string.", "password");

            using (var hmac = new System.Security.Cryptography.HMACSHA512())
            {
                passwordSalt = hmac.Key;
                passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
            }
        }

        private static bool VerifyPasswordHash(string password, byte[] storedHash, byte[] storedSalt)
        {
            if (password == null) throw new ArgumentNullException("password");
            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentException("Value cannot be empty or whitespace only string.", "password");
            if (storedHash.Length != 64) throw new ArgumentException("Invalid length of password hash (64 bytes expected).", "passwordHash");
            if (storedSalt.Length != 128) throw new ArgumentException("Invalid length of password salt (128 bytes expected).", "passwordHash");

            using (var hmac = new System.Security.Cryptography.HMACSHA512(storedSalt))
            {
                var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
                for (int i = 0; i < computedHash.Length; i++)
                {
                    if (computedHash[i] != storedHash[i]) return false;
                }
            }

            return true;
        }
        public Int64 Addloginhistory(loginhistoryModel history)
        {
            return oUserRepository.Addloginhistory(history);
        }

        public Int64 Logout(Int64 loginid)
        {
            var loginhistory = (loginhistoryModel)oUserRepository.FindByLoginId(loginid);
            if (loginhistory != null)
            {
                AuthHub hub = new AuthHub();
                hub.logout(loginhistory.Userid.ToString());
                return oUserRepository.UpdateLoginHistory(loginid);
            }
            return 0;
        }
        public Int64 Pendinglots(Int64 userid)
        {
                return oUserRepository.UpdatePendinglots(userid);
        }
        public bool FindbyMailId_user(string mailid)
        {
            var res = oUserRepository.FindbyMailidForUser(mailid);
            return res;
        }
        public bool FindbyMailId_userupdate(string mailid, int userid)
        {
            var res = oUserRepository.FindbyMailidForUserUpdate(mailid, userid);
            return res;
        }
        public object GetActiveUsers()
        {
            return oUserRepository.FindActiveUsers();
        }


        public object GetByRoleId(userModel user)
        {

            string input = JsonConvert.SerializeObject(user);
            var result = oUserRepository.GetByRoleId(input);
            return result;
        }
        public object GetUsersByDepartment(int departmentid)
        {
            return oUserRepository.GetUsersByDepartment(departmentid);
        }
        public object GetUserRights(int id)
        {
            return oUserRepository.GetserRights(id);

        }
        public object GetUserPending(int id)
        {
            return oUserRepository.Getuserpendinglotinfo(id);

        }

        //gokul add 01-02-2023
        public object Add_Mailfolder(usermailfoldermapping_model mailfolder)
        {
            string input = JsonConvert.SerializeObject(mailfolder);
            return oUserRepository.Master_MailFollderMapping("spusrmailfoldermapping", input, "insert_folder");
        }

        public object GetMailFolderLst()
        {
            return oUserRepository.Master_MailFollderMapping("spusermailfoldermappingselect", "", "get_mailfoldermapping");
        }

        public object Add_userMailfolder(usermailfoldermapping_model mailfolder)
        {
            string input = JsonConvert.SerializeObject(mailfolder);
            return oUserRepository.Master_MailFollderMapping("spusrmailfoldermapping", input, "insert_userfolder");
        }
        public object Update_userMailfolder(usermailfoldermapping_model mailfolder)
        {
            string input = JsonConvert.SerializeObject(mailfolder);
            return oUserRepository.Master_MailFollderMapping("spusrmailfoldermapping", input, "update_userfolder");
        }
        public object Update_foldername(usermailfoldermapping_model mailfolder)
        {
            string input = JsonConvert.SerializeObject(mailfolder);
            return oUserRepository.Master_MailFollderMapping("spusrmailfoldermapping", input, "update_foldername");
        }
        public object Delete_mailfoldermapping(usermailfoldermapping_model mailfolder)
        {
            string input = JsonConvert.SerializeObject(mailfolder);
            return oUserRepository.Master_MailFollderMapping("spusrmailfoldermapping", input, "active_userfolder");
        }
    }
}
