<?php
declare(strict_types=1);

define('CLI_SCRIPT', true);
require __DIR__ . '/../../config/bootstrap.php';

use App\Core\Database;

function cfg(array $arr, string $key, $default=null) { return array_key_exists($key, $arr) ? $arr[$key] : $default; }

function smtp_read($fp): string {
    $data = '';
    while (!feof($fp)) {
        $line = fgets($fp, 515);
        if ($line === false) break;
        $data .= $line;
        if (preg_match('/^\d{3}\s/', $line)) break;
    }
    return $data;
}
function smtp_write($fp, string $cmd): void { fwrite($fp, $cmd . "\r\n"); }
function smtp_expect($fp, array $codes, string $ctx): void {
    $resp = smtp_read($fp);
    if (!preg_match('/^(\d{3})\s/', $resp, $m)) throw new RuntimeException("SMTP bad response at {$ctx}: ".trim($resp));
    $code = (int)$m[1];
    if (!in_array($code, $codes, true)) throw new RuntimeException("SMTP unexpected {$code} at {$ctx}: ".trim($resp));
}

function smtp_send(array $mailCfg, string $to, string $subject, string $body, bool $isHtml=false, string $toName=''): void {
    $host = (string)cfg($mailCfg, 'host', '');
    $port = (int)cfg($mailCfg, 'port', 465);
    $enc  = strtolower((string)cfg($mailCfg, 'encryption', 'ssl')); // ssl|tls|''
    $user = (string)cfg($mailCfg, 'username', '');
    $pass = (string)cfg($mailCfg, 'password', '');

    $fromEmail = (string)cfg($mailCfg, 'from_email', $user);
    $fromName  = (string)cfg($mailCfg, 'from_name', 'EasyChair');

    if ($host==='' || $fromEmail==='') throw new RuntimeException("Mail config missing host/from_email");

    $remote = ($enc === 'ssl') ? "ssl://{$host}" : $host;
    $fp = fsockopen($remote, $port, $errno, $errstr, 20);
    if (!$fp) throw new RuntimeException("SMTP connect failed: {$errno} {$errstr}");
    stream_set_timeout($fp, 20);

    smtp_expect($fp, [220], "connect");

    smtp_write($fp, "EHLO easychair");
    $ehlo = smtp_read($fp);
    if (!preg_match('/^250/', $ehlo)) { smtp_write($fp, "HELO easychair"); smtp_expect($fp, [250], "helo"); }

    if ($enc === 'tls') {
        smtp_write($fp, "STARTTLS");
        smtp_expect($fp, [220], "starttls");
        if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
            throw new RuntimeException("STARTTLS crypto failed");
        }
        smtp_write($fp, "EHLO easychair");
        smtp_read($fp);
    }

    if ($user !== '') {
        smtp_write($fp, "AUTH LOGIN");
        smtp_expect($fp, [334], "auth login");
        smtp_write($fp, base64_encode($user));
        smtp_expect($fp, [334], "auth user");
        smtp_write($fp, base64_encode($pass));
        smtp_expect($fp, [235], "auth pass");
    }

    smtp_write($fp, "MAIL FROM:<{$fromEmail}>");
    smtp_expect($fp, [250], "mail from");

    smtp_write($fp, "RCPT TO:<{$to}>");
    smtp_expect($fp, [250,251], "rcpt");

    smtp_write($fp, "DATA");
    smtp_expect($fp, [354], "data");

    $hdrFrom = $fromName ? "{$fromName} <{$fromEmail}>" : $fromEmail;
    $hdrTo   = $toName ? "{$toName} <{$to}>" : $to;

    $headers = [];
    $headers[] = "From: {$hdrFrom}";
    $headers[] = "To: {$hdrTo}";
    $headers[] = "Subject: " . str_replace(["\r","\n"], '', $subject);
    $headers[] = "MIME-Version: 1.0";
    if ($isHtml) {
        $headers[] = "Content-Type: text/html; charset=UTF-8";
    } else {
        $headers[] = "Content-Type: text/plain; charset=UTF-8";
    }
    $headers[] = "Content-Transfer-Encoding: 8bit";

    $msg = implode("\r\n", $headers) . "\r\n\r\n" . $body . "\r\n.";
    fwrite($fp, $msg . "\r\n");
    smtp_expect($fp, [250], "data end");

    smtp_write($fp, "QUIT");
    @smtp_read($fp);
    fclose($fp);
}

$db = Database::getInstance();

// Load mail config (array return preferred)
$mailCfg = [];
$mailFile = BASE_PATH . '/config/mail.php';
if (is_file($mailFile)) {
    $ret = require $mailFile;
    if (is_array($ret)) $mailCfg = $ret;
}

$limit = 30; $dryrun = false;
foreach ($argv as $a) {
    if (preg_match('/^--limit=(\d+)$/', $a, $m)) $limit = (int)$m[1];
    if ($a === '--dryrun') $dryrun = true;
}

echo "Sending email_queue schema(to_email/subject_line/status). limit={$limit}".($dryrun?" DRYRUN":"")."\n";

$lock = fopen(BASE_PATH . '/storage/logs/email_sender.lock', 'c');
if ($lock && !flock($lock, LOCK_EX|LOCK_NB)) { echo "Another sender is running.\n"; exit(0); }

$st = $db->prepare("SELECT * FROM email_queue WHERE status='queued' ORDER BY id ASC LIMIT :lim");
$st->bindValue(':lim', $limit, PDO::PARAM_INT);
$st->execute();
$rows = $st->fetchAll();
echo "Queued found: ".count($rows)."\n";

$sent=0; $failed=0;
foreach ($rows as $r) {
    $id = (int)$r['id'];
    $to = (string)($r['to_email'] ?? '');
    $name = (string)($r['to_name'] ?? '');
    $subj = (string)($r['subject_line'] ?? '');
    $html = (string)($r['body_html'] ?? '');
    $txt  = (string)($r['body_text'] ?? '');
    $body = $html !== '' ? $html : $txt;
    $isHtml = ($html !== '');

    if ($to === '' || $subj === '' || $body === '') {
        $db->prepare("UPDATE email_queue SET status='failed', error_message='Missing to/subject/body' WHERE id=:id")->execute([':id'=>$id]);
        $failed++;
        continue;
    }

    try {
        if ($dryrun) {
            echo "DRYRUN #{$id} -> {$to} ({$subj})\n";
        } else {
            smtp_send($mailCfg, $to, $subj, $body, $isHtml, $name);
            $db->prepare("UPDATE email_queue SET status='sent', sent_at=NOW(), error_message=NULL WHERE id=:id")->execute([':id'=>$id]);
            echo "SENT #{$id} -> {$to}\n";
            $sent++;
        }
    } catch (Throwable $e) {
        $db->prepare("UPDATE email_queue SET status='failed', error_message=:err WHERE id=:id")->execute([':id'=>$id, ':err'=>$e->getMessage()]);
        echo "FAILED #{$id} -> {$to} :: ".$e->getMessage()."\n";
        $failed++;
    }
}

echo "Done. sent={$sent}, failed={$failed}\n";
if ($lock) { flock($lock, LOCK_UN); fclose($lock); }
