<?php
/**
 * Mini-lanceur de tests unitaires PHP (aucune dépendance externe).
 *
 * Usage : php tests/php/run.php
 *
 * Exécute tous les fichiers tests/php/*-test.php puis affiche un résumé.
 * Code de sortie : 0 si tous les tests passent, 1 sinon.
 */

error_reporting(E_ALL);

require_once __DIR__ . '/bootstrap.php';

// --- Assertions -----------------------------------------------------------

$GLOBALS['tests_passed'] = 0;
$GLOBALS['tests_failed'] = 0;
$GLOBALS['tests_failures'] = [];

/**
 * Formate une valeur pour l'affichage dans les messages d'échec
 */
function test_export($value) {
    if (is_array($value)) {
        return json_encode($value, JSON_UNESCAPED_UNICODE);
    }
    return var_export($value, true);
}

/**
 * Enregistre le résultat d'une assertion et affiche la ligne correspondante
 */
function test_record($ok, $label, $detail = '') {
    if ($ok) {
        $GLOBALS['tests_passed']++;
        echo "  [OK] $label\n";
    } else {
        $GLOBALS['tests_failed']++;
        $GLOBALS['tests_failures'][] = $label;
        echo "  [ÉCHEC] $label" . ($detail !== '' ? " — $detail" : '') . "\n";
    }
}

function assertEquals($expected, $actual, $label) {
    test_record(
        $expected == $actual,
        $label,
        'attendu ' . test_export($expected) . ', obtenu ' . test_export($actual)
    );
}

function assertTrue($actual, $label) {
    test_record($actual === true, $label, 'attendu true, obtenu ' . test_export($actual));
}

function assertFalse($actual, $label) {
    test_record($actual === false, $label, 'attendu false, obtenu ' . test_export($actual));
}

function assertNull($actual, $label) {
    test_record($actual === null, $label, 'attendu null, obtenu ' . test_export($actual));
}

function assertContains($needle, $haystack, $label) {
    test_record(
        strpos($haystack, $needle) !== false,
        $label,
        test_export($needle) . ' introuvable dans ' . test_export($haystack)
    );
}

function assertNotContains($needle, $haystack, $label) {
    test_record(
        strpos($haystack, $needle) === false,
        $label,
        test_export($needle) . ' trouvé dans ' . test_export($haystack)
    );
}

// --- Exécution des fichiers de test ---------------------------------------

$testFiles = glob(__DIR__ . '/*-test.php');
sort($testFiles);

if (empty($testFiles)) {
    echo "Aucun fichier de test trouvé dans " . __DIR__ . "\n";
    exit(1);
}

foreach ($testFiles as $file) {
    echo "\n== " . basename($file) . " ==\n";
    try {
        require $file;
    } catch (Throwable $e) {
        test_record(false, basename($file) . ' : exception non interceptée — ' . $e->getMessage());
    }
}

// --- Résumé ----------------------------------------------------------------

$passed = $GLOBALS['tests_passed'];
$failed = $GLOBALS['tests_failed'];

echo "\n----------------------------------------\n";
echo "Résumé : $passed réussi(s), $failed échoué(s).\n";

if ($failed > 0) {
    echo "Tests en échec :\n";
    foreach ($GLOBALS['tests_failures'] as $failure) {
        echo "  - $failure\n";
    }
    exit(1);
}

exit(0);
