package ru.ulstu.user.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;
import ru.ulstu.configuration.ApplicationProperties;
import ru.ulstu.configuration.Constants;
import ru.ulstu.user.model.User;

import javax.mail.internet.MimeMessage;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Service
public class MailService {
    private final Logger log = LoggerFactory.getLogger(MailService.class);

    private static final String USER = "user";
    private static final String BASE_URL = "baseUrl";

    private final JavaMailSender javaMailSender;
    private final SpringTemplateEngine templateEngine;
    private final MailProperties mailProperties;
    private final ApplicationProperties applicationProperties;

    public MailService(JavaMailSender javaMailSender, SpringTemplateEngine templateEngine,
                       MailProperties mailProperties, ApplicationProperties applicationProperties) {
        this.javaMailSender = javaMailSender;
        this.templateEngine = templateEngine;
        this.mailProperties = mailProperties;
        this.applicationProperties = applicationProperties;
    }

    @Async
    public void sendEmail(String to, String subject, String content) {
        log.debug("Send email to '{}' with subject '{}'", to, subject);
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, false, StandardCharsets.UTF_8.name());
            message.setTo(to);
            message.setFrom(mailProperties.getUsername());
            message.setSubject(subject);
            message.setText(content, true);
            javaMailSender.send(mimeMessage);
            log.debug("Sent email to User '{}'", to);
        } catch (Exception e) {
            if (log.isDebugEnabled()) {
                log.warn("Email could not be sent to user '{}'", to, e);
            } else {
                log.warn("Email could not be sent to user '{}': {}", to, e.getMessage());
            }
        }
    }

    @Async
    public void sendEmailFromTemplate(User user, String templateName, String subject) {
        Context context = new Context();
        context.setVariable(USER, user);
        context.setVariable(BASE_URL, applicationProperties.getBaseUrl());
        String content = templateEngine.process(templateName, context);
        sendEmail(user.getEmail(), subject, content);
    }

    //Todo: выделить сервис нотификаций
    @Async
    public void sendEmailFromTemplate(Map<String, Object> variables, User user, String templateName, String subject) {
        Context context = new Context();
        variables.entrySet().forEach(entry -> context.setVariable(entry.getKey(), entry.getValue()));
        context.setVariable(USER, user);
        context.setVariable(BASE_URL, applicationProperties.getBaseUrl());
        String content = templateEngine.process(templateName, context);
        sendEmail(user.getEmail(), subject, content);
    }

    @Async
    public void sendActivationEmail(User user) {
        sendEmailFromTemplate(user, "activationEmail", Constants.MAIL_ACTIVATE);
    }

    @Async
    public void sendPasswordResetMail(User user) {
        sendEmailFromTemplate(user, "passwordResetEmail", Constants.MAIL_RESET);
    }
}
