<?php
declare(strict_types=1);

/**
 * EasyChair Conference Mail Queue Worker
 *
 * Usage:
 *   php tools/mail_queue_worker.php --limit=25
 *   php tools/mail_queue_worker.php --conference_id=1 --limit=50
 *   php tools/mail_queue_worker.php --dry-run
 */

define('BASE_PATH', dirname(__DIR__));

require BASE_PATH . '/config/bootstrap.php';

use App\Core\Database;
use App\Core\SmtpMailer;

function arg_value(string $name, $default = null) {
    global $argv;
    foreach ($argv as $arg) {
        if ($arg === "--{$name}") return true;
        if (str_starts_with($arg, "--{$name}=")) {
            return substr($arg, strlen("--{$name}="));
        }
    }
    return $default;
}

function out(string $msg): void {
    echo '[' . date('Y-m-d H:i:s') . '] ' . $msg . PHP_EOL;
}

$db = Database::getInstance();

$limit = (int)arg_value('limit', 25);
if ($limit <= 0 || $limit > 200) {
    $limit = 25;
}

$conferenceId = (int)arg_value('conference_id', 0);
$dryRun = (bool)arg_value('dry-run', false);
$maxRetry = (int)arg_value('max-retry', 5);

$where = "
    WHERE status IN ('queued','failed')
      AND COALESCE(retry_count,0) < ?
      AND (
          last_attempt_at IS NULL
          OR last_attempt_at < DATE_SUB(NOW(), INTERVAL 3 MINUTE)
      )
";
$params = [$maxRetry];

if ($conferenceId > 0) {
    $where .= " AND conference_id = ? ";
    $params[] = $conferenceId;
}

$sql = "
    SELECT *
    FROM conference_mail_outbox
    {$where}
    ORDER BY 
      CASE status WHEN 'queued' THEN 1 ELSE 2 END,
      id ASC
    LIMIT {$limit}
";

$stmt = $db->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

out("Found " . count($rows) . " queued/failed message(s). limit={$limit}, conference_id=" . ($conferenceId ?: 'ALL') . ", dry_run=" . ($dryRun ? 'YES' : 'NO'));

if (!$rows) {
    exit(0);
}

$mailer = new SmtpMailer();

$sent = 0;
$failed = 0;
$skipped = 0;

foreach ($rows as $m) {
    $id = (int)$m['id'];
    $to = trim((string)($m['recipient_email'] ?? ''));
    $subject = (string)($m['subject'] ?? '');
    $body = (string)($m['body'] ?? '');
    $name = trim((string)($m['recipient_name'] ?? '')) ?: $to;

    out("Processing outbox #{$id} to={$to} template=" . ($m['template_key'] ?? '') . " status=" . ($m['status'] ?? ''));

    if ($to === '' || $subject === '' || $body === '') {
        $failed++;
        $err = "Missing recipient, subject, or body.";
        if (!$dryRun) {
            $u = $db->prepare("
                UPDATE conference_mail_outbox
                SET status='failed',
                    retry_count=COALESCE(retry_count,0)+1,
                    last_attempt_at=NOW(),
                    error_message=?
                WHERE id=?
            ");
            $u->execute([$err, $id]);
        }
        out("FAILED #{$id}: {$err}");
        continue;
    }

    if ($dryRun) {
        $skipped++;
        out("DRY RUN skip actual SMTP #{$id}");
        continue;
    }

    $markAttempt = $db->prepare("
        UPDATE conference_mail_outbox
        SET retry_count=COALESCE(retry_count,0)+1,
            last_attempt_at=NOW()
        WHERE id=?
    ");
    $markAttempt->execute([$id]);

    $result = $mailer->send($to, $subject, $body, $name);

    if (!empty($result['ok'])) {
        $u = $db->prepare("
            UPDATE conference_mail_outbox
            SET status='sent',
                sent_at=NOW(),
                error_message=NULL
            WHERE id=?
        ");
        $u->execute([$id]);

        if (!empty($m['submission_id'])) {
            $log = $db->prepare("
                INSERT INTO submission_activity_log
                (org_id, conference_id, submission_id, actor_id, actor_role, event_key, event_title, event_body)
                VALUES (?, ?, ?, NULL, 'system_worker', 'email_sent_worker', 'Queued email sent by worker', ?)
            ");
            $log->execute([
                (int)$m['org_id'],
                (int)$m['conference_id'],
                (int)$m['submission_id'],
                "Outbox ID: {$id}\nTemplate: " . ($m['template_key'] ?? '')
            ]);
        }

        $sent++;
        out("SENT #{$id}");
    } else {
        $err = trim(($result['error'] ?? 'SMTP failed') . "\n\n" . ($result['debug'] ?? ''));
        $u = $db->prepare("
            UPDATE conference_mail_outbox
            SET status='failed',
                error_message=?
            WHERE id=?
        ");
        $u->execute([$err, $id]);

        if (!empty($m['submission_id'])) {
            $log = $db->prepare("
                INSERT INTO submission_activity_log
                (org_id, conference_id, submission_id, actor_id, actor_role, event_key, event_title, event_body)
                VALUES (?, ?, ?, NULL, 'system_worker', 'email_failed_worker', 'Queued email failed by worker', ?)
            ");
            $log->execute([
                (int)$m['org_id'],
                (int)$m['conference_id'],
                (int)$m['submission_id'],
                "Outbox ID: {$id}\nError: " . mb_substr($err, 0, 1000)
            ]);
        }

        $failed++;
        out("FAILED #{$id}: " . mb_substr($err, 0, 250));
    }
}

out("Done. sent={$sent}, failed={$failed}, skipped={$skipped}");
