<?php

declare(strict_types=1);

use App\Application\LiveComponents\Dashboard\QueueStatsComponent;
use App\Application\LiveComponents\Dashboard\QueueStatsState;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
use App\Framework\Queue\Queue;
use App\Framework\Queue\Services\JobMetricsManagerInterface;
use App\Framework\Queue\ValueObjects\JobMetrics;
use App\Framework\Core\ValueObjects\Duration;

describe('QueueStatsComponent', function () {
    beforeEach(function () {
        // Mock Queue
        $this->queue = Mockery::mock(Queue::class);

        // Mock JobMetricsManager
        $this->metricsManager = Mockery::mock(JobMetricsManagerInterface::class);

        $this->componentId = ComponentId::create('queue-stats', 'test');
        $this->initialState = QueueStatsState::empty();
    });

    afterEach(function () {
        Mockery::close();
    });

    it('polls and updates state with queue statistics', function () {
        // Mock queue stats
        $this->queue->shouldReceive('getStats')
            ->once()
            ->andReturn([
                'total_size' => 42,
                'priority_breakdown' => ['high' => 10, 'medium' => 20, 'low' => 12],
            ]);

        $this->queue->shouldReceive('size')
            ->once()
            ->andReturn(42);

        // Mock metrics
        $jobMetrics = new JobMetrics(
            totalJobs: 1000,
            successfulJobs: 950,
            failedJobs: 50,
            avgExecutionTime: Duration::fromMilliseconds(123.45),
            successRate: 95.0
        );

        $this->metricsManager->shouldReceive('getAllQueueMetrics')
            ->once()
            ->with('1 hour')
            ->andReturn([$jobMetrics]);

        $component = new QueueStatsComponent(
            id: $this->componentId,
            state: $this->initialState,
            queue: $this->queue,
            metricsManager: $this->metricsManager
        );

        $newState = $component->poll();

        expect($newState)->toBeInstanceOf(QueueStatsState::class);
        expect($newState->currentQueueSize)->toBe(42);
        expect($newState->totalJobs)->toBe(1000);
        expect($newState->successfulJobs)->toBe(950);
        expect($newState->failedJobs)->toBe(50);
        expect($newState->successRate)->toBe(95.0);
        expect($newState->avgExecutionTimeMs)->toBe(123.45);
        expect($newState->lastUpdated)->not->toBe($this->initialState->lastUpdated);
    });

    it('has correct poll interval', function () {
        $component = new QueueStatsComponent(
            id: $this->componentId,
            state: $this->initialState,
            queue: $this->queue,
            metricsManager: $this->metricsManager
        );

        expect($component->getPollInterval())->toBe(5000);
    });

    it('returns correct render data', function () {
        $state = new QueueStatsState(
            currentQueueSize: 10,
            totalJobs: 100,
            successfulJobs: 90,
            failedJobs: 10,
            successRate: 90.0,
            avgExecutionTimeMs: 50.0,
            lastUpdated: '2024-01-15 12:00:00'
        );

        $component = new QueueStatsComponent(
            id: $this->componentId,
            state: $state,
            queue: $this->queue,
            metricsManager: $this->metricsManager
        );

        $renderData = $component->getRenderData();

        expect($renderData->templatePath)->toBe('livecomponent-queue-stats');
        expect($renderData->data)->toHaveKey('componentId');
        expect($renderData->data)->toHaveKey('stateJson');
        expect($renderData->data)->toHaveKey('pollInterval');
        expect($renderData->data['pollInterval'])->toBe(5000);
        expect($renderData->data['currentQueueSize'])->toBe(10);
        expect($renderData->data['totalJobs'])->toBe(100);
        expect($renderData->data['successRate'])->toBe(90.0);
    });

    it('handles empty metrics gracefully', function () {
        $this->queue->shouldReceive('getStats')
            ->once()
            ->andReturn(['total_size' => 0]);

        $this->queue->shouldReceive('size')
            ->once()
            ->andReturn(0);

        $this->metricsManager->shouldReceive('getAllQueueMetrics')
            ->once()
            ->with('1 hour')
            ->andReturn([]);

        $component = new QueueStatsComponent(
            id: $this->componentId,
            state: $this->initialState,
            queue: $this->queue,
            metricsManager: $this->metricsManager
        );

        $newState = $component->poll();

        expect($newState->currentQueueSize)->toBe(0);
        expect($newState->totalJobs)->toBe(0);
        expect($newState->successfulJobs)->toBe(0);
        expect($newState->failedJobs)->toBe(0);
    });
});
