package eu.eudat.logic.services.utilities;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.dao.entities.EmailConfirmationDao;
import eu.eudat.data.entities.EmailConfirmation;
import eu.eudat.models.data.mail.SimpleMail;
import eu.eudat.models.data.security.Principal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@Service("ConfirmationEmailService")
public class ConfirmationEmailServiceImpl implements ConfirmationEmailService {
	private static final Logger logger = LoggerFactory.getLogger(ConfirmationEmailServiceImpl.class);
	//private Logger logger;
	private Environment environment;

	public ConfirmationEmailServiceImpl(/*Logger logger,*/ Environment environment) {
//		this.logger = logger;
		this.environment = environment;
	}

	@Override
	public void createConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService, String email, UUID userId) {
		EmailConfirmation confirmationEmail = new EmailConfirmation();
		confirmationEmail.setEmail(email);
		confirmationEmail.setExpiresAt(Date
				.from(new Date()
						.toInstant()
						.plusSeconds(Long.parseLong(this.environment.getProperty("conf_email.expiration_time_seconds")))
				)
		);
		confirmationEmail.setUserId(userId);
		confirmationEmail.setIsConfirmed(false);
		confirmationEmail.setToken(UUID.randomUUID());
		confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail);
		sentConfirmationEmail(confirmationEmail, mailService);
	}

	@Override
	public CompletableFuture sentConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService) {
		return CompletableFuture.runAsync(() -> {
			SimpleMail mail = new SimpleMail();
			mail.setSubject(environment.getProperty("conf_email.subject"));
			mail.setContent(createContent(confirmationEmail.getToken(), mailService));
			mail.setTo(confirmationEmail.getEmail());
			try {
				mailService.sendSimpleMail(mail);
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
		});
	}

	private String createContent(UUID confirmationToken, MailService mailService) {
		String content = mailService.getMailTemplateContent(this.environment.getProperty("email.confirmation"));
		content = content.replace("{confirmationToken}", confirmationToken.toString());
		content = content.replace("{expiration_time}", secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds"))));
		content = content.replace("{host}", this.environment.getProperty("dmp.domain"));

		return content;
	}

	@Override
	public CompletableFuture sentMergeConfirmationEmail(EmailConfirmation confirmationEmail, MailService mailService, String userName) {
		return CompletableFuture.runAsync(() -> {
			SimpleMail mail = new SimpleMail();
			mail.setSubject(environment.getProperty("conf_email.subject"));
			mail.setContent(createMergeContent(confirmationEmail.getToken(), mailService, userName));
			mail.setTo(confirmationEmail.getEmail());
			try {
				mailService.sendSimpleMail(mail);
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}
		});
	}

	private String createMergeContent(UUID confirmationToken, MailService mailService, String userName) {
		String content = mailService.getMailTemplateContent(this.environment.getProperty("email.merge"));
		content = content.replace("{userName}", userName);
		content = content.replace("{confirmationToken}", confirmationToken.toString());
		content = content.replace("{expiration_time}", secondsToTime(Integer.parseInt(this.environment.getProperty("conf_email.expiration_time_seconds"))));
		content = content.replace("{host}", this.environment.getProperty("dmp.domain"));

		return content;
	}

	private String secondsToTime(int seconds) {
		int sec = seconds % 60;
		int hour = seconds / 60;
		int min = hour % 60;
		hour = hour / 60;
		return (hour + ":" + min + ":" + sec);
	}

	@Override
	public void createMergeConfirmationEmail(EmailConfirmationDao loginConfirmationEmailDao, MailService mailService,
											 String email, UUID userId, Principal principal, Integer provider) {
		EmailConfirmation confirmationEmail = new EmailConfirmation();
		confirmationEmail.setEmail(email);
		confirmationEmail.setExpiresAt(Date
				.from(new Date()
						.toInstant()
						.plusSeconds(Long.parseLong(this.environment.getProperty("conf_email.expiration_time_seconds")))
				)
		);
		confirmationEmail.setUserId(userId);
		try {
			Map<String, Object> map = new HashMap<>();
			map.put("userId", principal.getId());
			map.put("provider", provider.toString());
			confirmationEmail.setData(new ObjectMapper().writeValueAsString(map));
		} catch (JsonProcessingException e) {
			logger.error(e.getMessage(), e);
		}
		confirmationEmail.setIsConfirmed(false);
		confirmationEmail.setToken(UUID.randomUUID());
		confirmationEmail = loginConfirmationEmailDao.createOrUpdate(confirmationEmail);
		sentMergeConfirmationEmail(confirmationEmail, mailService, principal.getName());
		
	}
}