<?php

require_once __DIR__ . '/../include/config.php';

$autoload = __DIR__ . '/../vendor/autoload.php';
if (file_exists($autoload)) {
    require_once $autoload;
}

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception as PHPMailerException;

class EmailServiceProvider {

    // Hard ceiling on a single bulk-send call, so one notice post can't try to
    // email thousands of people in one blocking request or trip shared-hosting
    // SMTP rate limits. Notices affecting more than this should be split/queued.
    const BULK_SEND_LIMIT = 300;

    private function configuredMailer(): PHPMailer
    {
        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->Host       = SMTP_HOST;
        $mail->Port       = SMTP_PORT;
        $mail->SMTPAuth   = true;
        $mail->Username   = SMTP_USERNAME;
        $mail->Password   = SMTP_PASSWORD;
        $mail->SMTPSecure = SMTP_ENCRYPTION === 'ssl' ? PHPMailer::ENCRYPTION_SMTPS : PHPMailer::ENCRYPTION_STARTTLS;
        $mail->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME);
        $mail->isHTML(true);
        return $mail;
    }

    public function sendEmail($recipientEmail, $subject, $bodyHtml, $recipientName = '')
    {
        if (!class_exists(PHPMailer::class)) {
            return ['success' => false, 'message' => 'PHPMailer not installed. Run "composer require phpmailer/phpmailer".'];
        }

        $mail = $this->configuredMailer();

        try {
            $mail->addAddress($recipientEmail, $recipientName);
            $mail->Subject = $subject;
            $mail->Body    = $bodyHtml;
            $mail->AltBody = trim(strip_tags(str_replace(['<br>', '<br/>', '<br />'], "\n", $bodyHtml)));

            $mail->send();
            return ['success' => true, 'message' => 'Email sent'];
        } catch (PHPMailerException $e) {
            error_log('Email send error: ' . $mail->ErrorInfo);
            return ['success' => false, 'message' => $mail->ErrorInfo];
        } catch (Exception $e) {
            error_log('Email send error: ' . $e->getMessage());
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * Send the same email to many recipients over ONE kept-alive SMTP connection
     * (far cheaper than sendEmail() in a loop, which reconnects+re-authenticates
     * per recipient). Used for notice-board blasts.
     *
     * @param array $recipients [['email'=>.., 'name'=>..], ...]
     * @return array ['sent'=>int, 'failed'=>int, 'total'=>int, 'capped'=>bool]
     */
    public function sendBulkEmail(array $recipients, $subject, $bodyHtml)
    {
        $result = ['sent' => 0, 'failed' => 0, 'total' => count($recipients), 'capped' => false];

        if (!class_exists(PHPMailer::class)) {
            error_log('sendBulkEmail: PHPMailer not installed.');
            $result['failed'] = $result['total'];
            return $result;
        }
        if (empty($recipients)) return $result;

        if (count($recipients) > self::BULK_SEND_LIMIT) {
            $recipients = array_slice($recipients, 0, self::BULK_SEND_LIMIT);
            $result['capped'] = true;
            error_log('sendBulkEmail: recipient list capped at ' . self::BULK_SEND_LIMIT . ' (had ' . $result['total'] . ')');
        }

        $mail = $this->configuredMailer();
        $mail->SMTPKeepAlive = true;
        $mail->Subject = $subject;
        $mail->Body    = $bodyHtml;
        $mail->AltBody = trim(strip_tags(str_replace(['<br>', '<br/>', '<br />'], "\n", $bodyHtml)));

        foreach ($recipients as $r) {
            $email = $r['email'] ?? '';
            $name  = $r['name']  ?? '';
            if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $result['failed']++; continue; }
            try {
                $mail->addAddress($email, $name);
                $mail->send();
                $result['sent']++;
            } catch (Exception $e) {
                error_log('Bulk email failed to ' . $email . ': ' . $mail->ErrorInfo);
                $result['failed']++;
            }
            $mail->clearAddresses();
        }

        $mail->smtpClose();
        return $result;
    }

}
