package pl.polskalokalnie.send;

import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import pl.polskalokalnie.mailconfig.SmtpConfig;

/**
 * Wysylka pojedynczego e-maila przez konto SMTP z konfiguracji. JavaMailSender budowany jest per
 * wywolanie, bo konfiguracja moze zmienic sie w czasie dzialania aplikacji (niski wolumen).
 * Dla portu 465 wlacza SSL, w przeciwnym razie STARTTLS.
 */
@Component
public class EmailSender {

    public SendResult send(SmtpConfig config, String to, String subject, String htmlBody) {
        if (config == null || config.getHost() == null || config.getHost().isBlank()
                || config.getUsername() == null || config.getUsername().isBlank()) {
            return SendResult.failure("Konfiguracja SMTP jest niekompletna");
        }
        try {
            JavaMailSenderImpl mailSender = buildMailSender(config);
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, false, StandardCharsets.UTF_8.name());
            helper.setFrom(fromAddress(config));
            helper.setTo(to);
            helper.setSubject(subject == null ? "" : subject);
            helper.setText(htmlBody, true);
            mailSender.send(message);
            String messageId = message.getMessageID();
            return SendResult.ok(messageId);
        } catch (Exception ex) {
            return SendResult.failure(shorten(ex.getMessage()));
        }
    }

    private JavaMailSenderImpl buildMailSender(SmtpConfig config) {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(config.getHost());
        int port = config.getPort() != null ? config.getPort() : (config.isSslEnabled() ? 465 : 587);
        mailSender.setPort(port);
        mailSender.setUsername(config.getUsername());
        mailSender.setPassword(config.getPassword());
        mailSender.setDefaultEncoding(StandardCharsets.UTF_8.name());

        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.connectiontimeout", "10000");
        props.put("mail.smtp.timeout", "15000");
        props.put("mail.smtp.writetimeout", "15000");
        if (config.isSslEnabled()) {
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.smtp.ssl.protocols", "TLSv1.2 TLSv1.3");
        } else {
            props.put("mail.smtp.starttls.enable", "true");
        }
        return mailSender;
    }

    private InternetAddress fromAddress(SmtpConfig config) throws UnsupportedEncodingException {
        try {
            if (config.getFromName() != null && !config.getFromName().isBlank()) {
                return new InternetAddress(config.getUsername(), config.getFromName(), StandardCharsets.UTF_8.name());
            }
            return new InternetAddress(config.getUsername());
        } catch (Exception ex) {
            throw new UnsupportedEncodingException("Nieprawidłowy adres nadawcy");
        }
    }

    private static String shorten(String message) {
        if (message == null) {
            return "Nieznany błąd wysyłki";
        }
        return message.length() > 480 ? message.substring(0, 480) : message;
    }
}
