EmailService.java

package com.archiweb.service;

import jakarta.mail.internet.MimeMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.BarcodeFormat;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.List;

@Service
@Slf4j
public class EmailService {

    private final JavaMailSender mailSender;

    public EmailService(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    // ---------------------------------------------------
    // 1. Envoi simple (texte)
    // ---------------------------------------------------
    public void sendEmail(String to, String subject, String text) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setTo(to);
            message.setSubject(subject);
            message.setText(text);

            mailSender.send(message);
            log.info("Email envoyé à {}", to);

        } catch (Exception e) {
            log.error("Erreur envoi email simple: {}", e.getMessage());
        }
    }

    // ---------------------------------------------------
    // 2. Envoi groupé
    // ---------------------------------------------------
    public int sendBulkEmail(String subject, String text, List<String> recipients) {
        int sent = 0;

        for (String email : recipients) {
            sendEmail(email, subject, text);
            sent++;
        }
        return sent;
    }

    // ---------------------------------------------------
    // 2b. Envoi groupé HTML
    // ---------------------------------------------------
    public int sendBulkEmailHtml(String subject, String htmlContent, List<String> recipients) {
        int sent = 0;

        for (String email : recipients) {
            sendEmailHtml(email, subject, htmlContent);
            sent++;
        }
        return sent;
    }

    // ---------------------------------------------------
    // 1b. Envoi simple HTML
    // ---------------------------------------------------
    public void sendEmailHtml(String to, String subject, String htmlContent) {
        try {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            
            helper.setTo(to);
            helper.setSubject(subject);
            // Définir explicitement le contenu HTML
            helper.setText(htmlContent, true); // true = HTML content
            
            // Définir explicitement le Content-Type
            mimeMessage.setContent(htmlContent, "text/html; charset=UTF-8");

            mailSender.send(mimeMessage);
            log.info("✅ Email HTML envoyé à {} avec succès (Content-Type: text/html)", to);

        } catch (Exception e) {
            log.error("❌ Erreur envoi email HTML à {}: {}", to, e.getMessage(), e);
            throw new RuntimeException("Erreur lors de l'envoi de l'email HTML", e);
        }
    }

    // ---------------------------------------------------
    // 3. Email avec QR Code intégré
    // ---------------------------------------------------
    public void sendPrizeEmail(String to, String codeValue, String prizeType, String storeAddress) {
        try {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);

            helper.setTo(to);
            helper.setSubject("Félicitations ! Vous avez gagné un lot TipTop");

            // HTML email
            String htmlContent = """
                    <p>Bonjour,</p>
                    <p>Félicitations, vous avez gagné un lot :</p>
                    <ul>
                        <li><strong>Lot :</strong> %s</li>
                        <li><strong>Code :</strong> %s</li>
                    </ul>
                    <p>Veuillez vous rendre en boutique :</p>
                    <p><strong>%s</strong></p>
                    <p>Présentez ce QR Code à l'accueil :</p>
                    <p><img src="cid:qrcode"></p>
                    <br>
                    <p>Cordialement,<br>L'équipe TipTop ArchiWeb</p>
                    """.formatted(prizeType, codeValue, storeAddress);

            helper.setText(htmlContent, true);

            // Génération QR Code
            byte[] qrBytes = generateQRCodeImage(codeValue, 400, 400);

            // Ajout inline pour affichage dans email
            helper.addInline("qrcode", new ByteArrayResource(qrBytes), "image/png");

            // Ajout en pièce jointe
            helper.addAttachment("QRCode_" + codeValue + ".png", new ByteArrayResource(qrBytes));

            mailSender.send(mimeMessage);
            log.info("Email de gain envoyé à {}", to);

        } catch (Exception e) {
            log.error("Erreur envoi email avec QR code: {}", e.getMessage());
        }
    }

    // ---------------------------------------------------
    // 4. Génération QR Code PNG
    // ---------------------------------------------------
    private byte[] generateQRCodeImage(String text, int width, int height) throws Exception {

        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height);

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                boolean black = bitMatrix.get(x, y);
                image.setRGB(x, y, black ? 0x000000 : 0xFFFFFF);
            }
        }

        ByteArrayOutputStream pngOutput = new ByteArrayOutputStream();
        ImageIO.write(image, "png", pngOutput);

        return pngOutput.toByteArray();
    }

    // ---------------------------------------------------
    // 5. Email reset password
    // ---------------------------------------------------
    public void sendResetPasswordEmail(String to, String token) {
        try {
            String resetLink = "http://localhost:4200/reset-password?token=" + token;

            String body = "Bonjour,\n\nCliquez pour réinitialiser votre mot de passe :\n"
                    + resetLink + "\n\nCe lien expirera dans 30 minutes.\n\nL'équipe ArchiWeb.";

            SimpleMailMessage message = new SimpleMailMessage();
            message.setTo(to);
            message.setSubject("Réinitialisation du mot de passe");
            message.setText(body);

            mailSender.send(message);

        } catch (Exception e) {
            log.error("Erreur envoi email reset password: {}", e.getMessage());
        }
    }

    // ---------------------------------------------------
    // 6. Email Newsletter avec template HTML
    // ---------------------------------------------------
    public void sendNewsletterEmail(String to, String subject, String content) {
        try {
            String htmlContent = buildNewsletterTemplate(subject, content);
            
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true);
            
            mailSender.send(mimeMessage);
            log.info("✅ Email newsletter envoyé à {}", to);

        } catch (Exception e) {
            log.error("❌ Erreur envoi email newsletter à {}: {}", to, e.getMessage(), e);
            throw new RuntimeException("Erreur lors de l'envoi de l'email newsletter", e);
        }
    }

    // ---------------------------------------------------
    // 7. Template HTML pour newsletter (public pour prévisualisation)
    // ---------------------------------------------------
    public String buildNewsletterTemplate(String subject, String content) {
        // Convertir les retours à la ligne en <br> et préserver les paragraphes
        String htmlContent = content
                .replace("\n\n", "</p><p style=\"margin: 0 0 1.25em 0;\">")
                .replace("\n", "<br>");
        
        // Si le contenu ne commence pas par <p>, l'ajouter
        if (!htmlContent.trim().startsWith("<p>") && !htmlContent.trim().startsWith("<div>")) {
            htmlContent = "<p style=\"margin: 0 0 1.25em 0;\">" + htmlContent + "</p>";
        }
        
        return """
            <!DOCTYPE html>
            <html lang="fr">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <meta http-equiv="X-UA-Compatible" content="IE=edge">
                <title>%s</title>
                <style>
                    * { margin: 0; padding: 0; box-sizing: border-box; }
                    body { 
                        margin: 0; 
                        padding: 0; 
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        -webkit-font-smoothing: antialiased;
                        -moz-osx-font-smoothing: grayscale;
                    }
                    p { margin: 0 0 1.25em 0; line-height: 1.7; }
                    p:last-child { margin-bottom: 0; }
                    a { color: #4CAF50; text-decoration: none; }
                    a:hover { text-decoration: underline; }
                </style>
            </head>
            <body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
                <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="width: 100%%; border-collapse: collapse; background-color: #f5f5f5; padding: 0;">
                    <tr>
                        <td align="center" style="padding: 40px 20px;">
                            <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="max-width: 600px; width: 100%%; background-color: #ffffff; border-radius: 20px; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); overflow: hidden; border: 1px solid #e8e8e8;">
                                <!-- Header -->
                                <tr>
                                    <td style="background: linear-gradient(135deg, #4CAF50 0%%, #45a049 100%%); padding: 50px 40px; text-align: center; position: relative; overflow: hidden;">
                                        <div style="position: absolute; top: -50px; right: -50px; width: 200px; height: 200px; background: rgba(255, 255, 255, 0.1); border-radius: 50%%;"></div>
                                        <div style="position: absolute; bottom: -30px; left: -30px; width: 150px; height: 150px; background: rgba(255, 255, 255, 0.08); border-radius: 50%%;"></div>
                                        <div style="position: relative; z-index: 1;">
                                            <h1 style="margin: 0; color: #ffffff; font-size: 36px; font-weight: 700; letter-spacing: -1px; line-height: 1.2;">
                                                🍵 Thé Tip Top
                                            </h1>
                                            <p style="margin: 16px 0 0 0; color: #e8f5e9; font-size: 16px; font-weight: 400; letter-spacing: 0.3px;">
                                                Votre newsletter exclusive
                                            </p>
                                        </div>
                                    </td>
                                </tr>
                                
                                <!-- Content -->
                                <tr>
                                    <td style="padding: 60px 50px; background-color: #ffffff;">
                                        <div style="color: #212121; font-size: 17px; line-height: 1.75; font-weight: 400;">
                                            %s
                                        </div>
                                    </td>
                                </tr>
                                
                                <!-- Footer -->
                                <tr>
                                    <td style="background: linear-gradient(180deg, #f8f9fa 0%%, #ffffff 100%%); padding: 40px 50px; text-align: center; border-top: 1px solid #e8e8e8;">
                                        <p style="margin: 0 0 16px 0; color: #424242; font-size: 16px; font-weight: 600; letter-spacing: 0.2px;">
                                            Thé Tip Top
                                        </p>
                                        <p style="margin: 0 0 20px 0; color: #757575; font-size: 14px; line-height: 1.6;">
                                            Votre destination pour les meilleurs thés
                                        </p>
                                        <div style="padding-top: 20px; border-top: 1px solid #e8e8e8; margin-top: 20px;">
                                            <p style="margin: 0 0 12px 0; color: #9e9e9e; font-size: 12px; line-height: 1.6;">
                                                Vous recevez cet email car vous êtes abonné à notre newsletter.
                                            </p>
                                            <a href="#" style="color: #4CAF50; text-decoration: none; font-weight: 500; font-size: 13px; border-bottom: 1px solid #4CAF50; padding-bottom: 2px; transition: all 0.2s ease;">Se désabonner</a>
                                        </div>
                                    </td>
                                </tr>
                            </table>
                        </td>
                    </tr>
                </table>
            </body>
            </html>
            """.formatted(subject, htmlContent);
    }
}