<?php

namespace App\Tests\Security;

use App\Security\MaintenanceListener;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Twig\Environment;

#[AllowMockObjectsWithoutExpectations]
class MaintenanceListenerTest extends TestCase
{
    private $twig;
    private $tempDir;
    private $listener;

    protected function setUp(): void
    {
        $this->twig = $this->createMock(Environment::class);
        $this->tempDir = sys_get_temp_dir() . '/maintenance_test_' . uniqid();
        mkdir($this->tempDir . '/var', 0777, true);

        $this->listener = new MaintenanceListener($this->twig, $this->tempDir);
    }

    protected function tearDown(): void
    {
        $this->removeDirectory($this->tempDir);
    }

    public function testOnKernelRequestMaintenanceFileExists()
    {
        touch($this->tempDir . '/var/.maintenance');

        $kernel = $this->createMock(HttpKernelInterface::class);
        $request = Request::create('/');
        $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST);

        $this->twig->expects($this->once())
            ->method('render')
            ->with('security/maintenance.twig')
            ->willReturn('Maintenance Mode');

        $this->listener->onKernelRequest($event);

        $response = $event->getResponse();
        $this->assertInstanceOf(Response::class, $response);
        $this->assertEquals(503, $response->getStatusCode());
        $this->assertEquals('Maintenance Mode', $response->getContent());
    }

    public function testOnKernelRequestNoMaintenanceFile()
    {
        $kernel = $this->createMock(HttpKernelInterface::class);
        $request = Request::create('/');
        $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST);

        $this->listener->onKernelRequest($event);

        $this->assertNull($event->getResponse());
    }

    private function removeDirectory($dir) {
        if (!is_dir($dir)) return;
        $files = array_diff(scandir($dir), array('.','..'));
        foreach ($files as $file) {
            (is_dir("$dir/$file")) ? $this->removeDirectory("$dir/$file") : unlink("$dir/$file");
        }
        rmdir($dir);
    }
}
