<?php
/**
 * Fix Verification Test — Gap Date Returns Non-Null Session and Term via Fallback
 *
 * Validates: Requirements 2.1, 2.2, 2.3
 *
 * PURPOSE: Verify that resolveCurrentSessionTerm($con) correctly handles the
 * inter-term gap scenario by falling back to the most recently ended session
 * and term when the primary active-range query returns no rows.
 *
 * STRATEGY: We insert a test session/term that ended 2 days ago (gap scenario).
 * To isolate our test data from real active sessions in the DB, we temporarily
 * set all other sessions' end_date to a past date, run the helper, assert the
 * fallback returns our test rows, then restore the original data.
 *
 * EXPECTED OUTCOME: This test PASSES on fixed code — confirming the fallback
 * logic in session_term_helper.php resolves session_name and term_name correctly
 * even when today's date falls outside all active session/term ranges.
 *
 * Run via CLI: php portal/tests/test_gap_bug_condition_fixed.php
 */

// ── Bootstrap ────────────────────────────────────────────────────────────────
$root = dirname(__DIR__); // portal/
require_once $root . '/includes/dbconnection.php';
require_once $root . '/includes/session_term_helper.php';

if (!isset($con) || mysqli_connect_errno()) {
    echo "FATAL: Could not connect to database.\n";
    exit(1);
}

// ── Helpers ──────────────────────────────────────────────────────────────────
$pass = 0;
$fail = 0;

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

// ── Setup ────────────────────────────────────────────────────────────────────
$sessionName = 'TEST_GAP_FIXED_SESSION_2025';
$termName = 'TEST_GAP_FIXED_TERM_2025';

// Clean up any leftover rows from a previous run
$con->query("DELETE st FROM school_terms st
             INNER JOIN school_sessions ss ON st.session_id = ss.id
             WHERE ss.session_name = '$sessionName'");
$con->query("DELETE FROM school_sessions WHERE session_name = '$sessionName'");

// Snapshot real sessions' end_dates so we can restore them after the test.
// We will temporarily push them into the past to simulate a pure gap scenario.
$snapshotResult = $con->query("SELECT id, end_date FROM school_sessions");
$snapshot = [];
while ($row = $snapshotResult->fetch_assoc()) {
    $snapshot[] = $row;
}

// Insert our test session: started 30 days ago, ended 2 days ago (gap).
// This will become the most recently ended session once we push real ones back.
$insertSession = $con->prepare(
    "INSERT INTO school_sessions (session_name, start_date, end_date)
     VALUES (?, DATE_SUB(CURDATE(), INTERVAL 30 DAY), DATE_SUB(CURDATE(), INTERVAL 2 DAY))"
);
if (!$insertSession) {
    echo "FATAL: Could not prepare session insert: " . $con->error . "\n";
    exit(1);
}
$insertSession->bind_param('s', $sessionName);
$insertSession->execute();
$sessionId = $con->insert_id;
$insertSession->close();

if (!$sessionId) {
    echo "FATAL: Failed to insert test session row.\n";
    exit(1);
}

// Insert term linked to that session with the same date range
$insertTerm = $con->prepare(
    "INSERT INTO school_terms (term_name, session_id, start_date, end_date)
     VALUES (?, ?, DATE_SUB(CURDATE(), INTERVAL 30 DAY), DATE_SUB(CURDATE(), INTERVAL 2 DAY))"
);
if (!$insertTerm) {
    echo "FATAL: Could not prepare term insert: " . $con->error . "\n";
    exit(1);
}
$insertTerm->bind_param('si', $termName, $sessionId);
$insertTerm->execute();
$termId = $con->insert_id;
$insertTerm->close();

if (!$termId) {
    echo "FATAL: Failed to insert test term row.\n";
    // Cleanup session before exit
    $con->query("DELETE FROM school_sessions WHERE id = $sessionId");
    exit(1);
}

// Push all OTHER sessions' end_dates into the distant past so the primary
// query returns no rows and the fallback must fire.
// Our test session (ended 2 days ago) will be the most recently ended one.
$con->query(
    "UPDATE school_sessions
     SET end_date = DATE_SUB(CURDATE(), INTERVAL 365 DAY)
     WHERE id != $sessionId
       AND end_date >= CURDATE()"
);

echo "\n=== Fix Verification Test: Gap Date Returns Non-Null Session and Term ===\n";
echo "Test session inserted: id=$sessionId, session_name='$sessionName'\n";
echo "Test term inserted:    id=$termId,    term_name='$termName'\n";
echo "Both rows: start_date = CURDATE()-30, end_date = CURDATE()-2\n";
echo "Real active sessions temporarily set to end_date = CURDATE()-365.\n";
echo "Today is in the GAP — no active sessions exist.\n\n";

// ── Show current date for context ─────────────────────────────────────────────
$dateResult = $con->query("SELECT CURDATE() AS today");
$dateRow = $dateResult->fetch_assoc();
echo "MySQL CURDATE() = " . $dateRow['today'] . "\n\n";

// ── Call the fixed helper ─────────────────────────────────────────────────────
$st = resolveCurrentSessionTerm($con);

echo "resolveCurrentSessionTerm() returned:\n";
echo "  session_id   = " . var_export($st['session_id'], true) . "\n";
echo "  session_name = " . var_export($st['session_name'], true) . "\n";
echo "  term_id      = " . var_export($st['term_id'], true) . "\n";
echo "  term_name    = " . var_export($st['term_name'], true) . "\n\n";

// ── Assertions ────────────────────────────────────────────────────────────────

// 1. session_name is NOT null (fallback worked) — Requirements 2.1
assert_test(
    "session_name is NOT null after fallback (Requirements 2.1)",
    $st['session_name'] !== null,
    "session_name = " . var_export($st['session_name'], true) .
    ". Fallback query should have returned the most recently ended session."
);

// 2. term_name is NOT null (fallback worked) — Requirements 2.2
assert_test(
    "term_name is NOT null after fallback (Requirements 2.2)",
    $st['term_name'] !== null,
    "term_name = " . var_export($st['term_name'], true) .
    ". Fallback query should have returned the most recently ended term."
);

// 3. session_id matches the inserted test session — Requirements 2.3
assert_test(
    "session_id matches the inserted test session (Requirements 2.3)",
    (int) $st['session_id'] === (int) $sessionId,
    "Expected session_id=$sessionId, got session_id=" . $st['session_id'] . ". " .
    "Fallback should pick the most recently ended session (our test row, ended CURDATE()-2)."
);

// 4. term_id matches the inserted test term — Requirements 2.3
assert_test(
    "term_id matches the inserted test term (Requirements 2.3)",
    (int) $st['term_id'] === (int) $termId,
    "Expected term_id=$termId, got term_id=" . $st['term_id'] . ". " .
    "Fallback should pick the most recently ended term for the resolved session."
);

// ── Restore real sessions' end_dates ─────────────────────────────────────────
foreach ($snapshot as $snap) {
    $origId = (int) $snap['id'];
    $origEndDate = $snap['end_date'];
    $con->query("UPDATE school_sessions SET end_date = '$origEndDate' WHERE id = $origId");
}
echo "\nReal session end_dates restored.\n";

// ── Cleanup test rows ─────────────────────────────────────────────────────────
$con->query("DELETE FROM school_terms WHERE id = $termId");
$con->query("DELETE FROM school_sessions WHERE id = $sessionId");
echo "Test rows cleaned up.\n";

// ── Summary ───────────────────────────────────────────────────────────────────
echo "\n=== Results: $pass passed, $fail failed ===\n";

if ($fail > 0) {
    echo "\nFAIL — Fallback fix did not work as expected.\n";
    exit(1);
} else {
    echo "\nPASS — resolveCurrentSessionTerm() correctly falls back to the most\n";
    echo "recently ended session and term during an inter-term gap.\n";
    exit(0);
}
