<?php
use PHPUnit\Framework\TestCase;
require_once __DIR__ . '/../src/db.php';
require_once __DIR__ . '/../src/cms.php';
final class CmsTest extends TestCase {
    public function testCreerPuisLister(): void {
        $pdo = db_test();
        $id = cms_creer_actualite($pdo, 'Rentrée 2026', 'Les cours démarrent…', null);
        $this->assertSame('Rentrée 2026', cms_actualite($pdo, $id)['titre']);
        $this->assertCount(1, cms_actualites_recentes($pdo, 3));
    }
    public function testDepublieeInvisible(): void {
        $pdo = db_test();
        $id = cms_creer_actualite($pdo, 'Brouillon', 'x', null);
        cms_publier_actualite($pdo, $id, false);
        $this->assertCount(0, cms_actualites_recentes($pdo, 3));
        $this->assertNull(cms_actualite($pdo, $id));
    }
    // Une actualité dépubliée reste consultable côté admin (édition d'un brouillon).
    public function testActualiteAdminVoitLesDepubliees(): void {
        $pdo = db_test();
        $id = cms_creer_actualite($pdo, 'Brouillon', 'x', null);
        cms_publier_actualite($pdo, $id, false);
        $this->assertNull(cms_actualite($pdo, $id));
        $admin = cms_actualite_admin($pdo, $id);
        $this->assertSame('Brouillon', $admin['titre']);
    }
    public function testActualiteAdminIntrouvableRenvoieNull(): void {
        $pdo = db_test();
        $this->assertNull(cms_actualite_admin($pdo, 999));
    }
    // Republier après dépublication doit rendre l'actualité de nouveau visible.
    public function testRepublierRendVisible(): void {
        $pdo = db_test();
        $id = cms_creer_actualite($pdo, 'Cyclique', 'x', null);
        cms_publier_actualite($pdo, $id, false);
        $this->assertNull(cms_actualite($pdo, $id));
        cms_publier_actualite($pdo, $id, true);
        $this->assertNotNull(cms_actualite($pdo, $id));
    }
    public function testModificationConserveImageSiNonFournie(): void {
        $pdo = db_test();
        $id = cms_creer_actualite($pdo, 'Titre initial', 'Contenu initial', 'photo.jpg');
        cms_modifier_actualite($pdo, $id, 'Titre modifié', 'Contenu modifié', null);
        $a = cms_actualite($pdo, $id);
        $this->assertSame('Titre modifié', $a['titre']);
        $this->assertSame('Contenu modifié', $a['contenu']);
        $this->assertSame('photo.jpg', $a['image']); // COALESCE : image absente du POST => celle en base est conservée
    }
    public function testModificationRemplaceImageSiFournie(): void {
        $pdo = db_test();
        $id = cms_creer_actualite($pdo, 'Titre', 'Contenu', 'ancienne.jpg');
        cms_modifier_actualite($pdo, $id, 'Titre', 'Contenu', 'nouvelle.jpg');
        $this->assertSame('nouvelle.jpg', cms_actualite($pdo, $id)['image']);
    }
    public function testSuppressionActualite(): void {
        $pdo = db_test();
        $id = cms_creer_actualite($pdo, 'À supprimer', 'x', null);
        cms_supprimer_actualite($pdo, $id);
        $this->assertNull(cms_actualite($pdo, $id));
        $this->assertCount(0, cms_actualites_recentes($pdo, 3));
    }
    public function testListeAdminInclutLesDepubliees(): void {
        $pdo = db_test();
        cms_creer_actualite($pdo, 'Publiée', 'x', null);
        $id2 = cms_creer_actualite($pdo, 'Dépubliée', 'x', null);
        cms_publier_actualite($pdo, $id2, false);
        $this->assertCount(2, cms_actualites_admin($pdo));
        $this->assertCount(1, cms_actualites_recentes($pdo, 10));
    }
    // Revue Task 12 — contrat sur lequel repose le try/catch de la page admin :
    // une écriture refusée par la base remonte en PDOException (jamais un échec
    // silencieux), sinon le nettoyage du fichier image ne se déclencherait pas.
    public function testCreationEchoueePropageLException(): void {
        $pdo = db_test();
        $pdo->exec("CREATE TRIGGER bloque_insert BEFORE INSERT ON actualites BEGIN SELECT RAISE(ABORT, 'echec force'); END");
        $this->expectException(PDOException::class);
        cms_creer_actualite($pdo, 'Titre', 'Contenu', null);
    }
    // Revue Task 12 — created_at absent ou illisible : date vide plutôt que le
    // « 01/01/1970 » d'un strtotime() en échec.
    public function testDateIllisibleDonneDateVide(): void {
        $this->assertSame('', cms_decorer_actualite(['contenu' => 'x', 'created_at' => 'pas une date'])['date']);
        $this->assertSame('', cms_decorer_actualite(['contenu' => 'x'])['date']);
    }
    // 12 actualités publiées : page 1 (9, plus récente d'abord), page 2 (les 3 restantes),
    // et le compteur total utilisé pour calculer le nombre de pages.
    public function testPagination(): void {
        $pdo = db_test();
        for ($i = 1; $i <= 12; $i++) {
            cms_creer_actualite($pdo, "Actu $i", 'x', null);
        }
        $page1 = cms_actualites_recentes($pdo, 9, 0);
        $this->assertCount(9, $page1);
        $this->assertSame('Actu 12', $page1[0]['titre']);
        $this->assertSame('Actu 4', $page1[8]['titre']);

        $page2 = cms_actualites_recentes($pdo, 9, 9);
        $this->assertCount(3, $page2);
        $this->assertSame('Actu 3', $page2[0]['titre']);
        $this->assertSame('Actu 1', $page2[2]['titre']);

        $this->assertSame(12, cms_compter_actualites($pdo));
    }

    // --- Médias (Tâche 13) ---

    public function testMediasParAlbumOrdonnes(): void {
        $pdo = db_test();
        cms_ajouter_media($pdo, 'Campus', 'a.jpg', 'Portail', 2);
        cms_ajouter_media($pdo, 'Campus', 'b.jpg', 'Cour', 1);
        cms_ajouter_media($pdo, 'Tenues', 'c.jpg', null, 1);
        $albums = cms_medias_par_album($pdo);
        $this->assertSame(['Campus','Tenues'], array_keys($albums));
        $this->assertSame('b.jpg', $albums['Campus'][0]['fichier']);
    }

    // Les albums eux-mêmes doivent être triés alphabétiquement (ORDER BY album),
    // pas simplement dans l'ordre d'insertion.
    public function testMediasParAlbumTriAlphabetiqueDesAlbums(): void {
        $pdo = db_test();
        cms_ajouter_media($pdo, 'Zoo', 'z.jpg', null, 0);
        cms_ajouter_media($pdo, 'Alpha', 'a.jpg', null, 0);
        $albums = cms_medias_par_album($pdo);
        $this->assertSame(['Alpha','Zoo'], array_keys($albums));
    }

    public function testMediaRenvoieLaLigne(): void {
        $pdo = db_test();
        $id = cms_ajouter_media($pdo, 'Campus', 'a.jpg', 'Légende', 0);
        $media = cms_media($pdo, $id);
        $this->assertSame('a.jpg', $media['fichier']);
        $this->assertSame('Campus', $media['album']);
    }

    public function testMediaIntrouvableRenvoieNull(): void {
        $pdo = db_test();
        $this->assertNull(cms_media($pdo, 999));
    }

    public function testSuppressionMedia(): void {
        $pdo = db_test();
        $id = cms_ajouter_media($pdo, 'Campus', 'a.jpg', null, 0);
        cms_supprimer_media($pdo, $id);
        $this->assertNull(cms_media($pdo, $id));
        $this->assertSame([], cms_medias_par_album($pdo));
    }
}
