<?php

namespace App\Services\Email;

use PHPMailer\PHPMailer\Exception as MailerException;
use PHPMailer\PHPMailer\PHPMailer;

class EmailDispatchService
{
    public function __construct(private EmailProfileService $profiles)
    {
    }

    public function send(
        string $recipient,
        string $subject,
        string $htmlMessage,
        ?string $profile = null,
        ?string $replyToEmail = null,
        ?string $replyToName = null,
        array $attachments = []
    ): bool {
        $profile = $this->profiles->resolveProfile($profile);
        $cfg = $this->profiles->getProfileConfig($profile);

        if (empty($cfg['host']) || empty($cfg['user']) || $cfg['pass'] === '') {
            logger()->error("[mail:$profile] Missing SMTP config (host/user/pass). Check MAIL_{$this->profiles->envKeyFromProfile($profile)}_* or MAIL_DEFAULT_*/MAIL_*.");
            return false;
        }

        $debugEnabled = (bool) env('MAIL_DEBUG', false);
        $timeout = (int) env('MAIL_TIMEOUT', 15);
        $keepAlive = (bool) env('MAIL_KEEPALIVE', false);
        $verifyPeer = filter_var(env('MAIL_VERIFY_PEER', 'true'), FILTER_VALIDATE_BOOLEAN);

        $mail = new PHPMailer(true);

        try {
            if ($debugEnabled) {
                ob_start();
            }

            $mail->isSMTP();
            $mail->Host = $cfg['host'];
            $mail->Port = $cfg['port'];
            $mail->SMTPAuth = true;
            $mail->Username = $cfg['user'];
            $mail->Password = $cfg['pass'];
            $mail->CharSet = 'UTF-8';
            $mail->Timeout = $timeout;
            $mail->SMTPKeepAlive = $keepAlive;
            $mail->SMTPAutoTLS = true;

            if ($cfg['encryption'] === 'ssl') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
            } else {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
            }

            $mail->SMTPOptions = [
                'ssl' => [
                    'verify_peer' => $verifyPeer,
                    'verify_peer_name' => $verifyPeer,
                    'allow_self_signed' => !$verifyPeer,
                ],
            ];

            $mail->SMTPDebug = $debugEnabled ? 3 : 0;
            $mail->Debugoutput = 'error_log';

            $mail->setFrom($cfg['fromEmail'], $cfg['fromName']);
            if (!empty($cfg['returnPath'])) {
                $mail->Sender = $cfg['returnPath'];
            }

            $mail->clearReplyTos();
            $rtEmail = env('MAIL_DEFAULT_REPLY_TO');
            $rtName = env('MAIL_DEFAULT_REPLY_TO_NAME');
            if (!$rtEmail || !filter_var($rtEmail, FILTER_VALIDATE_EMAIL)) {
                $rtEmail = $replyToEmail ?: ($cfg['replyTo'] ?: $cfg['fromEmail']);
            }
            if (!$rtName) {
                $rtName = $replyToName ?: ($cfg['replyToName'] ?: $cfg['fromName']);
            }
            $rtName = $this->profiles->sanitizeReplyToName($rtName, $cfg['fromName']);
            if ($rtEmail) {
                $mail->addReplyTo($rtEmail, $rtName);
            }

            if (!empty($cfg['dkim']['domain']) && !empty($cfg['dkim']['private']) && !empty($cfg['dkim']['selector'])) {
                $mail->DKIM_domain = $cfg['dkim']['domain'];
                $mail->DKIM_private = $cfg['dkim']['private'];
                $mail->DKIM_selector = $cfg['dkim']['selector'];
                $mail->DKIM_identity = $cfg['fromEmail'];
            }

            $mail->addAddress($recipient);

            foreach ($attachments as $att) {
                if (!empty($att['path']) && is_file($att['path'])) {
                    $mail->addAttachment($att['path'], $att['name'] ?? '');
                }
            }

            $mail->isHTML(true);
            $mail->Subject = $subject;
            $mail->Body = $htmlMessage;

            $ok = $mail->send();
            $dbg = $debugEnabled ? (ob_get_clean() ?: '') : '';

            if ($ok) {
                logger()->info("[mail:$profile] Sent to {$recipient}, subj='{$subject}' via {$cfg['host']}:{$cfg['port']}/{$cfg['encryption']}");
                return true;
            }

            logger()->error("[mail:$profile] Failed: {$mail->ErrorInfo}. Debug: {$dbg}");
            return false;
        } catch (MailerException $e) {
            $dbg = $debugEnabled ? (ob_get_clean() ?: '') : '';
            logger()->error("[mail:$profile] Exception: {$e->getMessage()} | PHPMailer: {$mail->ErrorInfo} | Debug: {$dbg}");
            return false;
        }
    }
}
