<?php
// /lib/mailer.php
// Sends email using $config['mail'] (from_email, from_name, bcc, smtp{host,port,secure,user,pass})
// Returns [bool $ok, ?string $error]. Writes a transcript to /logs/mail.log.
//
// Plus helpers to load SMTP settings from organisation_mail_settings.

declare(strict_types=1);

/**
 * Core mail sender.
 * Expects:
 *   $config['mail'] = [
 *     'from_email' => '...',
 *     'from_name'  => '...',
 *     'bcc'        => '...',
 *     'smtp'       => [
 *       'host'   => '...',
 *       'port'   => 587,
 *       'secure' => 'tls'|'ssl'|'none',
 *       'user'   => '...',
 *       'pass'   => '...',
 *     ],
 *   ];
 */
function mpms_mail_send(array $config, string $to, string $subject, string $html, ?string $text = null): array
{
    $mailCfg   = $config['mail'] ?? [];
    $fromEmail = (string)($mailCfg['from_email'] ?? 'noreply@example.com');
    $fromName  = (string)($mailCfg['from_name']  ?? 'System');
    $bcc       = (string)($mailCfg['bcc']        ?? '');
    $smtp      = (array) ($mailCfg['smtp']       ?? []);

    // simple logger
    $logFile = __DIR__ . '/../logs/mail.log';
    @mkdir(dirname($logFile), 0775, true);
    $log = static function (string $msg) use ($logFile) {
        @file_put_contents($logFile, '[' . date('c') . "] $msg\n", FILE_APPEND);
    };

    // 1) Try Composer autoload first
    $autoload = __DIR__ . '/../vendor/autoload.php';
    if (is_file($autoload)) {
        require_once $autoload;
        $log('Loaded vendor/autoload.php');
    }

    // 2) If class still missing, manually include PHPMailer from vendor/phpmailer/phpmailer
    if (!class_exists('\PHPMailer\PHPMailer\PHPMailer')) {
        $root = __DIR__ . '/../vendor/phpmailer/phpmailer/src';
        if (is_file("$root/PHPMailer.php") && is_file("$root/SMTP.php") && is_file("$root/Exception.php")) {
            require_once "$root/PHPMailer.php";
            require_once "$root/SMTP.php";
            require_once "$root/Exception.php";
            $log('Manually included PHPMailer classes from vendor/phpmailer/phpmailer/src');
        }
    }

    $hasPHPMailer = class_exists('\PHPMailer\PHPMailer\PHPMailer');

    // If SMTP is configured but PHPMailer isn't available, fail fast so you see it
    if (!empty($smtp['host']) && !$hasPHPMailer) {
        $msg = 'SMTP is configured but PHPMailer is not found. Install via: composer require phpmailer/phpmailer';
        $log($msg);
        return [false, $msg];
    }

    // Prefer PHPMailer (especially for SMTP)
    if ($hasPHPMailer) {
        try {
            $m = new \PHPMailer\PHPMailer\PHPMailer(true);
            $m->CharSet = 'UTF-8';

            if (!empty($smtp['host'])) {
                $m->isSMTP();
                $m->Host = (string)$smtp['host'];
                $m->Port = (int)($smtp['port'] ?? 587);

                $secure = strtolower((string)($smtp['secure'] ?? 'tls'));
                if ($secure === 'ssl') {
                    $m->SMTPSecure = \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS;
                } elseif ($secure === 'tls') {
                    $m->SMTPSecure = \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
                } else {
                    // 'none' or anything else
                    $m->SMTPSecure = false;
                }

                $m->SMTPAuth = !empty($smtp['user']);
                if ($m->SMTPAuth) {
                    $m->Username = (string)($smtp['user'] ?? '');
                    $m->Password = (string)($smtp['pass'] ?? '');
                }

                // Verbose SMTP transcript into /logs/mail.log
                $m->SMTPDebug   = 2;
                $m->Debugoutput = function ($str, $level) use ($log) {
                    $log("SMTP[$level] $str");
                };
            }

            // Some providers want envelope-from/sender aligned with the SMTP user
            if (!empty($smtp['user'])) {
                $m->Sender = (string)$smtp['user']; // envelope-from
            }

            $m->setFrom($fromEmail, $fromName);
            $m->addAddress($to);
            if (!empty($bcc)) {
                $m->addBCC($bcc);
            }
            $m->addReplyTo($fromEmail, $fromName);

            $m->isHTML(true);
            $m->Subject = $subject;
            $m->Body    = $html;
            $m->AltBody = $text ?: strip_tags($html);

            $ok = $m->send();
            $log($ok ? "Sent OK to $to" : "Send returned false to $to");
            return [$ok, $ok ? null : 'PHPMailer send() returned false'];
        } catch (\Throwable $e) {
            $log('PHPMailer exception: ' . $e->getMessage());
            return [false, $e->getMessage()];
        }
    }

    // 3) Fallback: native mail() (no SMTP)
    $headers  = "From: {$fromName} <{$fromEmail}>\r\n";
    if (!empty($bcc)) {
        $headers .= "Bcc: {$bcc}\r\n";
    }
    $headers .= "MIME-Version: 1.0\r\nContent-Type: text/html; charset=UTF-8\r\n";

    $ok = @mail($to, $subject, $html, $headers);
    $log($ok ? "mail() sent OK to $to" : "mail() failed to $to");
    return [$ok, $ok ? null : 'PHP mail() failed'];
}

/**
 * Build a mail config array (for mpms_mail_send) from an organisation_mail_settings row.
 *
 * @param array $row      Row from organisation_mail_settings.
 * @param array $fallback Optional existing mail config to use for missing values.
 * @return array          ['from_email'=>..., 'from_name'=>..., 'bcc'=>..., 'smtp'=>[...]]
 */
function mpms_build_mail_config_from_row(array $row, array $fallback = []): array
{
    $fallbackMail = $fallback ?? [];
    $fallbackSmtp = $fallbackMail['smtp'] ?? [];

    $secure = strtolower(trim((string)($row['smtp_secure'] ?? $fallbackSmtp['secure'] ?? 'tls')));
    if (!in_array($secure, ['ssl', 'tls', 'none'], true)) {
        $secure = 'tls';
    }

    return [
        'from_email' => $row['from_email'] ?? ($fallbackMail['from_email'] ?? 'noreply@example.com'),
        'from_name'  => $row['from_name']  ?? ($fallbackMail['from_name']  ?? 'System'),
        'bcc'        => $row['bcc']        ?? ($fallbackMail['bcc']        ?? ''),
        'smtp'       => [
            'host'   => $row['smtp_host']   ?? ($fallbackSmtp['host']   ?? ''),
            'port'   => (int)($row['smtp_port'] ?? ($fallbackSmtp['port'] ?? 587)),
            'secure' => $secure,
            'user'   => $row['smtp_user']   ?? ($fallbackSmtp['user']   ?? ''),
            'pass'   => $row['smtp_pass']   ?? ($fallbackSmtp['pass']   ?? ''),
        ],
    ];
}

/**
 * Convenience: send mail for a given organisation using organisation_mail_settings.
 *
 * Usage:
 *   require_once __DIR__ . '/lib/mailer.php';
 *   [$ok, $err] = mpms_mail_send_for_org($pdo, $orgId, $to, $subject, $html);
 *
 * @param PDO    $pdo
 * @param int    $orgId
 * @param string $to
 * @param string $subject
 * @param string $html
 * @param string|null $text
 * @param array $baseConfig  Optional base config (e.g. global defaults from config.php)
 *
 * @return array [bool $ok, ?string $error]
 */
function mpms_mail_send_for_org(
    \PDO $pdo,
    int $orgId,
    string $to,
    string $subject,
    string $html,
    ?string $text = null,
    array $baseConfig = []
): array {
    $logFile = __DIR__ . '/../logs/mail.log';
    @mkdir(dirname($logFile), 0775, true);
    $log = static function (string $msg) use ($logFile) {
        @file_put_contents($logFile, '[' . date('c') . "] $msg\n", FILE_APPEND);
    };

    try {
        $stmt = $pdo->prepare('SELECT * FROM organisation_mail_settings WHERE organisation_id = ? LIMIT 1');
        $stmt->execute([$orgId]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$row) {
            $log("No organisation_mail_settings row for organisation_id={$orgId}; using baseConfig/mail only.");
            if (!isset($baseConfig['mail'])) {
                return [false, 'No mail settings found for organisation and no base mail config provided'];
            }
            $config = $baseConfig;
        } else {
            $log("Loaded organisation_mail_settings for organisation_id={$orgId}");
            $mailCfg = mpms_build_mail_config_from_row($row, $baseConfig['mail'] ?? []);
            $config  = $baseConfig;
            $config['mail'] = $mailCfg;
        }

        return mpms_mail_send($config, $to, $subject, $html, $text);
    } catch (\Throwable $e) {
        $log('Error loading organisation_mail_settings: ' . $e->getMessage());
        return [false, 'Failed to load organisation mail settings'];
    }
}