<?php
declare(strict_types=1);

namespace Celena\Plugin\Handbook\Controllers;

use Celena\Core\Http\Request;
use Celena\Core\Http\Response;
use Celena\Core\I18n\Locale;
use Celena\Core\I18n\Translator;
use Celena\Core\Kernel;
use Celena\Core\Template\Engine;
use Celena\Plugin\Handbook\Support\DocPage;
use Celena\Plugin\Handbook\Support\Navigation;
use Celena\Module\Settings\Options;

/**
 * Публичный раздел документации /docs (EN/UK/RU).
 *
 * Язык — через существующий Locale::detect() (?lang / cookie / Accept-Language),
 * нормализуется к трём языкам раздела. Контент — Markdown-файлы content/{lang}/.
 */
final class DocsController
{
    /** @var list<string> */
    private const LANGS = ['ru', 'uk', 'en'];

    /** Версия статики раздела — бампить при правке docs.css/docs.js. */
    private const ASSET_VER = '1';

    private readonly string $base;

    public function __construct(
        private readonly Engine $engine,
        private readonly Options $options,
        private readonly Locale $locale,
        private readonly Translator $translator,
    ) {
        $this->base = Kernel::rootPath() . '/plugins/handbook';
    }

    /** Главная раздела: карточки двух частей (панель / код). */
    public function index(Request $request): Response
    {
        $lang = $this->lang($request);
        $this->translator->setLocale($lang);
        $nav = $this->nav();

        // Главная раздела — со слешем: в docroot есть реальная папка docs/ (dev-материалы),
        // и сервер делает 301 /docs → /docs/. Канон и ссылки используют /docs/, чтобы
        // не было лишнего редиректа. Подстраницы /docs/{section}/{page} конфликта не имеют.
        $vars = $this->commonVars($request, $lang, '/docs/', $this->t('handbook.title'), $this->t('handbook.subtitle'));
        $vars['docs_cards'] = $nav->cards($lang);
        $vars['docs_home'] = '1';

        return $this->view('plugins/handbook/docs/index', $vars);
    }

    /** Страница документации /docs/{section}/{page}. */
    public function show(Request $request, array $params): Response
    {
        $lang = $this->lang($request);
        $this->translator->setLocale($lang);
        $nav = $this->nav();

        $section = (string) ($params['section'] ?? '');
        $page = (string) ($params['page'] ?? '');

        if (!$nav->sectionExists($section)) {
            return Response::notFound();
        }
        if ($page === '') {
            $page = $nav->firstPage($section) ?? '';
            if ($page === '') {
                return Response::notFound();
            }
        }

        $entry = $nav->find($section, $page);
        if ($entry === null) {
            return Response::notFound();
        }

        $doc = (new DocPage($this->base . '/content'))->load($lang, $entry['file']);
        if ($doc === null) {
            return Response::notFound();
        }

        $pageTitle = $nav->pageTitle($entry, $lang);
        $path = '/docs/' . $section . '/' . $page;

        $vars = $this->commonVars($request, $lang, $path, $pageTitle . ' · ' . $this->t('handbook.title'), $this->t('handbook.subtitle'));
        $vars['doc_title']    = $pageTitle;
        $vars['doc_content']  = $doc['html'];
        $vars['doc_toc']      = $this->decorateToc($doc['toc']);
        $vars['has_toc']      = $doc['toc'] === [] ? '' : '1';
        $vars['fallback']     = $doc['fallback'] ? '1' : '';
        $vars['sidebar']      = $nav->sidebar($lang, $section, $page);
        $vars['breadcrumbs']  = $nav->breadcrumbs($lang, $section, $page, $this->t('handbook.title'));

        return $this->view('plugins/handbook/docs/layout', $vars);
    }

    // ───────── helpers ─────────

    private function nav(): Navigation
    {
        return new Navigation($this->base . '/content/nav.php');
    }

    private function lang(Request $request): string
    {
        $l = $this->locale->detect($request);
        return in_array($l, self::LANGS, true) ? $l : 'en';
    }

    private function t(string $key): string
    {
        return $this->translator->translate($key);
    }

    private function view(string $template, array $vars): Response
    {
        $this->engine->setTheme((string) $this->options->get('theme', 'default'));
        return Response::html($this->engine->render($template, $vars));
    }

    /**
     * Общие переменные: site, SEO, переключатель языка, hreflang (через head_extra),
     * canonical для текущего языка.
     */
    private function commonVars(Request $request, string $lang, string $path, string $seoTitle, string $seoDesc): array
    {
        $siteName = (string) $this->options->get('site_name', 'Celena');
        $siteUrl = rtrim((string) $this->options->get('site_url', ''), '/');
        if ($siteUrl === '') {
            $siteUrl = ($request->isHttps() ? 'https' : 'http') . '://' . $request->host();
        }
        $def = $this->locale->default();

        $canonical = $siteUrl . $path . ($lang !== $def ? '?lang=' . $lang : '');

        // hreflang только по трём языкам раздела + x-default (en).
        $headExtra = '';
        foreach (self::LANGS as $code) {
            $href = $siteUrl . $path . ($code !== $def ? '?lang=' . $code : '');
            $headExtra .= '<link rel="alternate" hreflang="' . $code . '" href="' . htmlspecialchars($href, ENT_QUOTES, 'UTF-8') . '">' . "\n";
        }
        $headExtra .= '<link rel="alternate" hreflang="x-default" href="' . htmlspecialchars($siteUrl . $path, ENT_QUOTES, 'UTF-8') . '">' . "\n";

        // Ассеты раздела (имя ≠ slug → не подключаются через {plugin_assets} глобально).
        $headExtra .= '<link rel="stylesheet" href="/public/assets/plugins/handbook/docs.css?v=' . self::ASSET_VER . '">' . "\n";
        $headExtra .= '<script src="/public/assets/plugins/handbook/docs.js?v=' . self::ASSET_VER . '" defer></script>' . "\n";

        // Переключатель языка в шапке раздела.
        $labels = ['ru' => 'Русский', 'uk' => 'Українська', 'en' => 'English'];
        $langLinks = [];
        foreach (self::LANGS as $code) {
            $langLinks[] = [
                'code'      => $code,
                'label'     => $labels[$code] ?? $code,
                'href'      => $path . ($code !== $def ? '?lang=' . $code : ''),
                'is_active' => $code === $lang ? '1' : '',
            ];
        }

        return [
            'site'               => ['name' => $siteName, 'url' => $siteUrl],
            'page'               => ['title' => $seoTitle, 'og_image' => ''],
            'seo_title_override' => $seoTitle . ' — ' . $siteName,
            'seo_desc_override'  => $seoDesc,
            'canonical_url'      => $canonical,
            'no_hreflang'        => '1',
            'head_extra'         => $headExtra,
            'lang_links'         => $langLinks,
            'docs_lang'          => $lang,
        ];
    }

    /** Помечает h3 как вложенные пункты оглавления. */
    private function decorateToc(array $toc): array
    {
        $out = [];
        foreach ($toc as $t) {
            $out[] = [
                'id'     => (string) ($t['id'] ?? ''),
                'text'   => (string) ($t['text'] ?? ''),
                'is_sub' => ((int) ($t['level'] ?? 2)) >= 3 ? '1' : '',
            ];
        }
        return $out;
    }
}
