/*
 * Created on 31. 7. 2017 16:49:36
 *
 */
package com.jh.radegast.security;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.jh.common.security.PasswordHash;
import com.jh.common.security.PasswordSecurity;
import com.jh.common.web.error.ErrorMessage;

/**
 * The Class AppUserService.
 *
 * @author Jan Hrabal
 */
@Service
public class AppUserService {

    /** The repo. */
    @Autowired
    private AppUserRepository repo;
    
//    @Autowired
//    private SuiteEmails suiteEmails;
    
    /**
     * Fetch user.
     *
     * @param email the email
     * @return the app user
     */
    @Transactional
    public AppUser fetchUser(String email) {
    	if (!StringUtils.hasText(email)) {
    		return null;
    	}
		return repo.findByEmailAndDeletedFalse(StringUtils.trimAllWhitespace(email));
    }
    
    /**
     * Find by email.
     *
     * @param email the email
     * @return the app user
     */
    @Transactional
    public AppUser findByEmail(String email) {
		return repo.findByEmail(email);
    }
    

	/**
	 * Save user.
	 *
	 * @param user the user
	 * @param locale the locale
	 */
	@Transactional
	public void createUser(AppUser user, Locale locale) {
		Objects.requireNonNull(user);
		if (locale == null) {
			locale = Locale.ENGLISH;
		}

		repo.save(user);
	}

	
	@Transactional
	public void updateUser(AppUser user) {
		Objects.requireNonNull(user);
		repo.save(user);
	}	
	
	@Transactional
	public List<ErrorMessage> changePassword(Long userId, String currentPassword, String newPassword, String newPasswordCheck) {
		List<ErrorMessage> errors = new ArrayList<>();
		if (!StringUtils.hasText(currentPassword)) {
			errors.add(ErrorMessage.withFieldCode("currentPassword", "common.validation.requiredField"));
		}
		if (!StringUtils.hasText(newPassword)) {
			errors.add(ErrorMessage.withFieldCode("newPassword", "common.validation.requiredField"));
		}
		if (!StringUtils.hasText(newPasswordCheck)) {
			errors.add(ErrorMessage.withFieldCode("newPasswordCheck", "common.validation.requiredField"));
		}
		
		if (!Objects.equals(newPassword, newPasswordCheck)) {
			errors.add(ErrorMessage.withFieldCode("newPasswordCheck", "user.password.passwordsMismatch"));
		}

		if (errors.isEmpty()) {		
			AppUser user = repo.findById(userId);
			if (user != null) {
				if (PasswordSecurity.checkPassword(currentPassword, user.getPassword(), user.getPasswordSalt())) {
					PasswordHash hash = PasswordSecurity.hashPassword(newPassword);
					user.setPassword(hash.getHash());
					user.setPasswordSalt(hash.getSalt());
				} else {
					errors.add(ErrorMessage.withFieldCode("currentPassword", "user.password.badPassword"));
				}
				
			} else {
				errors.add(ErrorMessage.withCode("user.password.unknownUser"));
			}
		}
		
		
		return errors.isEmpty() ? null : errors;
	}
	
	
	@Transactional
	public void createPasswordResetRequest(String login) {
		if (!StringUtils.hasText(login)) {
			return;
		}
		AppUser user = fetchUser(login);
		if (user == null) {
			return;
		}
				
		PasswordResetRequest request = new PasswordResetRequest();
		request.setCreated(new Date());
		Calendar c = Calendar.getInstance();
		c.add(Calendar.DAY_OF_WEEK, 3);
		request.setValidUntil(c.getTime());
		
		String hash = UUID.randomUUID().toString();
		request.setHash(hash);
		request.setUserId(user.getId());
		
		repo.savePasswordResetRequest(request);
		
//		Unit unit = unitService.findByOwnerId(user.getId());
		
		//send email
//		suiteEmails.sendResetPasswordRequestEmail(unit, request.getHash());
	}
	
	
	@Transactional
	public PasswordResetRequest fetchPasswordResetRequest(String token) {
		PasswordResetRequest r = repo.fetchPasswordResetRequest(token);
		
		if (r.getValidUntil() == null || r.getValidUntil().compareTo(new Date()) < 0) {
			return null;
		}
		
		return r;
	}
    
	
	
	
	@Transactional
	public void deletePasswordResetRequest(PasswordResetRequest request) {
		Objects.requireNonNull(request, "Request must not be null");
		repo.delete(request);
	}
	
}
