<?php
/**
 * Twig Template Engine Service.
 *
 * @package WPBootstrap
 * @since 0.0.1
 */

namespace WPBootstrap\Twig;

use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFunction;
use Twig\TwigFilter;

class TwigService
{
    private static ?TwigService $instance = null;
    private Environment $twig;

    private function __construct()
    {
        $viewsDir = get_template_directory() . '/views';
        $cacheDir = WP_CONTENT_DIR . '/cache/twig';

        $loader = new FilesystemLoader($viewsDir);
        $this->twig = new Environment($loader, [
            'cache' => WP_DEBUG ? false : $cacheDir,
            'debug' => WP_DEBUG,
            'auto_reload' => true,
        ]);

        $this->registerWordPressFunctions();
        $this->registerWordPressGlobals();
        $this->registerFilters();
    }

    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function render(string $template, array $context = []): string
    {
        return $this->twig->render($template, $context);
    }

    public function display(string $template, array $context = []): void
    {
        $this->twig->display($template, $context);
    }

    public function getEnvironment(): Environment
    {
        return $this->twig;
    }

    private function registerWordPressFunctions(): void
    {
        // Translation functions.
        $this->twig->addFunction(new TwigFunction('__', function (string $text, string $domain = 'wp-bootstrap'): string {
            return __($text, $domain);
        }));

        $this->twig->addFunction(new TwigFunction('_e', function (string $text, string $domain = 'wp-bootstrap'): void {
            _e($text, $domain);
        }));

        $this->twig->addFunction(new TwigFunction('_n', function (string $single, string $plural, int $number, string $domain = 'wp-bootstrap'): string {
            return _n($single, $plural, $number, $domain);
        }));

        // Escaping functions.
        $this->twig->addFunction(new TwigFunction('esc_html', 'esc_html'));
        $this->twig->addFunction(new TwigFunction('esc_attr', 'esc_attr'));
        $this->twig->addFunction(new TwigFunction('esc_url', 'esc_url'));

        // WordPress head/footer output (captured via output buffering).
        $this->twig->addFunction(new TwigFunction('wp_head', function (): string {
            ob_start();
            wp_head();
            return ob_get_clean();
        }, ['is_safe' => ['html']]));

        $this->twig->addFunction(new TwigFunction('wp_footer', function (): string {
            ob_start();
            wp_footer();
            return ob_get_clean();
        }, ['is_safe' => ['html']]));

        $this->twig->addFunction(new TwigFunction('wp_body_open', function (): string {
            ob_start();
            wp_body_open();
            return ob_get_clean();
        }, ['is_safe' => ['html']]));

        // HTML attribute helpers.
        $this->twig->addFunction(new TwigFunction('language_attributes', function (): string {
            ob_start();
            language_attributes();
            return ob_get_clean();
        }, ['is_safe' => ['html']]));

        $this->twig->addFunction(new TwigFunction('body_class', function (string $extra = ''): string {
            ob_start();
            body_class($extra);
            return ob_get_clean();
        }, ['is_safe' => ['html']]));

        // URL and info helpers.
        $this->twig->addFunction(new TwigFunction('home_url', function (string $path = '/'): string {
            return home_url($path);
        }));

        $this->twig->addFunction(new TwigFunction('get_template_directory_uri', function (): string {
            return get_template_directory_uri();
        }));

        $this->twig->addFunction(new TwigFunction('get_bloginfo', function (string $show): string {
            return get_bloginfo($show);
        }));

        $this->twig->addFunction(new TwigFunction('get_search_query', function (): string {
            return get_search_query();
        }));

        // Content filtering.
        $this->twig->addFunction(new TwigFunction('wp_kses_post', function (string $content): string {
            return wp_kses_post($content);
        }, ['is_safe' => ['html']]));

        // Formatting.
        $this->twig->addFunction(new TwigFunction('number_format_i18n', function (float $number, int $decimals = 0): string {
            return number_format_i18n($number, $decimals);
        }));
    }

    private function registerWordPressGlobals(): void
    {
        $this->twig->addGlobal('site_name', get_bloginfo('name'));
        $this->twig->addGlobal('site_description', get_bloginfo('description'));
        $this->twig->addGlobal('site_url', home_url('/'));
        $this->twig->addGlobal('theme_uri', get_template_directory_uri());
        $this->twig->addGlobal('charset', get_bloginfo('charset'));
        $this->twig->addGlobal('current_year', date('Y'));
    }

    private function registerFilters(): void
    {
        $this->twig->addFilter(new TwigFilter('wpautop', 'wpautop', ['is_safe' => ['html']]));
        $this->twig->addFilter(new TwigFilter('wp_kses_post', 'wp_kses_post', ['is_safe' => ['html']]));
    }
}
