<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;

/**
 * KaTeX 服务端渲染服务
 *
 * 使用 Node.js 的 KaTeX 库在服务端预渲染 LaTeX 公式
 * 避免依赖 Chrome headless 执行 JavaScript
 */
class KatexRenderer
{
    /**
     * Node.js 脚本路径
     */
    private string $scriptPath;

    /**
     * 是否启用缓存
     */
    private bool $cacheEnabled = true;

    /**
     * 缓存前缀
     */
    private const CACHE_PREFIX = 'katex_rendered_';

    /**
     * 缓存时间（秒）
     */
    private const CACHE_TTL = 86400; // 24小时

    public function __construct()
    {
        $this->scriptPath = base_path('scripts/katex-render.mjs');
    }

    /**
     * 渲染 HTML 中的所有 LaTeX 公式
     *
     * @param string $html 包含 LaTeX 公式的 HTML
     * @return string 渲染后的 HTML
     */
    public function renderHtml(string $html): string
    {
        // 检查是否包含需要渲染的公式
        if (!$this->containsLatex($html)) {
            Log::debug('KatexRenderer: HTML 不包含 LaTeX 公式，跳过渲染');
            return $html;
        }

        // 尝试从缓存获取
        $cacheKey = $this->getCacheKey($html);
        if ($this->cacheEnabled && $cached = cache()->get($cacheKey)) {
            Log::debug('KatexRenderer: 从缓存获取渲染结果');
            return $cached;
        }

        // 调用 Node.js 脚本渲染
        $rendered = $this->callNodeScript($html);

        // 缓存结果
        if ($this->cacheEnabled && $rendered !== $html) {
            cache()->put($cacheKey, $rendered, self::CACHE_TTL);
        }

        return $rendered;
    }

    /**
     * 检查 HTML 是否包含 LaTeX 公式
     */
    private function containsLatex(string $html): bool
    {
        // 检查常见的 LaTeX 定界符
        return preg_match('/\$[^$]+\$|\$\$[\s\S]+?\$\$|\\\\\([\s\S]+?\\\\\)|\\\\\[[\s\S]+?\\\\\]/', $html) === 1;
    }

    /**
     * 调用 Node.js KaTeX 渲染脚本
     */
    private function callNodeScript(string $html): string
    {
        // 检查脚本是否存在
        if (!file_exists($this->scriptPath)) {
            Log::warning('KatexRenderer: 渲染脚本不存在', ['path' => $this->scriptPath]);
            return $html;
        }

        try {
            // 创建进程
            $process = new Process(['node', $this->scriptPath]);
            $process->setInput($html);
            $process->setTimeout(30); // 30秒超时

            // 执行
            $process->run();

            // 检查是否成功
            if (!$process->isSuccessful()) {
                Log::warning('KatexRenderer: Node.js 脚本执行失败', [
                    'exit_code' => $process->getExitCode(),
                    'error' => $process->getErrorOutput(),
                ]);
                return $html;
            }

            $output = $process->getOutput();

            // 验证输出
            if (empty($output)) {
                Log::warning('KatexRenderer: Node.js 脚本输出为空');
                return $html;
            }

            Log::info('KatexRenderer: LaTeX 公式渲染成功', [
                'input_length' => strlen($html),
                'output_length' => strlen($output),
            ]);

            return $output;

        } catch (\Exception $e) {
            Log::error('KatexRenderer: 渲染异常', [
                'error' => $e->getMessage(),
            ]);
            return $html;
        }
    }

    /**
     * 生成缓存键
     */
    private function getCacheKey(string $html): string
    {
        return self::CACHE_PREFIX . md5($html);
    }

    /**
     * 禁用缓存（用于调试）
     */
    public function disableCache(): self
    {
        $this->cacheEnabled = false;
        return $this;
    }

    /**
     * 启用缓存
     */
    public function enableCache(): self
    {
        $this->cacheEnabled = true;
        return $this;
    }

    /**
     * 清除所有 KaTeX 渲染缓存
     */
    public function clearCache(): void
    {
        // 注意：这个方法需要 Redis 或支持通配符删除的缓存驱动
        Log::info('KatexRenderer: 缓存清除请求（需要手动清理或使用 Redis）');
    }
}
