<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use App\Framework\LiveComponents\ValueObjects\ComponentData;
use App\Framework\LiveComponents\ValueObjects\ComponentId;

echo "Testing ComponentRegistry Value Objects Integration\n";
echo "===================================================\n\n";

$testsPassed = 0;
$testsFailed = 0;

function test(string $name, callable $fn): void
{
    global $testsPassed, $testsFailed;

    try {
        $fn();
        echo "✅ {$name}\n";
        $testsPassed++;
    } catch (Throwable $e) {
        echo "❌ {$name}\n";
        echo "   Error: {$e->getMessage()}\n";
        echo "   File: {$e->getFile()}:{$e->getLine()}\n";
        $testsFailed++;
    }
}

// Test 1: ComponentId creation
test('ComponentId: makeId returns ComponentId', function () {
    $id = App\Framework\LiveComponents\ComponentRegistry::makeId('counter', 'demo');
    assert($id instanceof ComponentId);
    assert($id->name === 'counter');
    assert($id->instanceId === 'demo');
    assert($id->toString() === 'counter:demo');
});

// Test 2: ComponentId parsing
test('ComponentId: fromString parses correctly', function () {
    $id = ComponentId::fromString('user-card:user-123');
    assert($id->name === 'user-card');
    assert($id->instanceId === 'user-123');
});

// Test 3: ComponentData conversion
test('ComponentData: fromArray creates immutable data', function () {
    $data = ComponentData::fromArray(['count' => 5, 'label' => 'Clicks']);
    assert($data->get('count') === 5);
    assert($data->get('label') === 'Clicks');
    assert($data->isEmpty() === false);
    assert($data->size() === 2);
});

// Test 4: ComponentData immutability
test('ComponentData: with() creates new instance', function () {
    $data1 = ComponentData::fromArray(['count' => 0]);
    $data2 = $data1->with('count', 10);

    assert($data1->get('count') === 0); // Original unchanged
    assert($data2->get('count') === 10); // New instance updated
    assert($data1 !== $data2); // Different instances
});

// Test 5: ComponentData toArray
test('ComponentData: toArray conversion', function () {
    $originalArray = ['user' => 'john', 'role' => 'admin'];
    $data = ComponentData::fromArray($originalArray);
    $convertedArray = $data->toArray();

    assert($convertedArray === $originalArray);
});

// Test 6: ComponentId equality
test('ComponentId: equals comparison', function () {
    $id1 = ComponentId::create('counter', 'demo');
    $id2 = ComponentId::create('counter', 'demo');
    $id3 = ComponentId::create('counter', 'other');

    assert($id1->equals($id2));
    assert(! $id1->equals($id3));
});

// Test 7: ComponentData merge
test('ComponentData: merge combines data', function () {
    $data1 = ComponentData::fromArray(['a' => 1, 'b' => 2]);
    $data2 = ComponentData::fromArray(['c' => 3, 'd' => 4]);
    $merged = $data1->merge($data2);

    assert($merged->get('a') === 1);
    assert($merged->get('b') === 2);
    assert($merged->get('c') === 3);
    assert($merged->get('d') === 4);
    assert($merged->size() === 4);
});

// Test 8: ComponentData filtering
test('ComponentData: only() filters keys', function () {
    $data = ComponentData::fromArray(['name' => 'John', 'age' => 30, 'email' => 'john@example.com']);
    $filtered = $data->only(['name', 'email']);

    assert($filtered->size() === 2);
    assert($filtered->has('name'));
    assert($filtered->has('email'));
    assert(! $filtered->has('age'));
});

// Test 9: ComponentData except
test('ComponentData: except() excludes keys', function () {
    $data = ComponentData::fromArray(['a' => 1, 'b' => 2, 'c' => 3]);
    $filtered = $data->except(['b']);

    assert($filtered->size() === 2);
    assert($filtered->has('a'));
    assert(! $filtered->has('b'));
    assert($filtered->has('c'));
});

// Test 10: ComponentId generate
test('ComponentId: generate() creates unique IDs', function () {
    $id1 = ComponentId::generate('counter');
    $id2 = ComponentId::generate('counter');

    assert($id1->name === 'counter');
    assert($id2->name === 'counter');
    assert($id1->instanceId !== $id2->instanceId); // Different instances
    assert(! $id1->equals($id2));
});

echo "\n";
echo "===================================================\n";
echo "Tests passed: {$testsPassed}\n";
echo "Tests failed: {$testsFailed}\n";
echo "===================================================\n";

if ($testsFailed > 0) {
    exit(1);
}

echo "\n✅ All ComponentRegistry Value Object tests passed!\n";
