<?php

declare(strict_types=1);

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

use App\Application\LiveComponents\TodoList\TodoItemComponent;
use App\Application\LiveComponents\TodoList\TodoListComponent;
use App\Framework\LiveComponents\NestedComponentEventDispatcher;
use App\Framework\LiveComponents\NestedComponentManager;
use App\Framework\LiveComponents\ValueObjects\ComponentHierarchy;
use App\Framework\LiveComponents\ValueObjects\ComponentId;

echo "🧪 Testing Nested Components System\n";
echo str_repeat('=', 70) . "\n\n";

// Test 1: Component Hierarchy Creation
echo "Test 1: Component Hierarchy Creation\n";
echo str_repeat('-', 70) . "\n";

$hierarchy = ComponentHierarchy::root();
echo "✓ Created root hierarchy: depth={$hierarchy->depth}, isRoot=" . ($hierarchy->isRoot() ? 'true' : 'false') . "\n";

$parentId = ComponentId::fromString('todo-list:main');
$childId = ComponentId::fromString('todo-item:1');

$childHierarchy = ComponentHierarchy::fromParent($parentId, $childId);
echo "✓ Created child hierarchy: depth={$childHierarchy->depth}, isChild=" . ($childHierarchy->isChild() ? 'true' : 'false') . "\n";
echo "✓ Child has parent: " . ($childHierarchy->parentId !== null ? 'true' : 'false') . "\n";
echo "✓ Path length: " . count($childHierarchy->path) . "\n\n";

// Test 2: Nested Component Manager
echo "Test 2: Nested Component Manager\n";
echo str_repeat('-', 70) . "\n";

$nestedManager = new NestedComponentManager();

// Register parent (root)
$parentId = ComponentId::fromString('todo-list:main');
$nestedManager->registerHierarchy($parentId, ComponentHierarchy::root());
echo "✓ Registered parent component: {$parentId->toString()}\n";

// Register children
$childIds = [
    ComponentId::fromString('todo-item:1'),
    ComponentId::fromString('todo-item:2'),
    ComponentId::fromString('todo-item:3'),
];

foreach ($childIds as $childId) {
    $hierarchy = ComponentHierarchy::fromParent($parentId, $childId);
    $nestedManager->registerHierarchy($childId, $hierarchy);
    echo "✓ Registered child component: {$childId->toString()}\n";
}

// Verify hierarchy queries
echo "\nHierarchy Queries:\n";
echo "  Parent has children: " . ($nestedManager->hasChildren($parentId) ? 'true' : 'false') . "\n";
echo "  Number of children: " . count($nestedManager->getChildIds($parentId)) . "\n";
echo "  First child's parent: " . $nestedManager->getParentId($childIds[0])?->toString() . "\n";
echo "  Parent is root: " . ($nestedManager->isRoot($parentId) ? 'true' : 'false') . "\n";
echo "  Child is root: " . ($nestedManager->isRoot($childIds[0]) ? 'true' : 'false') . "\n";

// Statistics
$stats = $nestedManager->getStats();
echo "\nHierarchy Statistics:\n";
echo "  Total components: {$stats['total_components']}\n";
echo "  Root components: {$stats['root_components']}\n";
echo "  Child components: {$stats['child_components']}\n";
echo "  Max nesting depth: {$stats['max_nesting_depth']}\n";
echo "  Parents with children: {$stats['parent_components_with_children']}\n\n";

// Test 3: TodoList Component with Children
echo "Test 3: TodoList Component with Children\n";
echo str_repeat('-', 70) . "\n";

$todoListId = ComponentId::fromString('todo-list:demo');
$initialTodos = [
    [
        'id' => 'todo_1',
        'title' => 'Learn Nested Components',
        'completed' => false,
        'created_at' => time(),
    ],
    [
        'id' => 'todo_2',
        'title' => 'Implement Event Bubbling',
        'completed' => true,
        'created_at' => time() - 3600,
    ],
    [
        'id' => 'todo_3',
        'title' => 'Write Integration Tests',
        'completed' => false,
        'created_at' => time() - 7200,
    ],
];

$todoList = new TodoListComponent(
    id: $todoListId,
    initialData: null,
    todos: $initialTodos,
    filter: 'all'
);

echo "✓ Created TodoList component: {$todoListId->toString()}\n";
echo "  Initial todos count: " . count($initialTodos) . "\n";

// Get child component IDs
$childComponents = $todoList->getChildComponents();
echo "  Child components declared: " . count($childComponents) . "\n";
foreach ($childComponents as $childIdString) {
    echo "    - {$childIdString}\n";
}

// Test child compatibility
$validChild = ComponentId::fromString('todo-item:test');
$invalidChild = ComponentId::fromString('other-component:test');

echo "\n  Child compatibility tests:\n";
echo "    todo-item:test can be child: " . ($todoList->canHaveChild($validChild) ? 'true' : 'false') . "\n";
echo "    other-component:test can be child: " . ($todoList->canHaveChild($invalidChild) ? 'true' : 'false') . "\n";

// Test Actions
echo "\n  Testing Actions:\n";

// Add Todo
$newData = $todoList->addTodo('New Todo Item');
$newDataArray = $newData->toArray();
echo "    ✓ Added todo, new count: " . count($newDataArray['todos']) . "\n";

// Set Filter
$filteredData = $todoList->setFilter('active');
echo "    ✓ Changed filter to 'active'\n";

// Clear Completed
$clearedData = $todoList->clearCompleted();
echo "    ✓ Cleared completed todos\n\n";

// Test 4: TodoItem Component
echo "Test 4: TodoItem Component\n";
echo str_repeat('-', 70) . "\n";

$todoItemId = ComponentId::fromString('todo-item:demo_1');
$todoData = [
    'id' => 'demo_1',
    'title' => 'Test TodoItem',
    'completed' => false,
    'created_at' => time(),
];

// Create event dispatcher
$eventDispatcher = new NestedComponentEventDispatcher();

$todoItem = new TodoItemComponent(
    id: $todoItemId,
    eventDispatcher: $eventDispatcher,
    initialData: null,
    todoData: $todoData
);

echo "✓ Created TodoItem component: {$todoItemId->toString()}\n";
echo "  Title: " . $todoData['title'] . "\n";
echo "  Completed: " . ($todoData['completed'] ? 'true' : 'false') . "\n\n";

echo "  Testing TodoItem Actions:\n";

// Toggle
$eventDispatcher->clear();
$todoItem->toggle();
echo "    ✓ Toggled todo\n";
echo "    Events dispatched: " . $eventDispatcher->count() . "\n";
if ($eventDispatcher->hasEvents()) {
    foreach ($eventDispatcher->getEvents() as $event) {
        echo "      📡 {$event['event_name']} from {$event['component_id']}\n";
    }
}
echo "\n";

// Start Edit
$editData = $todoItem->startEdit();
echo "    ✓ Started edit mode\n";

// Save Edit
$eventDispatcher->clear();
$savedData = $todoItem->saveEdit('Updated Title');
echo "    ✓ Saved edit\n";
echo "    Events dispatched: " . $eventDispatcher->count() . "\n";
if ($eventDispatcher->hasEvents()) {
    foreach ($eventDispatcher->getEvents() as $event) {
        echo "      📡 {$event['event_name']} from {$event['component_id']}\n";
    }
}
echo "\n";

// Delete
$eventDispatcher->clear();
$todoItem->delete();
echo "    ✓ Deleted todo\n";
echo "    Events dispatched: " . $eventDispatcher->count() . "\n";
if ($eventDispatcher->hasEvents()) {
    foreach ($eventDispatcher->getEvents() as $event) {
        echo "      📡 {$event['event_name']} from {$event['component_id']}\n";
    }
}
echo "\n";

// Test 5: Event Bubbling Simulation
echo "Test 5: Event Bubbling Simulation\n";
echo str_repeat('-', 70) . "\n";

// Create parent with event handling
$parentId = ComponentId::fromString('todo-list:bubble-test');
$parent = new TodoListComponent(
    id: $parentId,
    initialData: null,
    todos: [
        ['id' => 'child_1', 'title' => 'First Todo', 'completed' => false, 'created_at' => time()],
    ]
);

$childId = ComponentId::fromString('todo-item:child_1');

// Test different events
$events = [
    ['todo-completed', ['todo_id' => 'child_1', 'completed' => true]],
    ['todo-deleted', ['todo_id' => 'child_1']],
    ['todo-title-changed', ['todo_id' => 'child_1', 'title' => 'Updated Title']],
];

echo "Testing event bubbling (check error_log for details):\n";
foreach ($events as [$eventName, $payload]) {
    $shouldContinue = $parent->onChildEvent($childId, $eventName, $payload);
    echo "  ✓ {$eventName}: bubbling " . ($shouldContinue ? 'continues' : 'stopped') . "\n";
}

echo "\n";

// Test 6: Circular Dependency Detection
echo "Test 6: Circular Dependency Detection\n";
echo str_repeat('-', 70) . "\n";

try {
    $selfId = ComponentId::fromString('component:self');
    $circularHierarchy = ComponentHierarchy::fromParent($selfId, $selfId);

    $manager = new NestedComponentManager();
    $manager->registerHierarchy($selfId, $circularHierarchy);

    echo "❌ Should have thrown exception for circular dependency\n";
} catch (\InvalidArgumentException $e) {
    echo "✓ Circular dependency correctly detected and prevented\n";
    echo "  Error message: {$e->getMessage()}\n";
}

echo "\n";

// Summary
echo str_repeat('=', 70) . "\n";
echo "✅ All Nested Components Tests Completed!\n\n";

echo "Summary:\n";
echo "  ✓ Component Hierarchy Value Objects\n";
echo "  ✓ Nested Component Manager\n";
echo "  ✓ TodoList Parent Component\n";
echo "  ✓ TodoItem Child Component\n";
echo "  ✓ Event Dispatching\n";
echo "  ✓ Event Bubbling\n";
echo "  ✓ Circular Dependency Protection\n\n";

echo "Next Steps:\n";
echo "  - Integrate with LiveComponentHandler\n";
echo "  - Test in browser with real DOM\n";
echo "  - Add client-side event bubbling tests\n";
echo "  - Implement Slot System for flexible composition\n";
