<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\Contracts;

use App\Framework\LiveComponents\ValueObjects\ComponentId;

/**
 * Supports Nesting Contract
 *
 * Components implementing this interface can have child components.
 * Enables complex UI composition with parent-child relationships.
 *
 * Features:
 * - Child component registration
 * - Parent-to-child communication
 * - Child state synchronization
 * - Lifecycle management for children
 *
 * Example:
 * ```php
 * #[LiveComponent('todo-list')]
 * final readonly class TodoListComponent implements SupportsNesting
 * {
 *     public function getChildComponents(): array
 *     {
 *         return [
 *             'todo-item:1',
 *             'todo-item:2',
 *             'todo-item:3'
 *         ];
 *     }
 *
 *     public function onChildEvent(ComponentId $childId, string $eventName, array $payload): void
 *     {
 *         if ($eventName === 'item-completed') {
 *             // Handle child event
 *         }
 *     }
 * }
 * ```
 */
interface SupportsNesting
{
    /**
     * Get list of child component IDs
     *
     * Returns array of component ID strings that are children of this component.
     * Framework will ensure proper lifecycle management for all children.
     *
     * @return array<string> Array of component ID strings
     */
    public function getChildComponents(): array;

    /**
     * Handle event from child component
     *
     * Called when a child component dispatches an event that should bubble up.
     * Parent can handle the event and optionally prevent further bubbling.
     *
     * @param ComponentId $childId Child component that dispatched the event
     * @param string $eventName Name of the event
     * @param array $payload Event payload data
     * @return bool Return false to stop event bubbling, true to continue
     */
    public function onChildEvent(ComponentId $childId, string $eventName, array $payload): bool;

    /**
     * Validate child component compatibility
     *
     * Called before adding a child component. Parent can reject incompatible children.
     *
     * @param ComponentId $childId Child component ID to validate
     * @return bool True if child is compatible, false otherwise
     */
    public function canHaveChild(ComponentId $childId): bool;
}
