<?php

declare(strict_types=1);

namespace Tests\Support;

use App\Framework\Http\SseStreamInterface;
use App\Framework\Router\Result\SseEvent;

/**
 * Mock SSE Stream for Testing
 *
 * Simulates SSE stream behavior without actual HTTP connection.
 * Records all sent events for assertion in tests.
 *
 * This is a standalone test implementation that mimics SseStream
 * but does not extend it (since it's final).
 */
final class MockSseStream implements SseStreamInterface
{
    /** @var array<SseEvent> */
    private array $sentEvents = [];

    private bool $isActive = true;

    private bool $connectionActive = true;

    public function __construct()
    {
        // No parent constructor call - we don't need actual stream
    }

    public function sendEvent(SseEvent $event): void
    {
        if (!$this->isActive || !$this->connectionActive) {
            throw new \RuntimeException('Connection is not active');
        }

        $this->sentEvents[] = $event;
    }

    public function sendHeartbeat(): void
    {
        if (!$this->isActive || !$this->connectionActive) {
            throw new \RuntimeException('Connection is not active');
        }

        // Record heartbeat as special event
        $this->sentEvents[] = new SseEvent(
            data: ':heartbeat',
            event: 'heartbeat'
        );
    }

    public function isActive(): bool
    {
        return $this->isActive;
    }

    public function isConnectionActive(): bool
    {
        return $this->connectionActive;
    }

    /**
     * Simulate connection becoming inactive (for testing)
     */
    public function simulateDisconnect(): void
    {
        $this->isActive = false;
        $this->connectionActive = false;
    }

    /**
     * Simulate connection timeout (for testing)
     */
    public function simulateTimeout(): void
    {
        $this->connectionActive = false;
    }

    /**
     * Get all sent events (for testing)
     *
     * @return array<SseEvent>
     */
    public function getSentEvents(): array
    {
        return $this->sentEvents;
    }

    /**
     * Get sent events by type (for testing)
     *
     * @return array<SseEvent>
     */
    public function getSentEventsByType(string $eventType): array
    {
        return array_filter(
            $this->sentEvents,
            fn(SseEvent $event) => $event->event === $eventType
        );
    }

    /**
     * Get sent events count
     */
    public function getSentEventsCount(): int
    {
        return count($this->sentEvents);
    }

    /**
     * Clear all sent events (for testing)
     */
    public function clear(): void
    {
        $this->sentEvents = [];
    }

    /**
     * Reset connection state (for testing)
     */
    public function reset(): void
    {
        $this->sentEvents = [];
        $this->isActive = true;
        $this->connectionActive = true;
    }
}
