<?php

declare(strict_types=1);

use App\Framework\Cache\Warming\ValueObjects\WarmupResult;

describe('WarmupResult', function () {
    it('creates result with valid data', function () {
        $result = new WarmupResult(
            strategyName: 'test_strategy',
            itemsWarmed: 10,
            itemsFailed: 2,
            durationSeconds: 1.5,
            memoryUsedBytes: 1024000
        );

        expect($result->strategyName)->toBe('test_strategy');
        expect($result->itemsWarmed)->toBe(10);
        expect($result->itemsFailed)->toBe(2);
        expect($result->durationSeconds)->toBe(1.5);
        expect($result->memoryUsedBytes)->toBe(1024000);
    });

    it('calculates success correctly', function () {
        $successResult = new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 10,
            itemsFailed: 0,
            durationSeconds: 1.0,
            memoryUsedBytes: 1024
        );

        expect($successResult->isSuccess())->toBeTrue();

        $failureResult = new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 0,
            itemsFailed: 5,
            durationSeconds: 1.0,
            memoryUsedBytes: 1024
        );

        expect($failureResult->isSuccess())->toBeFalse();
    });

    it('calculates success rate', function () {
        $result = new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 8,
            itemsFailed: 2,
            durationSeconds: 1.0,
            memoryUsedBytes: 1024
        );

        expect($result->getSuccessRate())->toBe(0.8);
    });

    it('handles zero total items', function () {
        $result = new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 0,
            itemsFailed: 0,
            durationSeconds: 0.1,
            memoryUsedBytes: 1024
        );

        expect($result->getSuccessRate())->toBe(0.0);
    });

    it('calculates items per second', function () {
        $result = new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 100,
            itemsFailed: 0,
            durationSeconds: 2.0,
            memoryUsedBytes: 1024
        );

        expect($result->getItemsPerSecond())->toBe(50.0);
    });

    it('handles zero duration', function () {
        $result = new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 10,
            itemsFailed: 0,
            durationSeconds: 0.0,
            memoryUsedBytes: 1024
        );

        expect($result->getItemsPerSecond())->toBe(0.0);
    });

    it('calculates memory in MB', function () {
        $result = new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 10,
            itemsFailed: 0,
            durationSeconds: 1.0,
            memoryUsedBytes: 2048000 // 2MB
        );

        expect($result->getMemoryUsedMB())->toBe(2.0);
    });

    it('converts to array', function () {
        $result = new WarmupResult(
            strategyName: 'test_strategy',
            itemsWarmed: 10,
            itemsFailed: 2,
            durationSeconds: 1.5,
            memoryUsedBytes: 1024000,
            errors: [['item' => 'test', 'error' => 'failed']],
            metadata: ['key' => 'value']
        );

        $array = $result->toArray();

        expect($array)->toBeArray();
        expect($array['strategy_name'])->toBe('test_strategy');
        expect($array['items_warmed'])->toBe(10);
        expect($array['items_failed'])->toBe(2);
        expect($array['duration_seconds'])->toBe(1.5);
        expect($array['memory_used_bytes'])->toBe(1024000);
        expect($array['errors'])->toHaveCount(1);
        expect($array['metadata'])->toHaveKey('key');
    });

    it('throws on negative items warmed', function () {
        new WarmupResult(
            strategyName: 'test',
            itemsWarmed: -1,
            itemsFailed: 0,
            durationSeconds: 1.0,
            memoryUsedBytes: 1024
        );
    })->throws(InvalidArgumentException::class);

    it('throws on negative items failed', function () {
        new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 10,
            itemsFailed: -1,
            durationSeconds: 1.0,
            memoryUsedBytes: 1024
        );
    })->throws(InvalidArgumentException::class);

    it('throws on negative duration', function () {
        new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 10,
            itemsFailed: 0,
            durationSeconds: -1.0,
            memoryUsedBytes: 1024
        );
    })->throws(InvalidArgumentException::class);

    it('throws on negative memory', function () {
        new WarmupResult(
            strategyName: 'test',
            itemsWarmed: 10,
            itemsFailed: 0,
            durationSeconds: 1.0,
            memoryUsedBytes: -1024
        );
    })->throws(InvalidArgumentException::class);
});
