using AutoMapper;
using DataAccessLayer;
using DataAccessLayer.Entities;
using DataAccessLayer.Filtering;
using DataAccessLayer.Units;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using WcfServices.Authorization;
using WcfServices.Contract;
using WcfServices.Dto;
using WcfServices.Mapping;

namespace WcfServices.Services
{
    public partial class ISService : IUserService
    {

        [PrincipalPermission(SecurityAction.Demand, Role = "VIEW_EMPLOYEES")]
        public async Task<IEnumerable<UserDto>> GetUsersAsync(FilterDto filterDto)
        {
            var retval = new List<UserDto>();
            using (var userUnit = new UnitOfWork<User>(new ISDbContext()))
            {
                var filter = _mapper.Map<Filter>(filterDto);
                var users = await userUnit.GetAsync(filter);

                foreach(var user in users)
                {
                    retval.Add(_mapper.Map<UserDto>(user));
                }
            }

            return retval;
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "VIEW_EMPLOYEES")]
        public async Task<UserDto> GetUserByIdAsync(int id)
        {
            UserDto retval;
            using (var userUnit = new UnitOfWork<User>(new ISDbContext()))
            {
                var user = await userUnit.GetByIdAsync(id);

                retval = _mapper.Map<UserDto>(user);
            }

            return retval;
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "BASIC_ACCESS")]
        public async Task<UserDto> LoginAsync(string userName)
        {
            UserDto retval;
            using (var userUnit = new UnitOfWork<User>(new ISDbContext()))
            {
                var filter = new Filter()
                {
                    Conditions = new List<ConditionItem>()
                     {
                          new ConditionItem()
                          {
                               Column = nameof(UserDto.Login),
                               Type = ConditionTypeEnum.Equal,
                               Value = userName
                          }
                     }
                };
                var users = await userUnit.GetAsync(filter);

                var user = users.FirstOrDefault();

                if (user == null)
                    return null;

                retval = _mapper.Map<UserDto>(user);
            }

            return retval;
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "EDIT_EMPLOYEES")]
        public async Task CreateUserAsync(UserDto userDto)
        {
            using (var userUnit = new UnitOfWork<User>(new ISDbContext()))
            {
                var user = _mapper.Map<User>(userDto);
                user.Employee = null;
                user.Roles = null;
                user.PasswordHash = PasswordHelper.GeneratePasswordHash(userDto.Password);
                await userUnit.CreateAsync(user);
            }
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "BASIC_ACCESS")]
        public async Task UpdateUserAsync(UserDto userDto)
        {
            using (var userUnit = new UnitOfWork<User>(new ISDbContext()))
            {
                var user = _mapper.Map<User>(userDto);
                user.Employee = null;
                user.Roles = null;
                user.PasswordHash = PasswordHelper.GeneratePasswordHash(userDto.Password);
                await userUnit.UpdateAsync(user);
            }
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "EDIT_EMPLOYEES")]
        public async Task UpdateUserWithRolesAsync(UserDto userDto, IEnumerable<int> roleIds)
        {
            using (var userUnit = new UserRoleUnit(new ISDbContext()))
            {
                var user = _mapper.Map<User>(userDto);
                user.Employee = null;
                user.Roles = null;
                await userUnit.UpdateWithRolesAsync(user, roleIds);
            }
        }


        [PrincipalPermission(SecurityAction.Demand, Role = "EDIT_EMPLOYEES")]
        public async Task DeleteUserAsync(int id)
        {
            using (var userUnit = new UnitOfWork<User>(new ISDbContext()))
            {
                await userUnit.DeleteAsync(id);
            }
        }

    }
}
