using AutoMapper;
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
using DigitalData.UserManager.Domain.Entities;
using DigitalData.UserManager.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;

namespace DigitalData.UserManager.Application.Services
{
    public class UserService : BaseService<IUserRepository, UserCreateDto, UserReadDto, UserUpdateDto, User>, IUserService
    {
        private readonly IStringLocalizer<Resource> _localizer;
        public UserService(IUserRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper) : base(repository, mapper)
        {
            _localizer = localizer;
        }

        public async Task<DataResult<IEnumerable<UserReadDto>>> ReadByModuleIdAsync(int moduleId)
        {
            var users = await _repository.ReadByModuleIdAsync(moduleId);
            IEnumerable<UserReadDto> readDTOs = _mapper.Map<IEnumerable<UserReadDto>>(users);
            return Result.Success(readDTOs);
        }

        public async Task<DataResult<IEnumerable<UserReadDto>>> ReadByGroupIdAsync(int groupId)
        {
            var users = await _repository.ReadByGroupIdAsync(groupId);
            IEnumerable<UserReadDto> readDTOs = _mapper.Map<IEnumerable<UserReadDto>>(users);
            return Result.Success(readDTOs);
        }

        public async Task<DataResult<IEnumerable<UserReadDto>>> ReadUnassignedByModuleIdAsync(int moduleId)
        {
            var users = await _repository.ReadUnassignedByModuleIdAsync(moduleId);
            IEnumerable<UserReadDto> readDTOs = _mapper.Map<IEnumerable<UserReadDto>>(users);
            return Result.Success(readDTOs);
        }

        public async Task<DataResult<IEnumerable<UserReadDto>>> ReadUnassignedByGroupIdAsync(int groupId)
        {
            var users = await _repository.ReadUnassignedByGroupIdAsync(groupId);
            IEnumerable<UserReadDto> readDTOs = _mapper.Map<IEnumerable<UserReadDto>>(users);
            return Result.Success(readDTOs);
        }

        public async Task<DataResult<int>> CreateAsync(UserPrincipalDto upDto)
        {
            var user = _mapper.Map<User>(upDto);

            if (await HasEntity(user.Id))
                return Result.Fail<int>().Message(_localizer[Key.UserAlreadyExists]);

            //set the user
            var current_user = await GetUserAsync();
            user.AddedWho = current_user?.Username ?? "UNAUTHORIZED";

            var createdUser = await _repository.CreateAsync(user);
            if (createdUser is null)
                return Result.Fail<int>();
            else
                return Result.Success(createdUser.Id);
        }

        public async Task<DataResult<UserReadDto>> ReadByUsernameAsync(string username)
        {
            var user = await _repository.ReadByUsernameAsync(username);
            if (user is null)
                return Result.Fail<UserReadDto>().Message(_localizer[Key.UserNotFoundInLocalDB]);

            var userDto = _mapper.Map<UserReadDto>(user);
            return Result.Success(userDto);
        }
    }
}