<?php

declare(strict_types=1);

namespace App\Services;

use App\Core\Logger;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
use RuntimeException;

class MailService
{
    private PHPMailer $mailer;

    public function __construct()
    {
        $this->loadLibrary();

        $this->mailer = new PHPMailer(true);

        $this->configure();
    }

    private function loadLibrary(): void
    {
        $files = [
            PHPMAILER_PATH . '/src/Exception.php',
            PHPMAILER_PATH . '/src/PHPMailer.php',
            PHPMAILER_PATH . '/src/SMTP.php',
        ];

        foreach ($files as $file) {
            if (!is_file($file)) {
                throw new RuntimeException(
                    'Required PHPMailer file was not found: '
                    . $file
                );
            }

            require_once $file;
        }
    }

    private function configure(): void
    {
        $host = (string) env('MAIL_HOST', '');
        $port = (int) env('MAIL_PORT', 587);
        $username = (string) env('MAIL_USERNAME', '');
        $password = (string) env('MAIL_PASSWORD', '');
        $encryption = strtolower(
            (string) env('MAIL_ENCRYPTION', 'tls')
        );

        if ($host === '' || $username === '') {
            throw new RuntimeException(
                'Email configuration is incomplete.'
            );
        }

        $this->mailer->isSMTP();
        $this->mailer->Host = $host;
        $this->mailer->SMTPAuth = true;
        $this->mailer->Username = $username;
        $this->mailer->Password = $password;
        $this->mailer->Port = $port;

        if ($encryption === 'ssl') {
            $this->mailer->SMTPSecure =
                PHPMailer::ENCRYPTION_SMTPS;
        } elseif ($encryption === 'tls') {
            $this->mailer->SMTPSecure =
                PHPMailer::ENCRYPTION_STARTTLS;
        } else {
            $this->mailer->SMTPAutoTLS = false;
            $this->mailer->SMTPSecure = '';
        }

        $this->mailer->CharSet = 'UTF-8';
        $this->mailer->Encoding = 'base64';

        $this->mailer->setFrom(
            (string) env('MAIL_FROM_ADDRESS'),
            (string) env(
                'MAIL_FROM_NAME',
                'Linkage SA Group'
            )
        );
    }

    public function send(
        string $recipientEmail,
        string $recipientName,
        string $subject,
        string $htmlBody,
        ?string $plainTextBody = null,
        array $attachments = [],
        array $embeddedImages = []
    ): array {
        try {
            $this->mailer->clearAllRecipients();
            $this->mailer->clearAttachments();

            $this->mailer->addAddress(
                $recipientEmail,
                $recipientName
            );

            foreach ($embeddedImages as $image) {
                if (
                    empty($image['path']) ||
                    empty($image['cid']) ||
                    !is_file($image['path'])
                ) {
                    continue;
                }

                $this->mailer->addEmbeddedImage(
                    $image['path'],
                    $image['cid'],
                    $image['name'] ?? basename($image['path'])
                );
            }

            foreach ($attachments as $attachment) {
                if (
                    empty($attachment['path']) ||
                    !is_file($attachment['path'])
                ) {
                    continue;
                }

                $this->mailer->addAttachment(
                    $attachment['path'],
                    $attachment['name']
                        ?? basename($attachment['path'])
                );
            }

            $this->mailer->isHTML(true);
            $this->mailer->Subject = $subject;
            $this->mailer->Body = $htmlBody;
            $this->mailer->AltBody = $plainTextBody
                ?? strip_tags($htmlBody);

            $this->mailer->send();

            return [
                'success' => true,
                'message_id' =>
                    $this->mailer->getLastMessageID(),
                'error' => null,
            ];
        } catch (Exception $exception) {
            $error = $this->mailer->ErrorInfo
                ?: $exception->getMessage();

            if (class_exists(Logger::class)) {
                Logger::error(
                    'Email sending failed',
                    [
                        'recipient' => $recipientEmail,
                        'error' => $error,
                    ]
                );
            } else {
                error_log(
                    'Email sending failed: ' . $error
                );
            }

            return [
                'success' => false,
                'message_id' => null,
                'error' => $error,
            ];
        }
    }
}