<?php

namespace KeyLair;

/**
 * Thin wrapper around PHP's built-in mail(), which hands off to whatever
 * mail transfer agent (e.g. Postfix) is configured on the server — no
 * external dependency, in keeping with the rest of the project. See
 * install/INSTALL.md for setting up outgoing mail on a fresh server.
 */
class Mailer
{
    public static function send(string $to, string $subject, string $body): bool
    {
        $host = parse_url(Helpers::baseUrl(), PHP_URL_HOST) ?: 'localhost';
        $fromAddress = self::stripHeaderInjection(Settings::mailFromAddress() ?: ('no-reply@' . $host));
        $fromName = self::stripHeaderInjection(Settings::mailFromName());
        $to = self::stripHeaderInjection($to);
        $subject = self::stripHeaderInjection($subject);

        $headers = implode("\r\n", [
            'From: ' . mb_encode_mimeheader($fromName, 'UTF-8') . ' <' . $fromAddress . '>',
            'Content-Type: text/plain; charset=UTF-8',
        ]);

        return mail($to, mb_encode_mimeheader($subject, 'UTF-8'), $body, $headers);
    }

    /**
     * Header injection defense: the "From" name falls back to the site name
     * (Settings::siteName()), which any logged-in admin — not just master admin —
     * can set via Branding. A CR/LF embedded there (or in any other value
     * that ends up in a header) could otherwise inject arbitrary extra mail
     * headers, e.g. a Bcc:. mb_encode_mimeheader() encodes for charset, not
     * for this, so it's not enough on its own.
     */
    private static function stripHeaderInjection(string $value): string
    {
        return trim(str_replace(["\r", "\n"], '', $value));
    }

    /**
     * Best-effort read-only check for whether a known mail transfer agent
     * service is active — just `systemctl is-active`, which doesn't need
     * OS-level root. Returns null if that can't be determined at all (exec()
     * disabled, non-systemd server, ...), not false — "unknown" is not the
     * same as "not running".
     */
    public static function transferAgentStatus(): ?string
    {
        if (!function_exists('exec') || in_array('exec', array_map('trim', explode(',', (string) ini_get('disable_functions'))), true)) {
            return null;
        }

        foreach (['postfix', 'sendmail', 'exim4'] as $service) {
            exec('systemctl is-active ' . escapeshellarg($service) . ' 2>/dev/null', $output, $exitCode);
            $state = trim(implode('', $output));
            $output = [];
            if ($state === 'active') {
                return $service . ' (active)';
            }
        }

        return 'none detected';
    }
}
