using skydiveLogs_api.Domain;
using skydiveLogs_api.DomainBusiness.Interfaces;
using skydiveLogs_api.DomainService.Repositories;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace skydiveLogs_api.DomainBusiness
{
    public class UserService : IUserService
    {
        #region Public Constructors

        public UserService(IUserRepository userRepository,
                           IGearService gearService)
        {
            _userRepository = userRepository;
            _gearService = gearService;
        }

        #endregion Public Constructors

        #region Public Methods

        public bool AddNewUser(User newUser, bool isAdmin = false)
        {
            newUser.Password = EncryptPassword(newUser.Password);
            var foundUser = _userRepository.GetByLogin(newUser.Login, newUser.Password);
            var result = false;

            if (foundUser == null)
            {
                newUser.IsAdmin = isAdmin;
                var newUserId = _userRepository.Add(newUser);
                result = (newUserId > 0);

                if (result)
                {
                    newUser.Id = newUserId;
                    _gearService.AddRentalGear(newUser);
                }
            }

            return result;
        }

        public User GetById(int userId)
        {
            return _userRepository.GetById(userId);
        }

        public User GetByLogin(string login, string password)
        {
            return _userRepository.GetByLogin(login, EncryptPassword(password));
        }

        #endregion Public Methods

        #region Private Methods

        private string EncryptPassword(string password)
        {
            var encryptionKey = "skydivelogsangular";  //we can change the code converstion key as per our requirement
            byte[] clearBytes = Encoding.Unicode.GetBytes(password);
            var encryptedPassword = string.Empty;

            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(encryptionKey,
                                                                new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length);
                        cs.Close();
                    }

                    encryptedPassword = Convert.ToBase64String(ms.ToArray());
                }
            }

            return encryptedPassword;
        }

        #endregion Private Methods

        #region Private Fields

        private readonly IGearService _gearService;
        private readonly IUserRepository _userRepository;

        #endregion Private Fields
    }
}