using AutoMapper;
using Serwer.Core.Domain;
using Serwer.Core.Repositories;
using Serwer.Infrastructure.DTO;
using Serwer.Infrastructure.Mappers;
using Serwer.Infrastructure.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Serwer.Infrastructure.Services
{
    public class UserService: IUserService
    {
        private readonly IUserRepository _userRepository;
        private readonly IJwtHandler _jwtHandler;
        private readonly IMapper _mapper;

        public UserService(IUserRepository userRepository, IJwtHandler jwtHandler, IMapper mapper)
        {
            _userRepository = userRepository;
            _jwtHandler = jwtHandler;
            _mapper = mapper;
        }

        public async Task RegisterAsync(string email, string name, string surname, string login, string password)
        {
            if(await _userRepository.GetAsync(login) != null)
            {
                throw new Exception($"Użytkownik z loginem: {login} już istnieje.");
            }
            var user = new User(Guid.NewGuid(), email, name, surname, login, password);
            await _userRepository.AddAsync(user);
        }

        public async Task<SignedUserDto> SignInAsync(string login, string password)
        {
            var user = await _userRepository.GetAsync(login);
            if(user == null)
            {
                throw new Exception("Nie znaleziono użytkownika.");
            }
            if(user.Password != password)
            {
                throw new Exception("Hasło niepoprawne.");
            }

            var jwt = _jwtHandler.CreateToken(user.Id);

            return new SignedUserDto()
            {
                User = _mapper.Map<UserDto>(user),
                Jwt = _mapper.Map<JwtDto>(jwt)
            };
        }

        public async Task<UserDto> UpdateAsync(UpdateUserModel userModel)
        {
            var user = await _userRepository.GetAsync(userModel.Id);
            if(user == null)
            {
                throw new Exception("Nie znaleziono użytkownika.");
            }
            var userLoginTaken = await _userRepository.GetAsync(userModel.Login);
            if(userLoginTaken != null && userLoginTaken.Id != user.Id)
            {
                throw new Exception("Login jest już zajęty.");
            }

            var newUser = new User(user.Id, userModel.Email, userModel.Name, userModel.Surname, userModel.Login, user.Password);
            await _userRepository.UpdateAsync(newUser);
            newUser = await _userRepository.GetAsync(user.Id);
            return _mapper.Map<UserDto>(newUser);
        }
    }
}