<?php

namespace MintyPHP\Tests\Module\Audit\Service;

use MintyPHP\Http\RequestContext;
use MintyPHP\Http\SessionStore;
use MintyPHP\Module\Audit\Repository\SystemAuditLogRepository;
use MintyPHP\Module\Audit\Service\SystemAuditRedactionService;
use MintyPHP\Module\Audit\Service\SystemAuditService;
use MintyPHP\Service\Settings\SettingsSystemAuditGateway;
use PHPUnit\Framework\TestCase;

class SystemAuditServiceTest extends TestCase
{
    protected function tearDown(): void
    {
        RequestContext::resetForTests();
        $_SESSION = [];
    }

    public function testRecordReturnsNullWhenDisabled(): void
    {
        $repo = $this->createMock(SystemAuditLogRepository::class);
        $repo->expects($this->never())->method('create');

        $settings = $this->createMock(SettingsSystemAuditGateway::class);
        $settings->expects($this->once())->method('isSystemAuditEnabled')->willReturn(false);

        $service = new SystemAuditService($repo, new SystemAuditRedactionService(), $settings, new SessionStore());

        $this->assertNull($service->record('admin.users.update', 'success'));
    }

    public function testRecordWritesWhenEnabled(): void
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';
        $_SERVER['REQUEST_URI'] = '/admin/users/edit/abc';
        $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
        $_SERVER['HTTP_USER_AGENT'] = 'phpunit';

        $repo = $this->createMock(SystemAuditLogRepository::class);
        $repo->expects($this->once())->method('create')->willReturn(5);

        $settings = $this->createMock(SettingsSystemAuditGateway::class);
        $settings->method('isSystemAuditEnabled')->willReturn(true);

        $service = new SystemAuditService($repo, new SystemAuditRedactionService(), $settings, new SessionStore());

        $id = $service->record('admin.users.update', 'success', [
            'target_type' => 'user',
            'target_id' => 10,
            'before' => ['active' => 0],
            'after' => ['active' => 1],
        ]);

        $this->assertSame(5, $id);
    }

    public function testRecordIsFailOpenOnRepositoryError(): void
    {
        $repo = $this->createMock(SystemAuditLogRepository::class);
        $repo->method('create')->willThrowException(new \RuntimeException('db down'));

        $settings = $this->createMock(SettingsSystemAuditGateway::class);
        $settings->method('isSystemAuditEnabled')->willReturn(true);

        $service = new SystemAuditService($repo, new SystemAuditRedactionService(), $settings, new SessionStore());

        $this->assertNull($service->record('admin.users.update', 'success'));
    }

    public function testPurgeUsesConfiguredRetention(): void
    {
        $repo = $this->createMock(SystemAuditLogRepository::class);
        $repo->expects($this->once())->method('purgeOlderThanDays')->with(120)->willReturn(3);

        $settings = $this->createMock(SettingsSystemAuditGateway::class);
        $settings->method('getSystemAuditRetentionDays')->willReturn(120);

        $service = new SystemAuditService($repo, new SystemAuditRedactionService(), $settings, new SessionStore());

        $this->assertSame(3, $service->purgeExpired());
    }
}
