<?php

declare(strict_types=1);

namespace Tests\Unit\Application\Debug;

use App\Application\Debug\DebugCodeEvaluator;
use App\Application\Debug\EvaluationResult;

describe('DebugCodeEvaluator', function () {
    beforeEach(function () {
        $this->evaluator = new DebugCodeEvaluator();
    });

    it('evaluates simple return statement', function () {
        $result = $this->evaluator->evaluate('return 2 + 2;');

        expect($result)->toBeInstanceOf(EvaluationResult::class);
        expect($result->type)->toBe('int');
        expect($result->rawValue)->toBe(4);
    });

    it('evaluates string concatenation', function () {
        $result = $this->evaluator->evaluate('return "Hello" . " " . "World";');

        expect($result->type)->toBe('string');
        expect($result->rawValue)->toBe('Hello World');
    });

    it('evaluates array operations', function () {
        $result = $this->evaluator->evaluate('return array_map(fn($x) => $x * 2, [1, 2, 3]);');

        expect($result->type)->toBe('array');
        expect($result->rawValue)->toBe([2, 4, 6]);
    });

    it('captures echo output', function () {
        $result = $this->evaluator->evaluate('echo "Test output"; return null;');

        expect($result->output)->toContain('Test output');
    });

    it('measures execution time', function () {
        $result = $this->evaluator->evaluate('return 42;');

        expect($result->executionTime)->toBeGreaterThan(0);
        expect($result->executionTime)->toBeLessThan(1); // Should be very fast
    });

    it('throws exception for syntax errors', function () {
        expect(fn () => $this->evaluator->evaluate('return invalid syntax'))
            ->toThrow(\ParseError::class);
    });

    it('throws exception for runtime errors', function () {
        expect(fn () => $this->evaluator->evaluate('throw new \Exception("Test error");'))
            ->toThrow(\Exception::class, 'Test error');
    });

    it('formats array output', function () {
        $result = $this->evaluator->evaluate('return ["name" => "Alice", "age" => 30];');

        expect($result->output)->toContain('[');
        expect($result->output)->toContain('name');
        expect($result->output)->toContain('Alice');
    });

    it('handles null return value', function () {
        $result = $this->evaluator->evaluate('$x = 5; return null;');

        expect($result->type)->toBe('null');
        expect($result->output)->toBe('(no output)');
    });

    it('evaluates variable assignments', function () {
        $result = $this->evaluator->evaluate('$x = 10; $y = 20; return $x + $y;');

        expect($result->rawValue)->toBe(30);
        expect($result->type)->toBe('int');
    });
});
