<?php

declare(strict_types=1);

namespace Tests\Framework\Search\ValueObjects;

use App\Framework\Search\ValueObjects\EntityId;
use InvalidArgumentException;

describe('EntityId Value Object', function () {
    it('can be created with valid ID', function () {
        $id = new EntityId('user_123');
        expect($id->value)->toBe('user_123');
    });

    it('can be created from string', function () {
        $id = EntityId::fromString('product_456');
        expect($id->toString())->toBe('product_456');
    });

    it('can generate unique ID', function () {
        $id1 = EntityId::generate();
        $id2 = EntityId::generate();

        expect($id1->toString())->not->toBe($id2->toString());
        expect($id1->toString())->toStartWith('entity_');
    });

    it('converts to string', function () {
        $id = new EntityId('test_789');
        expect($id->__toString())->toBe('test_789');
    });

    it('compares equality correctly', function () {
        $id1 = new EntityId('same_id');
        $id2 = new EntityId('same_id');
        $id3 = new EntityId('different_id');

        expect($id1->equals($id2))->toBeTrue();
        expect($id1->equals($id3))->toBeFalse();
    });

    it('throws exception for empty ID', function () {
        expect(fn () => new EntityId(''))->toThrow(InvalidArgumentException::class);
        expect(fn () => new EntityId('   '))->toThrow(InvalidArgumentException::class);
    });

    it('throws exception for too long ID', function () {
        $longId = str_repeat('a', 256);
        expect(fn () => new EntityId($longId))->toThrow(InvalidArgumentException::class);
    });

    it('throws exception for invalid characters', function () {
        expect(fn () => new EntityId('invalid@id'))->toThrow(InvalidArgumentException::class);
        expect(fn () => new EntityId('invalid id'))->toThrow(InvalidArgumentException::class);
        expect(fn () => new EntityId('invalid/id'))->toThrow(InvalidArgumentException::class);
    });

    it('allows valid characters', function () {
        expect(fn () => new EntityId('valid_id.123-test'))->not->toThrow(InvalidArgumentException::class);
        expect(fn () => new EntityId('123'))->not->toThrow(InvalidArgumentException::class);
        expect(fn () => new EntityId('a'))->not->toThrow(InvalidArgumentException::class);
    });
});
