using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WorkFlowCheck.Common.DTO;
using WorkFlowCheck.BL.Services.Interfaces;
using WorkFlowCheck.DL;
using WorkFlowCheck.Common.Security;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using WorkFlowCheck.DL.Entities;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Identity;
using WorkFlowCheck.BL.Static;
using System.Reflection;

namespace WorkFlowCheck.BL.Services
{
    public class UserService : BaseService, IUserService
    {
        private IConfiguration _configuration;
        private IMessageService _messageService;

        public UserService(AppDbContext dbContext,
                           IMapper mapper,
                           IConfiguration configuration,
                           IMessageService messageService) : base(dbContext, mapper)
        {

            _configuration = configuration;
            _messageService = messageService;
        }

        public async Task<UserDTO> GetUserAsync(int Id)
        {
            var retVal = new UserDTO() { RoleDTO = new List<RoleDTO>() };

            try
            {
                var user = await _dbContext.Users
                    .Include(i => i.UserRoles)
                    .ThenInclude(i => i.Role)
                    .Where(w => w.Id == Id).FirstOrDefaultAsync();
                if (user != null)
                {
                    retVal = _mapper.Map<UserDTO>(user);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<List<UserDTO>> GetAllUserAsync()
        {
            var retVal = new List<UserDTO>
                {
                    new UserDTO
                    {
                        RoleDTO = new List<RoleDTO>()
                    }
                };
            try
            {
                var users = await _dbContext.Users
                                            .Include(i => i.UserRoles)
                                            .ThenInclude(i => i.Role)
                                            .ToListAsync();
                if (users != null)
                {
                    retVal = _mapper.Map<List<UserDTO>>(users);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<bool> DeleteUserAsync(int id)
        {
            return await DeleteEntityByIdAsync<User>(id);
        }
        public async Task<UserDTO> Authenticate(string userName, string password)
        {
            var retVal = new UserDTO() { RoleDTO = new List<RoleDTO>() };

            try
            {
                Log.ForContext("TAG", "AuditFlow").Information($"Bejelentkezési kísérlet: {userName}");
                var user = await _dbContext.Users
                    .Include(i => i.UserRoles)
                    .ThenInclude(i => i.Role)
                    .Where(w => w.UserName == userName && w.Active != false)
                    .FirstOrDefaultAsync();
                if (user != null && PasswordHasher.VerifyPassword(user.PasswordHash, password))
                {
                    var userDTO = new UserDTO()
                    {
                        Id = user.Id,
                        UserName = user.UserName,
                        RoleDTO = new List<RoleDTO>(),
                    };
                    foreach (var item in user.UserRoles)
                    {
                        userDTO.RoleDTO.Add(new RoleDTO()
                        {
                            Id = item.Role.Id,
                            RoleName = item.Role.RoleName,
                        });
                    }
                    user.JwtToken = GenerateJwtToken(userDTO);
                    await _dbContext.SaveChangesAsync();
                    Log.ForContext("TAG", "AuditFlow").Information($"Sikeres bejelentkezés: {userName}");
                    retVal = _mapper.Map<UserDTO>(user);
                }
                else
                {
                    Log.ForContext("TAG", "AuditFlow").Error($"Sikertelen bejelenkezési kísérlet: {userName}");
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<string> Authenticate2F1(string userName, string password)
        {
            var retVal = "";
            try
            {
                Log.ForContext("TAG", "AuditFlow").Information($"Bejelentkezési kísérlet: {userName}");

                var user = await _dbContext.Users
                    .Include(i => i.UserRoles)
                    .ThenInclude(i => i.Role)
                    .Where(w => w.UserName == userName)
                    .FirstOrDefaultAsync();
                if (user != null && PasswordHasher.VerifyPassword(user.PasswordHash, password))
                {
                    var canUseWebAdmin = false;
                    foreach (var userRole in user.UserRoles)
                    {
                        if (userRole.Role.CanUseWebAdmin)
                        {
                            canUseWebAdmin = true;
                            break;
                        }
                    }

                    if (!string.IsNullOrEmpty(user.Email) && canUseWebAdmin)
                    {
                        var code = CodeGenerator2F.GenerateSixDigitCode();

                        await _messageService.SendMailAsync(new List<string>()
                                                {
                                                   user.Email,
                                                }, "Bejelentkezés megerősítése",
                                                Get2FConfirmationMessageBody(code));
                        Log.ForContext("TAG", "AuditFlow").Information($"Bejelentkezési kísérlet, email küldés: {user.Email}");
                        retVal = CodeGenerator2F.GenerateToken2F(userName, password, code);
                        return retVal;
                    }
                    else
                    {
                        Log.ForContext("TAG", "AuditFlow").Information($"A WEB felület NEM használható!: {userName}");
                    }
                }
                else
                {
                    Log.ForContext("TAG", "AuditFlow").Error($"Sikertelen bejelentkezési kísérlet: {userName}");
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<UserDTO> Authenticate2F2(string userName, string password, string code, string token2FA)
        {
            var retVal = new UserDTO() { RoleDTO = new List<RoleDTO>() };
            try
            {
                var user = await _dbContext.Users
                    .Include(i => i.UserRoles)
                    .ThenInclude(i => i.Role)
                    .Where(w => w.UserName == userName && w.Active != false)
                    .FirstOrDefaultAsync();
                if (user != null && PasswordHasher.VerifyPassword(user.PasswordHash, password))
                {
                    if (CodeGenerator2F.ValidateToken2F(token2FA, userName, password, code))
                    {
                        var userDTO = new UserDTO()
                        {
                            Id = user.Id,
                            UserName = user.UserName,
                            RoleDTO = new List<RoleDTO>(),
                        };
                        foreach (var item in user.UserRoles)
                        {
                            userDTO.RoleDTO.Add(new RoleDTO()
                            {
                                Id = item.Role.Id,
                                RoleName = item.Role.RoleName,
                            });
                        }
                        user.JwtToken = GenerateJwtToken(userDTO);
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<UserDTO>(user);
                        Log.ForContext("TAG", "AuditFlow").Information($"Sikeres 2FA azonosítás!: {userName}");
                        return retVal;
                    }
                }
                else
                {
                    Log.ForContext("TAG", "AuditFlow").Error($"Sikertelen 2FA bejelentkezési kísérlet: {userName}");
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;


        }
        public async Task<UserDTO> Authenticate2F2ChangePassword(string userName, string oldPassword, string newPassword, string code, string token2FA)
        {
            var retVal = new UserDTO() { RoleDTO = new List<RoleDTO>() };
            try
            {
                var user = await _dbContext.Users
                    .Include(i => i.UserRoles)
                    .ThenInclude(i => i.Role)
                    .Where(w => w.UserName == userName && w.Active != false)
                    .FirstOrDefaultAsync();
                if (user != null && PasswordHasher.VerifyPassword(user.PasswordHash, oldPassword))
                {
                    if (CodeGenerator2F.ValidateToken2F(token2FA, userName, oldPassword, code))
                    {
                        user.PasswordHash = PasswordHasher.HashPassword(newPassword);


                        var userDTO = new UserDTO()
                        {
                            Id = user.Id,
                            UserName = user.UserName,
                            RoleDTO = new List<RoleDTO>(),
                        };
                        foreach (var item in user.UserRoles)
                        {
                            userDTO.RoleDTO.Add(new RoleDTO()
                            {
                                Id = item.Role.Id,
                                RoleName = item.Role.RoleName,
                            });
                        }

                        user.PasswordHash = PasswordHasher.HashPassword(newPassword);
                        user.JwtToken = GenerateJwtToken(userDTO);
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<UserDTO>(user);
                        Log.ForContext("TAG", "AuditFlow").Information($"Sikeres jelszó módosítás: {userName}");
                        return retVal;
                    }
                }
                else
                {
                    Log.ForContext("TAG", "AuditFlow").Error($"Sikertelen jelszó módosítási kísérlet: {userName}");
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<UserDTO> AuthenticateNFC(string NFCCode)
        {
            var retVal = new UserDTO() { RoleDTO = new List<RoleDTO>() };

            try
            {
                var user = await _dbContext.Users
                    .Include(i => i.UserRoles)
                    .ThenInclude(i => i.Role)
                    .Where(w => w.NFCCode == NFCCode && w.NFCActive == true)
                    .FirstOrDefaultAsync();
                if (user != null)
                {

                    var userDTO = new UserDTO()
                    {
                        Id = user.Id,
                        UserName = user.UserName,
                        RoleDTO = new List<RoleDTO>(),
                    };
                    foreach (var item in user.UserRoles)
                    {
                        userDTO.RoleDTO.Add(new RoleDTO()
                        {
                            Id = item.Role.Id,
                            RoleName = item.Role.RoleName,
                        });
                    }
                    user.JwtToken = GenerateJwtToken(userDTO);
                    await _dbContext.SaveChangesAsync();
                    Log.ForContext("TAG", "AuditFlow").Information($"Sikeres NFC kártya azonosítás kísérlet: {user.UserName}");
                    retVal = _mapper.Map<UserDTO>(user);
                }
                else
                {
                    Log.ForContext("TAG", "AuditFlow").Error($"Sikertelen NFC kártya azonosítás: {NFCCode}");
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public string GenerateJwtToken(UserDTO userDTO)
        {
            var jwtSettings = _configuration.GetSection("Jwt");
            var secretKey = jwtSettings["SecretKey"];
            var issuer = jwtSettings["Issuer"];
            var audience = jwtSettings["Audience"];
            var tokenLifetime = int.Parse(jwtSettings["TokenLifetimeMinutes"]);

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, userDTO.UserName),
                new Claim(ClaimTypes.NameIdentifier, userDTO.Id.ToString())
            };

            foreach (var role in userDTO.RoleDTO)
            {
                claims.Add(new Claim(ClaimTypes.Role, role.RoleName));
            }

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                claims: claims,
                expires: DateTime.UtcNow.AddMinutes(tokenLifetime),
                signingCredentials: creds);

            return new JwtSecurityTokenHandler().WriteToken(token);
        }
        public async Task<UserDTO> UpdateUserAsync(UserDTO userDTO)
        {
            var retVal = new UserDTO() { RoleDTO = new List<RoleDTO>() };
            try
            {
                if (userDTO.Id == 0)
                {
                    var user = new User();
                    user.UserName = userDTO.UserName;
                    user.FirstName = userDTO.FirstName;
                    user.LastName = userDTO.LastName;
                    user.Email = userDTO.Email;
                    user.NFCActive = userDTO.NFCActive;
                    user.NFCCode = userDTO.NFCCode;
                    user.JwtToken = "";
                    user.Token2FA = "";
                    user.IsDeleted = false;
                    user.Active = userDTO.Active;


                    user.PasswordHash = PasswordHasher.HashPassword(userDTO.Password);


                    _dbContext.Users.Add(user);
                    await _dbContext.SaveChangesAsync();

                    retVal = _mapper.Map<UserDTO>(user);
                }
                else
                {
                    var user = await _dbContext.Users.Where(w => w.Id == userDTO.Id).FirstOrDefaultAsync();

                    if (user != null)
                    {
                        user.UserName = userDTO.UserName;
                        user.FirstName = userDTO.FirstName;
                        user.LastName = userDTO.LastName;
                        user.Email = userDTO.Email;
                        user.Active = userDTO.Active;
                        user.NFCActive = userDTO.NFCActive;
                        user.NFCCode = userDTO.NFCCode;
                        
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<UserDTO>(user);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        private string Get2FConfirmationMessageBody(string token2F)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var resourceName = "WorkFlowCheck.BL.HtmlTemplates.Token2FBody.html";

            using var stream = assembly.GetManifestResourceStream(resourceName);
            if (stream == null)
                throw new FileNotFoundException($"Nem található a beágyazott erőforrás: {resourceName}");

            using var reader = new StreamReader(stream);
            var html = reader.ReadToEnd();
            return html.Replace("#token2F#", token2F);
        }

        public async Task<RoleDTO> GetRoleAsync(int Id)
        {
            var retVal = new RoleDTO();

            try
            {
                var user = await _dbContext.Roles.Where(w => w.Id == Id).FirstOrDefaultAsync();
                if (user != null)
                {
                    retVal = _mapper.Map<RoleDTO>(user);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<List<RoleDTO>> GetAllRoleAsync()
        {
            var retVal = new List<RoleDTO>();
            try
            {
                var roles = await _dbContext.Roles.ToListAsync();
                if (roles != null)
                {
                    retVal = _mapper.Map<List<RoleDTO>>(roles);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<bool> DeleteRoleAsync(int id)
        {
            return await DeleteEntityByIdAsync<Role>(id);
        }
        public async Task<RoleDTO> UpdateRoleAsync(RoleDTO roleDTO)
        {
            var retVal = new RoleDTO();
            try
            {
                if (roleDTO.Id == 0)
                {
                    var role = new Role();
                    role.RoleName = roleDTO.RoleName;
                    if (roleDTO.ParentId > 0)
                    {
                        role.ParentId = roleDTO.ParentId;
                    }
                    role.IsAdmin = roleDTO.IsAdmin;
                    role.CanDownloadAPK = roleDTO.CanDownloadAPK;
                    role.CanEnableBlocked = roleDTO.CanEnableBlocked;
                    role.CanUseWebAdmin = roleDTO.CanUseWebAdmin;
                    role.CanUseMobilApp = roleDTO.CanUseMobilApp;
                    _dbContext.Roles.Add(role);
                    await _dbContext.SaveChangesAsync();

                    retVal = _mapper.Map<RoleDTO>(role);
                }
                else
                {
                    var role = await _dbContext.Roles.Where(w => w.Id == roleDTO.Id).FirstOrDefaultAsync();

                    if (role != null)
                    {
                        role.RoleName = roleDTO.RoleName;
                        if (roleDTO.ParentId > 0)
                        {
                            role.ParentId = roleDTO.ParentId;
                        }
                        role.IsAdmin = roleDTO.IsAdmin;
                        role.CanDownloadAPK = roleDTO.CanDownloadAPK;
                        role.CanEnableBlocked = roleDTO.CanEnableBlocked;
                        role.CanUseWebAdmin = roleDTO.CanUseWebAdmin;
                        role.CanUseMobilApp = roleDTO.CanUseMobilApp;
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<RoleDTO>(role);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<UserRoleDTO> GetUserRoleAsync(int Id)
        {
            var retVal = new UserRoleDTO();

            try
            {
                var userRole = await _dbContext.UserRoles.Where(w => w.Id == Id).FirstOrDefaultAsync();
                if (userRole != null)
                {
                    retVal = _mapper.Map<UserRoleDTO>(userRole);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<List<UserRoleDTO>> GetAllUserRoleAsync()
        {
            var retVal = new List<UserRoleDTO>();
            try
            {
                var userRoles = await _dbContext.UserRoles
                    .Include(i => i.User)
                    .Include(i => i.Role)
                    .AsNoTracking()
                    .ToListAsync();
                if (userRoles != null)
                {
                    retVal = _mapper.Map<List<UserRoleDTO>>(userRoles);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<bool> DeleteUserRoleAsync(int id)
        {
            return await DeleteEntityByIdAsync<UserRole>(id);
        }
        public async Task<UserRoleDTO> UpdateUserRoleAsync(UserRoleDTO userRoleDTO)
        {
            var retVal = new UserRoleDTO();
            try
            {
                if (userRoleDTO.Id == 0)
                {
                    var userRole = new UserRole();
                    userRole.UserId = userRoleDTO.UserId;
                    userRole.RoleId = userRoleDTO.RoleId;

                    _dbContext.UserRoles.Add(userRole);
                    await _dbContext.SaveChangesAsync();

                    retVal = _mapper.Map<UserRoleDTO>(userRole);
                }
                else
                {
                    var userRole = await _dbContext.UserRoles.Where(w => w.Id == userRoleDTO.Id).FirstOrDefaultAsync();

                    if (userRole != null)
                    {
                        userRole.UserId = userRoleDTO.UserId;
                        userRole.RoleId = userRoleDTO.RoleId;
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<UserRoleDTO>(userRole);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<RoleCheckListTemplateHeaderDTO> GetRoleCheckListTemplateHeaderAsync(int Id)
        {
            var retVal = new RoleCheckListTemplateHeaderDTO();

            try
            {
                var userRole = await _dbContext.RoleCheckListTemplateHeaders.Where(w => w.Id == Id).FirstOrDefaultAsync();
                if (userRole != null)
                {
                    retVal = _mapper.Map<RoleCheckListTemplateHeaderDTO>(userRole);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<List<RoleCheckListTemplateHeaderDTO>> GetAllRoleCheckListTemplateHeadersAsync()
        {
            var retVal = new List<RoleCheckListTemplateHeaderDTO>();
            try
            {
                var results = await _dbContext.RoleCheckListTemplateHeaders
                                        .Include(i => i.CheckListTemplateHeader)
                                        .Include(i => i.Role)
                                        .AsNoTracking()
                                        .ToListAsync();
                if (results != null)
                {
                    retVal = _mapper.Map<List<RoleCheckListTemplateHeaderDTO>>(results);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<bool> DeleteRoleCheckListTemplateHeaderAsync(int id)
        {
            return await DeleteEntityByIdAsync<RoleCheckListTemplateHeader>(id);
        }
        public async Task<RoleCheckListTemplateHeaderDTO> UpdateRoleCheckListTemplateHeaderAsync(RoleCheckListTemplateHeaderDTO roleCheckListTemplateHeaderDTO)
        {
            var retVal = new RoleCheckListTemplateHeaderDTO();
            try
            {
                if (roleCheckListTemplateHeaderDTO.Id == 0)
                {
                    var roleCheckListTemplateHeader_Exists = await _dbContext.RoleCheckListTemplateHeaders
                                                                             .Where(w => w.RoleId == roleCheckListTemplateHeaderDTO.RoleId &&
                                                                                         w.CheckListTemplateHeaderId == roleCheckListTemplateHeaderDTO.CheckListTemplateHeaderId)
                                                                             .FirstOrDefaultAsync();
                    if (roleCheckListTemplateHeader_Exists == null)
                    {
                        var roleCheckListTemplateHeader = new RoleCheckListTemplateHeader();
                        roleCheckListTemplateHeader.CheckListTemplateHeaderId = roleCheckListTemplateHeaderDTO.CheckListTemplateHeaderId;
                        roleCheckListTemplateHeader.RoleId = roleCheckListTemplateHeaderDTO.RoleId;
                        roleCheckListTemplateHeader.Enabled = roleCheckListTemplateHeaderDTO.Enabled;

                        _dbContext.RoleCheckListTemplateHeaders.Add(roleCheckListTemplateHeader);
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<RoleCheckListTemplateHeaderDTO>(roleCheckListTemplateHeader);
                    }
                    else
                    {
                        retVal = _mapper.Map<RoleCheckListTemplateHeaderDTO>(roleCheckListTemplateHeader_Exists);
                    }
                }
                else
                {
                    var roleCheckListTemplateHeader = await _dbContext.RoleCheckListTemplateHeaders.Where(w => w.Id == roleCheckListTemplateHeaderDTO.Id).FirstOrDefaultAsync();

                    if (roleCheckListTemplateHeader != null)
                    {
                        roleCheckListTemplateHeader.CheckListTemplateHeaderId = roleCheckListTemplateHeaderDTO.CheckListTemplateHeaderId;
                        roleCheckListTemplateHeader.RoleId = roleCheckListTemplateHeaderDTO.RoleId;
                        roleCheckListTemplateHeader.Enabled = roleCheckListTemplateHeaderDTO.Enabled;
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<RoleCheckListTemplateHeaderDTO>(roleCheckListTemplateHeader);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<RoleCheckPointDTO> GetRoleCheckPointAsync(int Id)
        {
            var retVal = new RoleCheckPointDTO();

            try
            {
                var userRole = await _dbContext.RoleCheckPoints.Where(w => w.Id == Id).FirstOrDefaultAsync();
                if (userRole != null)
                {
                    retVal = _mapper.Map<RoleCheckPointDTO>(userRole);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<List<RoleCheckPointDTO>> GetAllRoleCheckPointsAsync()
        {
            var retVal = new List<RoleCheckPointDTO>();
            try
            {
                var results = await _dbContext.RoleCheckPoints
                                        .Include(i => i.CheckPoint)
                                        .Include(i => i.Role)
                                        .AsNoTracking()
                                        .ToListAsync();
                if (results != null)
                {
                    retVal = _mapper.Map<List<RoleCheckPointDTO>>(results);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<bool> DeleteRoleCheckPointAsync(int id)
        {
            return await DeleteEntityByIdAsync<RoleCheckPoint>(id);
        }
        public async Task<RoleCheckPointDTO> UpdateRoleCheckPointAsync(RoleCheckPointDTO roleCheckPointDTO)
        {
            var retVal = new RoleCheckPointDTO();
            try
            {
                if (roleCheckPointDTO.Id == 0)
                {
                    var roleCheckPoint_Exists = await _dbContext.RoleCheckPoints
                                                                             .Where(w => w.RoleId == roleCheckPointDTO.RoleId &&
                                                                                         w.CheckPointId == roleCheckPointDTO.CheckPointId)
                                                                             .FirstOrDefaultAsync();
                    if (roleCheckPoint_Exists == null)
                    {
                        var roleCheckPoint = new RoleCheckPoint();
                        roleCheckPoint.CheckPointId = roleCheckPointDTO.CheckPointId;
                        roleCheckPoint.RoleId = roleCheckPointDTO.RoleId;
                        roleCheckPoint.Enabled = roleCheckPointDTO.Enabled;

                        _dbContext.RoleCheckPoints.Add(roleCheckPoint);
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<RoleCheckPointDTO>(roleCheckPoint);
                    }
                    else
                    {
                        retVal = _mapper.Map<RoleCheckPointDTO>(roleCheckPoint_Exists);
                    }
                }
                else
                {
                    var roleCheckPoint = await _dbContext.RoleCheckPoints.Where(w => w.Id == roleCheckPointDTO.Id).FirstOrDefaultAsync();

                    if (roleCheckPoint != null)
                    {
                        roleCheckPoint.CheckPointId = roleCheckPointDTO.CheckPointId;
                        roleCheckPoint.RoleId = roleCheckPointDTO.RoleId;
                        roleCheckPoint.Enabled = roleCheckPointDTO.Enabled;
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<RoleCheckPointDTO>(roleCheckPoint);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
    }
}
