<?php

namespace App\Service\Mailer;

use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Crypto\SMimeSigner;
use Symfony\Component\Mime\Email;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig\Environment;
use Symfony\Component\HttpKernel\KernelInterface;

class Mailer
{
    private readonly MailerInterface $mailer;

    public function __construct(
        MailerInterface $mailer,
        private readonly EntityManagerInterface $entityManager,
        private readonly UrlGeneratorInterface $urlGenerator,
        private readonly ?Profiler $profiler,
        private readonly Environment $environment,
        private readonly KernelInterface $kernel,
    ) {
        $this->mailer = $mailer;
    }

    /**
     * Convertit le contenu MJML en HTML via le binaire MJML.
     */
    private function convertMjmlToHtml(string $mjmlContent): string
    {
        $process = new Process(['mjml', '--stdin']);
        $process->setInput($mjmlContent);

        try {
            $process->run();

            if (!$process->isSuccessful()) {
                throw new ProcessFailedException($process);
            }

            return $process->getOutput();
        } catch (ProcessFailedException|Exception) {
            return '';
        }
    }

    /**
     * Envoie un email avec headers de désinscription et Message-ID conforme RFC 2822.
     */
    public function send(
        string $address,
        string $addressName,
        string $subject,
        string $template,
        array $data,
        array $files = []
    ): void {
        $domain = "ludikevent.fr";
        $dest = new Address($address, $addressName);
        $src = new Address("no-reply@esy-web.fr", "Ludikevent");
        $replyTo = new Address("contact@ludikevent.fr", "Ludikevent");

        // 1. Génération du Message-ID (SANS les crochets < >, Symfony les ajoute)
        $messageId = sprintf('%s.%s@%s',
            time(),
            bin2hex(random_bytes(8)),
            $domain
        );

        // 2. Préparation de l'URL de désinscription
        $unsubscribeUrl = "https://intranet.ludikevent.fr/unscribe/" . urlencode($address);

        $mail = (new Email())
            ->subject($subject)
            ->to($dest)
            ->from($src)
            ->replyTo($replyTo);

        // 3. Configuration des Headers
        $headers = $mail->getHeaders();

        // addIdHeader entoure automatiquement la valeur de < >
        $headers->addIdHeader('Message-ID', $messageId);

        // RFC 2369 & 8058
        $headers->addTextHeader('List-Unsubscribe', sprintf('<mailto:unscribe@%s>, <%s>', $domain, $unsubscribeUrl));
        $headers->addTextHeader('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click');

        // 4. Génération du contenu MJML
        $mjmlGenerator = $this->environment->render($template, [
            'system' => [
                'subject' => $subject,
                'path' => $_ENV['PATH_URL'] ?? 'https://ludikevent.fr',
                'unsubscribe_url' => $unsubscribeUrl,
                'message_id' => $messageId // Ici on peut l'afficher pour info
            ],
            'datas' => $data,
        ]);

        $htmlContent = $this->convertMjmlToHtml($mjmlGenerator);

        // 5. Fallback Texte Brut
        try {
            $txtContent = $this->environment->render('txt-' . $template, [
                'system' => [
                    'subject' => $subject,
                    'path' => $_ENV['PATH_URL'] ?? 'https://ludikevent.fr',
                    'unsubscribe_url' => $unsubscribeUrl
                ],
                'datas' => $data,
            ]);
            $mail->text($txtContent);
        } catch (Exception) {
            // Optionnel : générer un texte brut basique si le template n'existe pas
        }

        foreach ($files as $file) {
            $mail->addPart($file);
        }

        $mail->html($htmlContent);

        // Signer l'email S/MIME
        $certPath = $this->kernel->getProjectDir() . '/cert/email_smime.pem';
        $keyPath = $this->kernel->getProjectDir() . '/cert/email_smime_key.pem';
        $passphrase = 'vwWRh+1+0u2U9ppMB3';

        if (file_exists($certPath) && file_exists($keyPath)) {
            $signer = new SMimeSigner($certPath, $keyPath, $passphrase);
            $signedEmail = $signer->sign($mail);
            $this->mailer->send($signedEmail);
        } else {
             $this->mailer->send($mail);
        }
    }
}
