<?php
namespace Misuzu;

use InvalidArgumentException;
use Symfony\Component\Mime\Email as SymfonyMessage;
use Symfony\Component\Mime\Address as SymfonyAddress;
use Symfony\Component\Mailer\Mailer as SymfonyMailer;
use Symfony\Component\Mailer\Transport as SymfonyTransport;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;

final class Mailer {
    private const TEMPLATE_PATH = MSZ_ROOT . '/config/emails/%s.txt';

    private static $dsn = 'null://null';
    private static $transport = null;

    private static string $senderName = 'Flashii';
    private static string $senderAddr = 'sys@flashii.net';

    public static function init(string $method, array $config): void {
        if($method !== 'smtp') {
            self::$dsn = 'null://null';
            return;
        }

        $dsn = $method;

        // guess this is applied automatically based on the port?
        //if(!empty($config['encryption']))
        //    $dsn .= 't';

        $dsn .= '://';

        if(!empty($config['username'])) {
            $dsn .= $config['username'];

            if(!empty($config['password']))
                $dsn .= ':' . $config['password'];

            $dsn .= '@';
        }

        $dsn .= $config['host'] ?? '';
        $dsn .= ':';
        $dsn .= $config['port'] ?? 25;

        self::$dsn = $dsn;

        if(!empty($config['sender_name']))
            self::$senderName = $config['sender_name'];

        if(!empty($config['sender_addr']))
            self::$senderAddr = $config['sender_addr'];
    }

    public static function getTransport() {
        if(self::$transport === null)
            self::$transport = SymfonyTransport::fromDsn(self::$dsn);
        return self::$transport;
    }

    public static function sendMessage(array $to, string $subject, string $contents, bool $bcc = false): bool {
        foreach($to as $email => $name) {
            $to = new SymfonyAddress($email, $name);
            break;
        }

        $message = new SymfonyMessage;

        $message->from(new SymfonyAddress(
            self::$senderAddr,
            self::$senderName
        ));

        if($bcc)
            $message->bcc($to);
        else
            $message->to($to);

        $message->subject(trim($subject));
        $message->text(trim($contents));

        try {
            self::getTransport()->send($message);
            return true;
        } catch(TransportExceptionInterface $ex) {
            if(MSZ_DEBUG)
                throw $ex;
            return false;
        }
    }

    public static function template(string $name, array $vars = []): array {
        $path = sprintf(self::TEMPLATE_PATH, $name);

        if(!is_file($path))
            throw new InvalidArgumentException('Invalid e-mail template name.');

        $tpl = file_get_contents($path);

        // Normalise newlines
        $tpl = str_replace("\n", "\r\n", str_replace("\r\n", "\n", $tpl));

        foreach($vars as $key => $val)
            $tpl = str_replace("%{$key}%", $val, $tpl);

        [$subject, $message] = explode("\r\n\r\n", $tpl, 2);

        return compact('subject', 'message');
    }
}
