<?php
declare(strict_types=1);

namespace Tests;

use App\Core\EventBus;
use PHPUnit\Framework\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        EventBus::enableTestMode();
    }

    protected function tearDown(): void
    {
        EventBus::disableTestMode();
        parent::tearDown();
    }

    protected function assertEventDispatched(string $eventName, ?callable $assertion = null): void
    {
        $dispatched = EventBus::getDispatched();
        $matches = array_filter($dispatched, fn($e) => $e['event'] === $eventName);

        $this->assertNotEmpty($matches, "Expected event '{$eventName}' was not dispatched.");

        if ($assertion !== null) {
            $first = array_values($matches)[0];
            $assertion($first['data']);
        }
    }

    protected function assertEventNotDispatched(string $eventName): void
    {
        $dispatched = EventBus::getDispatched();
        $matches = array_filter($dispatched, fn($e) => $e['event'] === $eventName);

        $this->assertEmpty($matches, "Event '{$eventName}' was unexpectedly dispatched.");
    }

    protected function assertEventDispatchedCount(string $eventName, int $count): void
    {
        $dispatched = EventBus::getDispatched();
        $matches = array_filter($dispatched, fn($e) => $e['event'] === $eventName);

        $this->assertCount($count, $matches, "Expected event '{$eventName}' to be dispatched {$count} time(s), got " . count($matches) . ".");
    }

    protected function getDispatchedEvents(): array
    {
        return EventBus::getDispatched();
    }
}
