<?php
/**
 * Standalone test runner for PendingTokenReminderTest
 * Run: php tests/run_pending_token_tests.php
 */

// Suppress session/header calls from send_token_reminder.php
// We only need the functions, not the routing logic.
// We'll define a stub for flash_alert and mock the session/header behaviour.

// Prevent the routing code from executing by faking the environment
$_SERVER['REQUEST_METHOD'] = 'GET'; // non-POST → would redirect, but we intercept

// Stub out functions that send headers (not available in CLI)
if (!function_exists('flash_alert')) {
    function flash_alert(string $message, string $redirect = ''): void { /* stub */ }
}

// Stub header() — not needed in CLI but avoids warnings
// (PHP CLI ignores header() calls silently, so no override needed)

// Include only the functions we need by requiring the file
// The routing block will call header() + exit on non-POST, so we need to
// capture that. We use output buffering and a shutdown trick.
// Simpler: just define the functions directly here by copy.

function build_reminder_email(string $studentName, string $token, string $schoolName): string
{
    $safeName   = htmlspecialchars($studentName, ENT_QUOTES, 'UTF-8');
    $safeToken  = htmlspecialchars($token,       ENT_QUOTES, 'UTF-8');
    $safeSchool = htmlspecialchars($schoolName,  ENT_QUOTES, 'UTF-8');

    return <<<HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body { font-family: Arial, sans-serif; background: #f4f4f4; margin: 0; padding: 0; }
    .container { max-width: 600px; margin: 30px auto; background: #fff;
                 border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,.1); }
    .header { background: #003366; color: #fff; padding: 24px 32px; text-align: center; }
    .header h1 { margin: 0; font-size: 22px; }
    .body { padding: 32px; color: #333; line-height: 1.6; }
    .token-box { background: #f0f4ff; border: 2px solid #003366; border-radius: 6px;
                 text-align: center; padding: 20px; margin: 24px 0; }
    .token-box span { font-size: 28px; font-weight: bold; color: #003366;
                      letter-spacing: 4px; }
    .footer { background: #f4f4f4; text-align: center; padding: 16px;
              font-size: 12px; color: #888; }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>{$safeSchool}</h1>
      <p style="margin:4px 0 0">Student Registration Reminder</p>
    </div>
    <div class="body">
      <p>Dear <strong>{$safeName}</strong>,</p>
      <p>This is a reminder that your registration token has been issued but not yet used.
         Please use the token below to complete your registration form:</p>
      <div class="token-box">
        <span>{$safeToken}</span>
      </div>
      <p>To complete your registration, please visit the school registration portal and
         enter your token when prompted.</p>
      <p>If you have already completed your registration, please disregard this message.</p>
      <p>For assistance, contact the school administration.</p>
    </div>
    <div class="footer">
      &copy; {$safeSchool}. All rights reserved.
    </div>
  </div>
</body>
</html>
HTML;
}

// -----------------------------------------------------------------------
// Test helpers
// -----------------------------------------------------------------------
$pass = 0;
$fail = 0;

function assert_true(bool $condition, string $label): void
{
    global $pass, $fail;
    if ($condition) {
        echo "[PASS] {$label}\n";
        $pass++;
    } else {
        echo "[FAIL] {$label}\n";
        $fail++;
    }
}

function count_pending(array $records): int
{
    return count(array_filter($records, fn($r) => $r['token_status'] === 'pending'));
}

// -----------------------------------------------------------------------
// Property 1: Pending count correctness
// Feature: pending-token-email-reminder, Property 1: Pending count correctness
// -----------------------------------------------------------------------
echo "\n=== Property 1: Pending count correctness ===\n";

assert_true(count_pending([]) === 0, 'Empty array → 0 pending');

assert_true(
    count_pending([['token_status' => 'pending'], ['token_status' => 'pending']]) === 2,
    'All pending → count matches'
);

assert_true(
    count_pending([['token_status' => 'used'], ['token_status' => 'expired']]) === 0,
    'None pending → 0'
);

assert_true(
    count_pending([
        ['token_status' => 'pending'],
        ['token_status' => 'used'],
        ['token_status' => 'pending'],
        ['token_status' => 'expired'],
        ['token_status' => 'pending'],
    ]) === 3,
    'Mixed → 3 pending'
);

// Property-based: 100 random iterations
// Feature: pending-token-email-reminder, Property 1: Pending count correctness
$statuses = ['pending', 'used', 'expired', 'active', 'inactive'];
$pbFail = 0;
for ($i = 0; $i < 100; $i++) {
    $records = [];
    $expected = 0;
    $count = random_int(0, 20);
    for ($j = 0; $j < $count; $j++) {
        $s = $statuses[array_rand($statuses)];
        $records[] = ['token_status' => $s];
        if ($s === 'pending') $expected++;
    }
    if (count_pending($records) !== $expected) $pbFail++;
}
assert_true($pbFail === 0, "Property-based 100 iterations: pending count always correct (failures: {$pbFail})");

// -----------------------------------------------------------------------
// Property 2: Email body contains required content
// Feature: pending-token-email-reminder, Property 2: Email body contains required content
// -----------------------------------------------------------------------
echo "\n=== Property 2: Email body contains required content ===\n";

$html = build_reminder_email('John Doe', 'ABC123', 'Test School');

assert_true(strpos($html, 'John Doe') !== false, 'Student name present in email');
assert_true(strpos($html, 'ABC123') !== false, 'Token present in email');
assert_true(substr_count($html, 'Test School') >= 2, 'School name in header AND footer');
assert_true(stripos($html, 'registration') !== false, 'Registration reference present');
assert_true(strpos($html, '<!DOCTYPE html>') !== false, 'HTML DOCTYPE present');
assert_true(strpos($html, '<html>') !== false, 'HTML tag present');

// XSS safety
$xssHtml = build_reminder_email('<script>alert(1)</script>', '<b>token</b>', '<i>school</i>');
assert_true(strpos($xssHtml, '<script>') === false, 'XSS in name is escaped');
assert_true(strpos($xssHtml, '<b>token</b>') === false, 'XSS in token is escaped');

// Property-based: 100 random triples
// Feature: pending-token-email-reminder, Property 2: Email body contains required content
$names   = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank'];
$tokens  = ['ABC123', 'XYZ789', 'TOK001', 'REG999', 'HTM001', 'QWE456'];
$schools = ['Adesina College', 'Test School', 'My Academy', 'Sample High'];
$pbFail2 = 0;
for ($i = 0; $i < 100; $i++) {
    $n = $names[array_rand($names)];
    $t = $tokens[array_rand($tokens)];
    $s = $schools[array_rand($schools)];
    $h = build_reminder_email($n, $t, $s);
    if (
        strpos($h, $n) === false ||
        strpos($h, $t) === false ||
        substr_count($h, $s) < 2 ||
        stripos($h, 'registration') === false
    ) {
        $pbFail2++;
    }
}
assert_true($pbFail2 === 0, "Property-based 100 iterations: email content always correct (failures: {$pbFail2})");

// -----------------------------------------------------------------------
// Summary
// -----------------------------------------------------------------------
echo "\n=== Results: {$pass} passed, {$fail} failed ===\n";
exit($fail > 0 ? 1 : 0);
