<?php

declare(strict_types=1);

namespace App\Domain\Theme;

use App\Domain\Plugin\Hook;

/**
 * Named injection points for themes / plugins / site snippets.
 *
 * Themes call ThemeSlot::render('head') (or @themeslot('head')).
 * Plugins listen on Hook event "theme.{slot}".
 * Admin SnippetSettings also appends into these slots at boot.
 */
final class ThemeSlot
{
    public const HEAD = 'head';

    public const BODY_START = 'body_start';

    public const BODY_END = 'body_end';

    public const HEADER_AFTER = 'header_after';

    public const NAV_AFTER = 'nav_after';

    public const CONTENT_BEFORE = 'content_before';

    public const CONTENT_AFTER = 'content_after';

    public const ARTICLE_TOP = 'article_top';

    public const ARTICLE_BOTTOM = 'article_bottom';

    public const SIDEBAR_BEFORE = 'sidebar_before';

    public const SIDEBAR = 'sidebar';

    public const SIDEBAR_AFTER = 'sidebar_after';

    public const FOOTER_BEFORE = 'footer_before';

    public const FOOTER_AFTER = 'footer_after';

    /** @return list<string> */
    public static function all(): array
    {
        return [
            self::HEAD,
            self::BODY_START,
            self::BODY_END,
            self::HEADER_AFTER,
            self::NAV_AFTER,
            self::CONTENT_BEFORE,
            self::CONTENT_AFTER,
            self::ARTICLE_TOP,
            self::ARTICLE_BOTTOM,
            self::SIDEBAR_BEFORE,
            self::SIDEBAR,
            self::SIDEBAR_AFTER,
            self::FOOTER_BEFORE,
            self::FOOTER_AFTER,
        ];
    }

    public static function event(string $slot): string
    {
        return 'theme.'.$slot;
    }

    public static function render(string $slot): string
    {
        return Hook::gather(self::event($slot), '');
    }

    /**
     * Soft contract for theme authors & admin UI.
     * Sizes are recommendations only — the active theme's CSS wins.
     *
     * @return array<string, array{label: string, place: string, size: string, multi: bool}>
     */
    public static function catalog(): array
    {
        $catalog = [];

        foreach (self::all() as $slot) {
            $catalog[$slot] = [
                'label' => __('admin.slots.'.$slot.'.label'),
                'place' => __('admin.slots.'.$slot.'.place'),
                'size' => __('admin.slots.'.$slot.'.size'),
                'multi' => true,
            ];
        }

        return $catalog;
    }

    public static function hint(string $slot): string
    {
        $meta = self::catalog()[$slot] ?? null;
        if ($meta === null) {
            return __('admin.slots.custom', ['slot' => $slot]);
        }

        return __('admin.slots.hint', [
            'place' => $meta['place'],
            'size' => $meta['size'],
            'slot' => $slot,
        ]);
    }
}
