<?php

declare(strict_types=1);

namespace App\Blog\Support;

use App\Models\Setting;

/**
 * 主题内容注入点：在标准位置注入广告/统计/临时链接等 HTML。
 *
 * 注入点（Blade @stack，主题视图内置）：
 *   head / header / sidebar_top / sidebar_bottom / content_top / content_bottom
 *   post_content_top / post_content_bottom / footer / body_end
 *
 * 特性：
 *   1. 同一位置可配置「多条」注入块（后台主题注入页管理），按 sort 顺序渲染
 *   2. 每条可启停
 *   3. 插件可通过 filter `theme.inject.{point}` 追加
 *   4. 主题变量（stylevar）：theme('var', 'key') 引用任意键值 HTML
 */
class ThemeInjector
{
    public const POINTS = [
        'head' => '页头（</head> 前）',
        'header' => '页头下方',
        'sidebar_top' => '侧边栏顶部',
        'sidebar_bottom' => '侧边栏底部',
        'content_top' => '内容区顶部',
        'content_bottom' => '内容区底部',
        'post_content_top' => '文章正文前',
        'post_content_bottom' => '文章正文后',
        'footer' => '页脚前',
        'body_end' => '页面末尾（</body> 前）',
    ];

    /**
     * 读取某一注入点的所有注入块（多条，已排序、已过滤停用），
     * 并把插件追加的 HTML 合并进来。
     */
    public static function blocksFor(string $point): array
    {
        $raw = Setting::get('inject.blocks', []);
        $raw = is_array($raw) ? $raw : (json_decode((string) $raw, true) ?: []);

        $blocks = collect($raw)
            ->filter(fn (array $b) => ($b['point'] ?? null) === $point && ($b['enabled'] ?? true))
            ->sortBy(fn (array $b) => (int) ($b['sort'] ?? 0))
            ->pluck('html')
            ->filter()
            ->values()
            ->all();

        $extra = (string) app(PluginManager::class)->applyFilters("theme.inject.{$point}", '');

        if ($extra !== '') {
            $blocks[] = $extra;
        }

        return $blocks;
    }

    /**
     * 注册 View Composer：渲染前台视图前把各注入点内容 push 到对应 @stack。
     */
    public static function registerComposer(): void
    {
        $views = ['index', 'show', 'list', 'archives', 'tags', 'tag', 'search', 'links', 'comments', 'login', 'register', 'profile', 'membership.*', 'payments.*'];

        \Illuminate\Support\Facades\View::composer($views, function (\Illuminate\View\View $view) {
            foreach (array_keys(self::POINTS) as $point) {
                foreach (self::blocksFor($point) as $html) {
                    $view->getFactory()->startPush("theme:{$point}", $html);
                }
            }
        });
    }
}
