<?php

declare(strict_types=1);

use App\Application\LiveComponents\Dashboard\SchedulerState;

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

        expect($state->totalScheduledTasks)->toBe(0);
        expect($state->dueTasks)->toBe(0);
        expect($state->upcomingTasks)->toBe([]);
        expect($state->nextExecution)->toBeNull();
        expect($state->statistics)->toBe([]);
        expect($state->lastUpdated)->toBeString();
    });

    it('creates state from array', function () {
        $data = [
            'totalScheduledTasks' => 10,
            'dueTasks' => 2,
            'upcomingTasks' => [
                [
                    'id' => 'task-1',
                    'schedule_type' => 'cron',
                    'next_run' => '2024-01-15 13:00:00',
                ],
            ],
            'nextExecution' => '2024-01-15 13:00:00',
            'statistics' => [
                'total_executions_today' => 50,
            ],
            'lastUpdated' => '2024-01-15 12:00:00',
        ];

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

        expect($state->totalScheduledTasks)->toBe(10);
        expect($state->dueTasks)->toBe(2);
        expect($state->upcomingTasks)->toHaveCount(1);
        expect($state->nextExecution)->toBe('2024-01-15 13:00:00');
    });

    it('converts state to array', function () {
        $upcomingTasks = [
            [
                'id' => 'task-1',
                'schedule_type' => 'interval',
                'next_run' => '2024-01-15 13:00:00',
                'next_run_relative' => 'in 1 hour',
                'is_due' => false,
            ],
        ];

        $statistics = [
            'successful_executions' => 45,
            'failed_executions' => 5,
        ];

        $state = new SchedulerState(
            totalScheduledTasks: 5,
            dueTasks: 1,
            upcomingTasks: $upcomingTasks,
            nextExecution: '2024-01-15 13:00:00',
            statistics: $statistics,
            lastUpdated: '2024-01-15 12:00:00'
        );

        $array = $state->toArray();

        expect($array)->toHaveKey('totalScheduledTasks');
        expect($array)->toHaveKey('dueTasks');
        expect($array)->toHaveKey('upcomingTasks');
        expect($array)->toHaveKey('nextExecution');
        expect($array)->toHaveKey('statistics');
        expect($array['upcomingTasks'])->toHaveCount(1);
    });

    it('creates new state with updated scheduler data', function () {
        $state = SchedulerState::empty();

        $upcomingTasks = [
            [
                'id' => 'backup-task',
                'schedule_type' => 'cron',
                'next_run' => '2024-01-15 02:00:00',
                'is_due' => true,
            ],
        ];

        $statistics = [
            'tasks_executed_today' => 20,
            'average_execution_time' => 1.5,
        ];

        $updatedState = $state->withSchedulerData(
            totalScheduledTasks: 3,
            dueTasks: 1,
            upcomingTasks: $upcomingTasks,
            nextExecution: '2024-01-15 02:00:00',
            statistics: $statistics
        );

        // Original unchanged
        expect($state->totalScheduledTasks)->toBe(0);
        expect($state->upcomingTasks)->toBe([]);
        expect($state->nextExecution)->toBeNull();

        // New state updated
        expect($updatedState->totalScheduledTasks)->toBe(3);
        expect($updatedState->dueTasks)->toBe(1);
        expect($updatedState->upcomingTasks)->toHaveCount(1);
        expect($updatedState->nextExecution)->toBe('2024-01-15 02:00:00');
        expect($updatedState->statistics)->toHaveKey('tasks_executed_today');
        expect($updatedState->lastUpdated)->not->toBe($state->lastUpdated);
    });

    it('is immutable', function () {
        $state = new SchedulerState(
            totalScheduledTasks: 10,
            dueTasks: 2,
            upcomingTasks: [],
            nextExecution: '2024-01-15 12:00:00',
            statistics: [],
            lastUpdated: '2024-01-15 11:00:00'
        );

        $newState = $state->withSchedulerData(
            totalScheduledTasks: 15,
            dueTasks: 3,
            upcomingTasks: [],
            nextExecution: '2024-01-15 13:00:00',
            statistics: []
        );

        // Original unchanged
        expect($state->totalScheduledTasks)->toBe(10);
        expect($state->dueTasks)->toBe(2);

        // New instance
        expect($newState)->not->toBe($state);
        expect($newState->totalScheduledTasks)->toBe(15);
        expect($newState->dueTasks)->toBe(3);
    });

    it('handles null next execution', function () {
        $state = SchedulerState::empty()->withSchedulerData(
            totalScheduledTasks: 0,
            dueTasks: 0,
            upcomingTasks: [],
            nextExecution: null,
            statistics: []
        );

        expect($state->nextExecution)->toBeNull();
        expect($state->totalScheduledTasks)->toBe(0);
    });

    it('handles empty upcoming tasks', function () {
        $state = SchedulerState::empty()->withSchedulerData(
            totalScheduledTasks: 0,
            dueTasks: 0,
            upcomingTasks: [],
            nextExecution: null,
            statistics: []
        );

        expect($state->upcomingTasks)->toBe([]);
        expect($state->statistics)->toBe([]);
    });
});
