<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\Contracts;

use App\Framework\LiveComponents\ValueObjects\SlotContent;
use App\Framework\LiveComponents\ValueObjects\SlotContext;
use App\Framework\LiveComponents\ValueObjects\SlotDefinition;

/**
 * Supports Slots Contract
 *
 * Components implementing this interface can define slots that can be filled
 * with content from parent components or consumers.
 *
 * Similar to Vue's slots or React's children/render props pattern.
 *
 * Example:
 * ```php
 * #[LiveComponent('card')]
 * final readonly class CardComponent implements SupportsSlots
 * {
 *     public function getSlotDefinitions(): array
 *     {
 *         return [
 *             SlotDefinition::default('<p>Default content</p>'),
 *             SlotDefinition::named('header'),
 *             SlotDefinition::named('footer'),
 *         ];
 *     }
 *
 *     public function getSlotContext(string $slotName): SlotContext
 *     {
 *         return SlotContext::create([
 *             'card_title' => $this->state->title,
 *             'card_type' => $this->state->type
 *         ]);
 *     }
 * }
 * ```
 */
interface SupportsSlots
{
    /**
     * Get slot definitions for this component
     *
     * Returns array of SlotDefinition objects that define available slots.
     *
     * @return array<SlotDefinition> Array of slot definitions
     */
    public function getSlotDefinitions(): array;

    /**
     * Get context data for a specific slot (scoped slots)
     *
     * Returns data that will be available to slot content.
     * Used for scoped slots where parent needs access to child data.
     *
     * @param string $slotName Name of the slot
     * @return SlotContext Context data for the slot
     */
    public function getSlotContext(string $slotName): SlotContext;

    /**
     * Process slot content before rendering
     *
     * Optional hook to transform or validate slot content.
     * Default implementation should return content unchanged.
     *
     * @param SlotContent $content Slot content to process
     * @return SlotContent Processed slot content
     */
    public function processSlotContent(SlotContent $content): SlotContent;

    /**
     * Validate that required slots are filled
     *
     * Called before rendering to ensure all required slots have content.
     *
     * @param array<SlotContent> $providedSlots Slots provided by parent
     * @return array<string> Array of validation error messages (empty if valid)
     */
    public function validateSlots(array $providedSlots): array;
}
