<?php

namespace App\Tests\Controller;

use App\Controller\LogVerifyController;
use App\Entity\AppLog;
use App\Repository\AppLogRepository;
use App\Service\AppLoggerService;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Twig\Environment;

class LogVerifyControllerTest extends TestCase
{
    private function setupController(LogVerifyController $controller): void
    {
        $session = new Session(new MockArraySessionStorage());
        $stack = $this->createStub(RequestStack::class);
        $stack->method('getSession')->willReturn($session);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $container = $this->createStub(ContainerInterface::class);
        $container->method('has')->willReturn(true);
        $container->method('get')->willReturnMap([
            ['twig', $twig],
            ['security.authorization_checker', $this->createStub(AuthorizationCheckerInterface::class)],
            ['security.token_storage', $this->createStub(TokenStorageInterface::class)],
            ['request_stack', $stack],
            ['parameter_bag', $this->createStub(\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface::class)],
        ]);
        $controller->setContainer($container);
    }

    public function testLogNotFound(): void
    {
        $repo = $this->createStub(AppLogRepository::class);
        $repo->method('find')->willReturn(null);

        $controller = new LogVerifyController();
        $this->setupController($controller);

        $response = $controller(1, 'abcdef', $repo, $this->createStub(AppLoggerService::class));
        $this->assertSame(200, $response->getStatusCode());
    }

    public function testHmacMismatch(): void
    {
        $log = new AppLog('GET', '/admin', 'app_admin', 'Test', 'secret', null, '127.0.0.1');

        $repo = $this->createStub(AppLogRepository::class);
        $repo->method('find')->willReturn($log);

        $controller = new LogVerifyController();
        $this->setupController($controller);

        $response = $controller(1, 'wrong_hmac_prefix', $repo, $this->createStub(AppLoggerService::class));
        $this->assertSame(200, $response->getStatusCode());
    }

    public function testValidLog(): void
    {
        $log = new AppLog('GET', '/admin', 'app_admin', 'Test', 'secret', null, '127.0.0.1');
        $hmacPrefix = substr($log->getHmac(), 0, 16);

        $repo = $this->createStub(AppLogRepository::class);
        $repo->method('find')->willReturn($log);

        $loggerService = $this->createStub(AppLoggerService::class);
        $loggerService->method('verifyLog')->willReturn(true);

        $controller = new LogVerifyController();
        $this->setupController($controller);

        $response = $controller(1, $hmacPrefix, $repo, $loggerService);
        $this->assertSame(200, $response->getStatusCode());
    }

    public function testInvalidHmacLog(): void
    {
        $log = new AppLog('POST', '/admin/sync', 'app_admin_sync', 'Sync', 'secret', null, '10.0.0.1');
        $hmacPrefix = substr($log->getHmac(), 0, 16);

        $repo = $this->createStub(AppLogRepository::class);
        $repo->method('find')->willReturn($log);

        $loggerService = $this->createStub(AppLoggerService::class);
        $loggerService->method('verifyLog')->willReturn(false);

        $controller = new LogVerifyController();
        $this->setupController($controller);

        $response = $controller(1, $hmacPrefix, $repo, $loggerService);
        $this->assertSame(200, $response->getStatusCode());
    }
}
