<?php

declare(strict_types=1);

namespace App\Tests\Module\Sites\Api;

use App\Module\Core\Domain\Entity\User;
use App\Module\Sites\Domain\Entity\Site;
use App\Tests\Module\Core\Api\AbstractApiTestCase;

/**
 * Tests de cascade DB a la suppression d'un site.
 *
 * Verifie les deux comportements attendus :
 *  - `user_site` a `ON DELETE CASCADE` : les rattachements sont supprimes ;
 *  - `user.current_site_id` a `ON DELETE SET NULL` : les users pointant sur
 *    le site supprime voient leur `currentSite` repasser a NULL.
 *
 * @internal
 */
final class SiteCascadeTest extends AbstractApiTestCase
{
    public function testDeletingSitePurgesUserSiteRows(): void
    {
        // Creer un site jetable et rattacher alice dessus.
        $em   = $this->getEm();
        $site = new Site('Test-Cascade-Purge', '1 rue Test', null, '12345', 'Ville', '#000000');
        $em->persist($site);
        $em->flush();
        $siteId = $site->getId();

        $alice = $em->getRepository(User::class)->findOneBy(['username' => 'alice']);
        self::assertNotNull($alice);
        $alice->addSite($site);
        $em->flush();
        $em->clear();

        // Verifie presence du rattachement M2M via SQL direct (l'EM est cleared).
        $connection = $this->getEm()->getConnection();
        $before     = (int) $connection->fetchOne(
            'SELECT COUNT(*) FROM user_site WHERE site_id = :id',
            ['id' => $siteId],
        );
        self::assertSame(1, $before);

        // Admin supprime le site.
        $client = $this->authenticatedClient('admin', 'admin');
        $client->request('DELETE', '/api/sites/'.$siteId);
        self::assertResponseStatusCodeSame(204);

        // L'entree user_site doit avoir disparu via ON DELETE CASCADE.
        $after = (int) $connection->fetchOne(
            'SELECT COUNT(*) FROM user_site WHERE site_id = :id',
            ['id' => $siteId],
        );
        self::assertSame(0, $after, 'Les rattachements user_site doivent etre purges en cascade.');
    }

    public function testDeletingSiteSetsCurrentSiteToNullOnReferencingUsers(): void
    {
        $em   = $this->getEm();
        $site = new Site('Test-Cascade-Current', '1 rue Test', null, '12345', 'Ville', '#000000');
        $em->persist($site);
        $em->flush();
        $siteId = $site->getId();

        $alice = $em->getRepository(User::class)->findOneBy(['username' => 'alice']);
        self::assertNotNull($alice);
        $aliceId = $alice->getId();
        $alice->addSite($site);
        $alice->setCurrentSite($site);
        $em->flush();
        $em->clear();

        // Admin supprime le site.
        $client = $this->authenticatedClient('admin', 'admin');
        $client->request('DELETE', '/api/sites/'.$siteId);
        self::assertResponseStatusCodeSame(204);

        // currentSite d'alice doit etre passe a NULL via ON DELETE SET NULL.
        $em = $this->getEm();
        $em->clear();
        $reload = $em->getRepository(User::class)->find($aliceId);
        self::assertNotNull($reload);
        self::assertNull(
            $reload->getCurrentSite(),
            'currentSite doit etre NULL apres suppression du site reference.',
        );
    }
}
