<?php

declare(strict_types=1);

use App\Application\LiveComponents\Dashboard\QueueStatsState;

describe('QueueStatsState', function () {
    it('creates empty state with default values', function () {
        $state = QueueStatsState::empty();

        expect($state->currentQueueSize)->toBe(0);
        expect($state->totalJobs)->toBe(0);
        expect($state->successfulJobs)->toBe(0);
        expect($state->failedJobs)->toBe(0);
        expect($state->successRate)->toBe(0.0);
        expect($state->avgExecutionTimeMs)->toBe(0.0);
        expect($state->lastUpdated)->toBeString();
    });

    it('creates state from array', function () {
        $data = [
            'currentQueueSize' => 42,
            'totalJobs' => 1000,
            'successfulJobs' => 950,
            'failedJobs' => 50,
            'successRate' => 95.0,
            'avgExecutionTimeMs' => 123.45,
            'lastUpdated' => '2024-01-15 12:00:00',
        ];

        $state = QueueStatsState::fromArray($data);

        expect($state->currentQueueSize)->toBe(42);
        expect($state->totalJobs)->toBe(1000);
        expect($state->successfulJobs)->toBe(950);
        expect($state->failedJobs)->toBe(50);
        expect($state->successRate)->toBe(95.0);
        expect($state->avgExecutionTimeMs)->toBe(123.45);
        expect($state->lastUpdated)->toBe('2024-01-15 12:00:00');
    });

    it('converts state to array', function () {
        $state = new QueueStatsState(
            currentQueueSize: 10,
            totalJobs: 100,
            successfulJobs: 90,
            failedJobs: 10,
            successRate: 90.0,
            avgExecutionTimeMs: 50.5,
            lastUpdated: '2024-01-15 12:00:00'
        );

        $array = $state->toArray();

        expect($array)->toBe([
            'currentQueueSize' => 10,
            'totalJobs' => 100,
            'successfulJobs' => 90,
            'failedJobs' => 10,
            'successRate' => 90.0,
            'avgExecutionTimeMs' => 50.5,
            'lastUpdated' => '2024-01-15 12:00:00',
        ]);
    });

    it('creates new state with updated stats', function () {
        $state = QueueStatsState::empty();

        $updatedState = $state->withStats(
            currentQueueSize: 5,
            totalJobs: 50,
            successfulJobs: 45,
            failedJobs: 5,
            successRate: 90.0,
            avgExecutionTimeMs: 75.0
        );

        // Original state unchanged (immutable)
        expect($state->currentQueueSize)->toBe(0);
        expect($state->totalJobs)->toBe(0);

        // New state has updated values
        expect($updatedState->currentQueueSize)->toBe(5);
        expect($updatedState->totalJobs)->toBe(50);
        expect($updatedState->successfulJobs)->toBe(45);
        expect($updatedState->failedJobs)->toBe(5);
        expect($updatedState->successRate)->toBe(90.0);
        expect($updatedState->avgExecutionTimeMs)->toBe(75.0);
        expect($updatedState->lastUpdated)->not->toBe($state->lastUpdated);
    });

    it('handles zero division in success rate gracefully', function () {
        $state = new QueueStatsState(
            currentQueueSize: 0,
            totalJobs: 0,
            successfulJobs: 0,
            failedJobs: 0,
            successRate: 0.0,
            avgExecutionTimeMs: 0.0,
            lastUpdated: '2024-01-15 12:00:00'
        );

        expect($state->successRate)->toBe(0.0);
    });

    it('is immutable', 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'
        );

        $newState = $state->withStats(
            currentQueueSize: 20,
            totalJobs: 200,
            successfulJobs: 180,
            failedJobs: 20,
            successRate: 90.0,
            avgExecutionTimeMs: 60.0
        );

        // Original unchanged
        expect($state->currentQueueSize)->toBe(10);
        expect($state->totalJobs)->toBe(100);

        // New instance created
        expect($newState)->not->toBe($state);
        expect($newState->currentQueueSize)->toBe(20);
        expect($newState->totalJobs)->toBe(200);
    });
});
