<?php
// ════════════════════════════════════════════════════════
// SELF-CONTAINED SMTP MAILER  (no external library)
// Place in: Triangle_Tree_Life_Number/api/config/smtp_mailer.php
// Sends HTML email via authenticated SMTP over SSL.
// Reads connection settings from environment (.env).
// ════════════════════════════════════════════════════════

/**
 * Send an HTML email through SMTP.
 *
 * @param string $toEmail   Recipient address
 * @param string $toName    Recipient display name (may be '')
 * @param string $subject   Email subject
 * @param string $htmlBody  HTML message body
 * @return array            ['ok' => bool, 'error' => string]
 */
function sendSmtpMail($toEmail, $toName, $subject, $htmlBody) {

    $host   = getenv('EMAIL_HOST') ?: 'mail.decode.com.my';
    $port   = (int)(getenv('EMAIL_PORT') ?: 465);
    $user   = getenv('EMAIL_USER') ?: '';
    $pass   = getenv('EMAIL_PASS') ?: '';
    $secure = strtolower(getenv('EMAIL_SECURE') ?: 'ssl'); // ssl | tls
    $from   = getenv('EMAIL_FROM') ?: ('Numerology <' . $user . '>');

    if (!$user || !$pass) {
        return ['ok' => false, 'error' => 'Email credentials not configured in .env'];
    }

    // Parse "Name <addr>" or plain address from EMAIL_FROM
    $fromEmail = $user;
    $fromName  = 'Numerology';
    if (preg_match('/^\s*(.*?)\s*<(.+?)>\s*$/', $from, $m)) {
        $fromName  = trim($m[1]) !== '' ? trim($m[1]) : $fromName;
        $fromEmail = trim($m[2]);
    } elseif (filter_var(trim($from), FILTER_VALIDATE_EMAIL)) {
        $fromEmail = trim($from);
    }

    // ── Connect ──────────────────────────────
    $remote = ($secure === 'ssl')
        ? "ssl://{$host}:{$port}"
        : "{$host}:{$port}";

    $errno = 0; $errstr = '';
    $ctx = stream_context_create([
        'ssl' => ['verify_peer' => false, 'verify_peer_name' => false]
    ]);
    $fp = @stream_socket_client($remote, $errno, $errstr, 20,
        STREAM_CLIENT_CONNECT, $ctx);

    if (!$fp) {
        return ['ok' => false, 'error' => "Connection failed: $errstr ($errno)"];
    }
    stream_set_timeout($fp, 20);

    // ── Helpers ──────────────────────────────
    $read = function() use ($fp) {
        $data = '';
        while ($line = fgets($fp, 515)) {
            $data .= $line;
            // SMTP multiline replies have a '-' after the code; ' ' = last line
            if (isset($line[3]) && $line[3] === ' ') break;
        }
        return $data;
    };
    $cmd = function($command) use ($fp, $read) {
        fputs($fp, $command . "\r\n");
        return $read();
    };
    $code = function($resp) {
        return (int)substr(trim($resp), 0, 3);
    };

    // ── SMTP conversation ────────────────────
    $resp = $read();                       // server greeting
    if ($code($resp) !== 220) {
        fclose($fp);
        return ['ok' => false, 'error' => 'Bad greeting: ' . trim($resp)];
    }

    $host_ehlo = $_SERVER['SERVER_NAME'] ?? 'localhost';
    $resp = $cmd("EHLO {$host_ehlo}");
    if ($code($resp) !== 250) {
        fclose($fp);
        return ['ok' => false, 'error' => 'EHLO failed: ' . trim($resp)];
    }

    // STARTTLS upgrade if using tls (port 587)
    if ($secure === 'tls') {
        $resp = $cmd("STARTTLS");
        if ($code($resp) !== 220) {
            fclose($fp);
            return ['ok' => false, 'error' => 'STARTTLS failed: ' . trim($resp)];
        }
        if (!stream_socket_enable_crypto($fp, true,
                STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
            fclose($fp);
            return ['ok' => false, 'error' => 'TLS negotiation failed'];
        }
        $resp = $cmd("EHLO {$host_ehlo}"); // re-EHLO after TLS
    }

    // AUTH LOGIN
    $resp = $cmd("AUTH LOGIN");
    if ($code($resp) !== 334) {
        fclose($fp);
        return ['ok' => false, 'error' => 'AUTH not accepted: ' . trim($resp)];
    }
    $resp = $cmd(base64_encode($user));
    if ($code($resp) !== 334) {
        fclose($fp);
        return ['ok' => false, 'error' => 'Username rejected: ' . trim($resp)];
    }
    $resp = $cmd(base64_encode($pass));
    if ($code($resp) !== 235) {
        fclose($fp);
        return ['ok' => false, 'error' => 'Login failed (check password): ' . trim($resp)];
    }

    // Envelope
    $resp = $cmd("MAIL FROM:<{$fromEmail}>");
    if ($code($resp) !== 250) {
        fclose($fp);
        return ['ok' => false, 'error' => 'MAIL FROM rejected: ' . trim($resp)];
    }
    $resp = $cmd("RCPT TO:<{$toEmail}>");
    if ($code($resp) !== 250 && $code($resp) !== 251) {
        fclose($fp);
        return ['ok' => false, 'error' => 'RCPT TO rejected: ' . trim($resp)];
    }

    // DATA
    $resp = $cmd("DATA");
    if ($code($resp) !== 354) {
        fclose($fp);
        return ['ok' => false, 'error' => 'DATA rejected: ' . trim($resp)];
    }

    // Build message headers + body
    $encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
    $fromHeader = $fromName
        ? ('=?UTF-8?B?' . base64_encode($fromName) . '?= <' . $fromEmail . '>')
        : $fromEmail;
    $toHeader = $toName
        ? ('=?UTF-8?B?' . base64_encode($toName) . '?= <' . $toEmail . '>')
        : $toEmail;

    $headers  = "From: {$fromHeader}\r\n";
    $headers .= "To: {$toHeader}\r\n";
    $headers .= "Subject: {$encodedSubject}\r\n";
    $headers .= "Date: " . date('r') . "\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html; charset=UTF-8\r\n";
    $headers .= "Content-Transfer-Encoding: base64\r\n";

    // Dot-stuffing: lines starting with '.' must be escaped
    $body = chunk_split(base64_encode($htmlBody));

    fputs($fp, $headers . "\r\n" . $body . "\r\n.\r\n");
    $resp = $read();
    if ($code($resp) !== 250) {
        fclose($fp);
        return ['ok' => false, 'error' => 'Message not accepted: ' . trim($resp)];
    }

    $cmd("QUIT");
    fclose($fp);

    return ['ok' => true, 'error' => ''];
}
?>
