<?php

declare(strict_types=1);

namespace App\Application\LiveComponents;

use App\Framework\LiveComponents\Contracts\LiveComponent;
use App\Framework\LiveComponents\Contracts\SupportsSlots;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
use App\Framework\LiveComponents\ValueObjects\ComponentState;
use App\Framework\LiveComponents\ValueObjects\SlotContent;
use App\Framework\LiveComponents\ValueObjects\SlotContext;
use App\Framework\LiveComponents\ValueObjects\SlotDefinition;

/**
 * Layout Component with Multiple Slots
 *
 * Demonstrates complex layout with sidebar, main, and footer areas.
 * Uses scoped slots to provide layout metadata to child content.
 *
 * Example Usage:
 * ```html
 * <live-component name="layout" id="app-layout">
 *     <slot name="sidebar" scope="layout">
 *         <nav>
 *             <p>Width: {context.sidebarWidth}</p>
 *             <ul>...</ul>
 *         </nav>
 *     </slot>
 *
 *     <slot name="main">
 *         <h1>Main Content</h1>
 *         <p>Page content goes here</p>
 *     </slot>
 *
 *     <slot name="footer">
 *         <footer>© 2025</footer>
 *     </slot>
 * </live-component>
 * ```
 */
final readonly class LayoutComponent implements LiveComponent, SupportsSlots
{
    public function __construct(
        public ComponentId $id,
        public ComponentState $state
    ) {
    }

    public function getSlotDefinitions(): array
    {
        return [
            // Sidebar slot - scoped with layout dimensions
            SlotDefinition::scoped(
                name: 'sidebar',
                props: ['sidebarWidth', 'isCollapsed'],
                defaultContent: '<aside class="sidebar-default">Default Sidebar</aside>'
            ),

            // Main content slot - required
            SlotDefinition::named(
                name: 'main'
            )->withRequired(true),

            // Footer slot - optional
            SlotDefinition::named(
                name: 'footer',
                defaultContent: '<footer class="layout-footer">Default Footer</footer>'
            ),

            // Header slot - optional, added for completeness
            SlotDefinition::named(
                name: 'header',
                defaultContent: ''
            ),
        ];
    }

    public function getSlotContext(string $slotName): SlotContext
    {
        $sidebarWidth = $this->state->get('sidebarWidth', '250px');
        $isCollapsed = $this->state->get('sidebarCollapsed', false);

        return match ($slotName) {
            'sidebar' => SlotContext::create([
                'sidebarWidth' => $sidebarWidth,
                'isCollapsed' => $isCollapsed,
            ]),
            default => SlotContext::empty()
        };
    }

    public function processSlotContent(SlotContent $content): SlotContent
    {
        // Apply layout-specific structure
        $wrappedContent = match ($content->slotName) {
            'header' => '<header class="layout-header">' . $content->content . '</header>',
            'sidebar' => '<aside class="layout-sidebar">' . $content->content . '</aside>',
            'main' => '<main class="layout-main">' . $content->content . '</main>',
            'footer' => '<footer class="layout-footer">' . $content->content . '</footer>',
            default => $content->content
        };

        return $content->withContent($wrappedContent);
    }

    public function validateSlots(array $providedSlots): array
    {
        $errors = [];

        // Custom validation: check layout completeness
        $hasSidebar = false;
        $hasMain = false;

        foreach ($providedSlots as $slot) {
            if ($slot->slotName === 'sidebar') {
                $hasSidebar = true;
            }
            if ($slot->slotName === 'main') {
                $hasMain = true;
            }
        }

        // Warn if sidebar is provided but main is missing (unusual layout)
        if ($hasSidebar && ! $hasMain) {
            $errors[] = 'Layout has sidebar but no main content - this is an unusual configuration';
        }

        return $errors;
    }

    public function render(): string
    {
        return 'layout';
    }

    public function getComponentType(): string
    {
        return 'layout';
    }

    public function getId(): ComponentId
    {
        return $this->id;
    }

    public function getState(): ComponentState
    {
        return $this->state;
    }
}
