<?php
declare(strict_types=1);

namespace Celena\Module\Docs;

use Celena\Core\Http\Request;
use Celena\Core\Http\Response;
use Celena\Core\Kernel;
use Celena\Core\Plugin\PluginManager;
use Celena\Core\Security\Auth;
use Celena\Core\Security\Filter;
use Celena\Core\Support\Markdown;
use Celena\Core\Template\Engine;
use Celena\Core\Template\TagDocs;
use Celena\Module\AdminBase\AdminController;
use Celena\Module\Settings\Options;

/**
 * Встроенная документация для админа: справочник по тегам шаблонизатора.
 * Доступен как страница /admin/docs/tags и как фрагмент /admin/docs/tags-panel
 * (без head/foot) — для отображения в выезжающем drawer-окне редактора шаблонов.
 */
final class DocsController extends AdminController
{
    public function __construct(Engine $engine, Auth $auth, Options $options)
    {
        parent::__construct($engine, $auth, $options);
    }

    public function tags(Request $request): Response
    {
        if (!$this->auth->check()) return Response::redirect('/admin/login');
        return $this->view('admin/docs/tags', $this->vars(), 'docs-tags', 'Теги шаблонов');
    }

    /** AJAX-фрагмент только с содержимым справочника — без head/foot. */
    public function tagsPanel(Request $request): Response
    {
        if (!$this->auth->check()) return Response::json(['error' => 'forbidden'], 403);
        $engine = Kernel::container()->make(Engine::class);
        $engine->setTheme('admin');
        $html = $engine->render('admin/docs/tags-panel', $this->vars());
        return Response::html($html);
    }

    /**
     * Фрагмент drawer'а с документацией конкретного плагина.
     * GET /admin/docs/plugin-panel?slug=<slug>&doc=<file.md>
     */
    public function pluginDocsPanel(Request $request): Response
    {
        if (!$this->auth->check()) return Response::json(['error' => 'forbidden'], 403);
        $slug = Filter::slug($request->query('slug'));
        if ($slug === '') {
            return Response::html('<p class="muted">Плагин не указан.</p>');
        }
        /** @var PluginManager $pm */
        $pm = Kernel::container()->make(PluginManager::class);
        $manifest = $pm->all()[$slug] ?? null;
        if ($manifest === null) {
            return Response::html('<p class="muted">Плагин не найден.</p>');
        }
        $sections = $pm->docsFor($slug);
        if ($sections === []) {
            return Response::html('<div class="plugin-docs"><h2>' . e((string) ($manifest['name'] ?? $slug)) . '</h2><p class="muted">У плагина нет документации (отсутствует папка <code>docs/</code>).</p></div>');
        }

        $requestedDoc = (string) $request->query('doc', '');
        $active = null;
        foreach ($sections as $s) {
            if ($s['file'] === $requestedDoc || $s['slug'] === $requestedDoc) {
                $active = $s;
                break;
            }
        }
        if ($active === null) {
            $active = $sections[0];
        }
        // Защита: путь должен оставаться внутри docs/ плагина (PluginManager::docsFor уже отдаёт только из docs/, но проверим ещё раз).
        $expectedPrefix = realpath(dirname((string) $active['abs_path']));
        $actual         = realpath((string) $active['abs_path']);
        if ($expectedPrefix === false || $actual === false || !str_starts_with($actual, $expectedPrefix)) {
            return Response::html('<p class="muted">Файл документации недоступен.</p>');
        }

        $md = (string) @file_get_contents($active['abs_path']);
        $body = Markdown::render($md);

        $engine = Kernel::container()->make(Engine::class);
        $engine->setTheme('admin');
        $html = $engine->render('admin/docs/plugin-panel', [
            'plugin'   => [
                'slug'    => $slug,
                'name'    => (string) ($manifest['name'] ?? $slug),
                'version' => (string) ($manifest['version'] ?? ''),
                'author'  => (string) ($manifest['author'] ?? ''),
            ],
            'sections' => $sections,
            'active'   => $active,
            'body'     => $body,
        ]);
        return Response::html($html);
    }

    private function vars(): array
    {
        $tr = Kernel::container()->make(\Celena\Core\I18n\Translator::class);
        $tags = TagDocs::all();
        $grouped = [];
        foreach ($tags as $t) {
            $grouped[$t['group']][] = $t;
        }
        $groups = [];
        foreach (['var', 'control', 'lists', 'core', 'plugin', 'content'] as $g) {
            if (!empty($grouped[$g])) {
                $groups[] = [
                    'slug'  => $g,
                    'label' => $tr->translate('admin.docs_tag_group_' . $g),
                    'tags'  => $grouped[$g],
                ];
            }
        }
        return [
            'groups'         => $groups,
            'params_label'   => $tr->translate('admin.docs_tag_params'),
            'example_label'  => $tr->translate('admin.docs_tag_example'),
            'required_label' => $tr->translate('admin.docs_tag_param_required'),
            'optional_label' => $tr->translate('admin.docs_tag_param_optional'),
        ];
    }
}
