<?php
declare(strict_types=1);

namespace App\Tests\Game;

use App\Game\Entity\Player;
use App\Game\Entity\Session;
use App\Game\Entity\SessionSetting;
use App\Game\Enum\SessionSettingType;
use App\Game\Repository\SessionSettingRepository;
use App\Game\Service\GameResponseService;
use App\Game\Service\PlayerService;
use App\Tech\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Mercure\HubInterface;

class SessionLoggingTest extends TestCase
{
    private string $tempDir;
    private $security;
    private $playerService;
    private $sessionSettingRepository;
    private $hub;
    private $entityManager;
    private $service;

    protected function setUp(): void
    {
        $this->tempDir = sys_get_temp_dir() . '/escapepage_test_' . uniqid();
        mkdir($this->tempDir, 0777, true);

        $this->security = $this->createMock(Security::class);
        $this->playerService = $this->createMock(PlayerService::class);
        $this->sessionSettingRepository = $this->createMock(SessionSettingRepository::class);
        $this->hub = $this->createMock(HubInterface::class);
        $this->entityManager = $this->createMock(EntityManagerInterface::class);

        $this->service = new GameResponseService(
            $this->security,
            $this->playerService,
            $this->sessionSettingRepository,
            $this->hub,
            $this->entityManager,
            $this->tempDir
        );
    }

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

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

    public function testLogging(): void
    {
        $user = new User();
        $user->setUsername('player1');

        $session = $this->createMock(Session::class);
        $session->method('getId')->willReturn(456);

        $player = $this->createMock(Player::class);
        $player->method('getUser')->willReturn($user);
        $player->method('getSession')->willReturn($session);
        $player->method('getScreen')->willReturn(1);

        $this->security->method('getUser')->willReturn($user);
        $this->playerService->method('GetCurrentlyActiveAsPlayer')->willReturn($player);

        // Mock rights
        $rightsSetting = new SessionSetting();
        $rightsSetting->setValue(json_encode(['chat']));
        $this->sessionSettingRepository->method('getSetting')
            ->willReturnMap([
                [$session, SessionSettingType::RIGHTS_FOR_PLAYER1, $player, $rightsSetting],
            ]);

        // Simulate 'help' command (always returns something)
        $raw = json_encode(['message' => 'help', 'ts' => '123']);
        $result = $this->service->getGameResponse($raw);

        $this->assertNotEmpty($result);

        $logFilePath = $this->tempDir . '/var/log/sessions/456/player1.txt';
        $this->assertFileExists($logFilePath);

        $logContent = file_get_contents($logFilePath);
        $this->assertStringContainsString('PLAYER: help', $logContent);
        $this->assertStringContainsString('SERVER:', $logContent);
    }
}
