<?php

namespace App\Services;

use App\Models\Component;
use Illuminate\Support\Facades\Log;
use Twig\Environment;
use Twig\Error\Error as TwigError;
use Twig\Loader\FilesystemLoader;

class ComponentRendererService
{
    private Environment $twig;

    public function __construct()
    {
        $this->initializeTwigEnvironment();
    }

    /**
     * Render component with sample data
     */
    public function renderComponent(Component $component): string
    {
        if (! $component->is_renderable) {
            return $this->renderError($component->error_message ?? 'Component is not renderable');
        }

        try {
            // Simple approach: just pass the show_dummy_data flag
            // Components now define their own dummy data inline
            $sampleData = ['show_dummy_data' => true];
            $template = $this->twig->load('includes/'.$component->path);

            return $template->render($sampleData);
        } catch (TwigError $e) {
            $errorMessage = "Twig error in {$component->path}: ".$e->getMessage();
            Log::error($errorMessage);

            return $this->renderError($errorMessage);
        } catch (\Exception $e) {
            $errorMessage = "Rendering error in {$component->path}: ".$e->getMessage();
            Log::error($errorMessage);

            return $this->renderError($errorMessage);
        }
    }

    /**
     * Get component with sample data for API response
     */
    public function getComponentWithSampleData(Component $component): array
    {
        // Simple approach: components define their own dummy data inline
        $sampleData = ['show_dummy_data' => true];
        $usage = [
            'include_example' => "{% include 'includes/{$component->path}' %}",
            'required_variables' => ['show_dummy_data'],
            'optional_variables' => ['All component-specific variables defined in the component file'],
        ];

        return [
            'component' => $component->toArray(),
            'sample_data' => $sampleData,
            'usage' => $usage,
        ];
    }

    /**
     * Render component preview page (full HTML)
     */
    public function renderComponentPreview(Component $component): string
    {
        $componentOutput = '';
        $errorMessage = null;

        if ($component->is_renderable) {
            try {
                $componentOutput = $this->renderComponent($component);
            } catch (\Exception $e) {
                $errorMessage = $e->getMessage();
            }
        } else {
            $errorMessage = $component->error_message;
        }

        $sampleData = ['show_dummy_data' => true];
        $usage = [
            'include_example' => "{% include 'includes/{$component->path}' %}",
            'required_variables' => ['show_dummy_data'],
            'optional_variables' => ['All component-specific variables defined in the component file'],
        ];

        return $this->renderPreviewHtml([
            'component' => $component,
            'componentOutput' => $componentOutput,
            'errorMessage' => $errorMessage,
            'sampleData' => $sampleData,
            'usage' => $usage,
        ]);
    }

    /**
     * Initialize Twig environment using main system's approach
     */
    private function initializeTwigEnvironment(): void
    {
        // Use the same Twig initialization pattern as the main system
        $path = base_path().'/';
        $templatesPath = base_path('sites/default/templates');

        if (! is_dir($templatesPath)) {
            throw new \RuntimeException("Templates directory not found: {$templatesPath}");
        }

        // Initialize Twig loader with multiple template paths
        $coreTemplatesPath = base_path('core/templates');
        $loader = new FilesystemLoader([$templatesPath, $coreTemplatesPath]);

        // Create Twig environment with component-specific settings
        $this->twig = new Environment($loader, [
            'cache' => false, // Disable caching for component preview
            'debug' => config('app.debug', false),
            'strict_variables' => false, // Allow undefined variables for sample data
        ]);

        // Add debug extension if needed
        if (config('app.debug', false)) {
            $this->twig->addExtension(new \Twig\Extension\DebugExtension);
        }

        // The functions.twig.php file expects a global $twig variable
        global $twig;
        $twig = $this->twig;

        // Load the main system's Twig functions (includes file_get_contents, config, etc.)
        $functionsPath = $path.'core/includes/functions.twig.php';
        if (! file_exists($functionsPath)) {
            throw new \RuntimeException("Functions file not found: {$functionsPath}");
        }

        include $functionsPath;

        // Add the same global variables as main system
        $this->addMainSystemGlobals();
    }

    /**
     * Add main system's global variables and any component-specific customizations
     */
    private function addMainSystemGlobals(): void
    {
        // Add the same global variables as the main system
        // Get all user defined settings (same as header.inc.php)
        $settings = get_defined_constants(true);
        $settings = $settings['user'];
        $this->twig->addGlobal('settings', $settings);

        // Add image folders global (components often use this)
        global $image_folders;
        if (isset($image_folders)) {
            $this->twig->addGlobal('image_folders', $image_folders);
        }

        // Vite functions (vite, vite_css) are already loaded via functions.twig.php

        // Load plugins and modules (same as main system)
        $this->loadPluginsAndModules();
    }

    /**
     * Load plugins and modules (same as main system)
     */
    private function loadPluginsAndModules(): void
    {
        $loaded_module_paths = [];
        $module_types = ['plugins', 'modules'];

        $previous_dir = getcwd();

        foreach ($module_types as $module_type) {
            $module_folder_parent = base_path().'/'.$module_type.'/';

            if (is_dir($module_folder_parent)) {
                chdir($module_folder_parent);

                $modules = [];

                // Check if there is a user-defined module order
                if (file_exists('./.order')) {
                    $modules = file('./.order');
                    $modules = array_map(trim(...), $modules);
                    $modules = array_filter($modules, static fn($module) => ! empty($module));
                }

                // Add unlisted modules from the modules directory
                $modules = array_merge($modules, glob('*', GLOB_ONLYDIR));
                $modules = array_unique($modules);

                foreach ($modules as $module) {
                    $module_folder = $module_folder_parent.$module;

                    if (is_dir($module_folder) && $module != '.' && $module != '..') {
                        if (is_file($module_folder.'/loader.php')) {
                            $loaded_module_paths[] = $module_folder.'/loader.php';
                        }
                    }
                }
            }
        }

        chdir($previous_dir);

        // Load plugin functions manually since the global $twig approach doesn't work
        $this->registerPluginFunctions();
    }

    /**
     * Register plugin functions manually
     */
    private function registerPluginFunctions(): void
    {
        // Register ShareButtons follow_buttons function
        $this->twig->addFunction(
            new \Twig\TwigFunction('follow_buttons', function ($template = 'social/follow_buttons.twig') {
                // Use the ShareButtons class if available, otherwise return empty content for preview
                try {
                    if (class_exists(\Mtc\Plugins\ShareButtons\Classes\ShareButtons::class)) {
                        $shareButtonsClass = \Mtc\Plugins\ShareButtons\Classes\ShareButtons::class;
                        $follow_buttons = (new $shareButtonsClass)
                            ->where('hide', 0)
                            ->orderBy('order', 'ASC')
                            ->get();

                        return $this->twig->render($template, compact('follow_buttons'));
                    } else {
                        // Fallback for component preview
                        return '<div class="social-buttons-preview">Social buttons would appear here</div>';
                    }
                } catch (\Exception $e) {
                    Log::error('Error rendering follow_buttons: '.$e->getMessage());

                    return '<div class="social-buttons-preview">Social buttons would appear here</div>';
                }
            }),
        );
    }

    /**
     * Render error message
     */
    private function renderError(string $message): string
    {
        return (
            '<div class="component-render-error" style="background: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; padding: 1rem; margin: 1rem 0; border-radius: 4px;">'
            .'<strong>Rendering Error:</strong> '
            .htmlspecialchars($message)
            .'</div>'
        );
    }

    /**
     * Render full HTML preview page
     */
    private function renderPreviewHtml(array $data): string
    {
        $component = $data['component'];
        $componentOutput = $data['componentOutput'];
        $errorMessage = $data['errorMessage'];
        $usage = $data['usage'];

        // Generate Vite asset URLs using shared functions from functions.twig.php
        $jsUrl = '';
        $cssUrls = [];
        $viteFunction = $this->twig->getFunction('vite');
        $viteCssFunction = $this->twig->getFunction('vite_css');
        if ($viteFunction) {
            $jsUrl = $viteFunction->getCallable()('js/app.js');
        }
        if ($viteCssFunction) {
            $cssUrls = $viteCssFunction->getCallable()('js/app.js');
        }

        // Generate CSS link tags
        $cssLinks = '';
        foreach ($cssUrls as $url) {
            $cssLinks .= '    <link href="'.htmlspecialchars((string) $url).'" rel="stylesheet">'."\n";
        }

        $html =
            '<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Component Preview: '.htmlspecialchars((string) $component->name).'</title>
'.$cssLinks.'    <style>
        body {
            font-family: system-ui, -apple-system, sans-serif;
            line-height: 1.5;
            margin: 0;
            padding: 0;
            background: #f8f9fa;
        }
        #vue_environment {
            padding: 2rem;
        }
        .component-preview {
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .component-info {
            padding: 2rem;
            border-bottom: 1px solid #e9ecef;
            background: #f8f9fa;
        }
        .component-info h1 {
            margin: 0 0 0.5rem 0;
            color: #212529;
        }
        .component-info p {
            margin: 0 0 2rem 0;
            color: #6c757d;
        }
        .component-info h2 {
            margin: 0 0 1rem 0;
            font-size: 1.25rem;
            color: #495057;
        }
        .component-info pre {
            background: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            padding: 1rem;
            overflow-x: auto;
            font-size: 0.875rem;
        }
        .component-output {
            padding: 2rem;
        }
        .component-output h3 {
            margin: 0 0 1rem 0;
            color: #495057;
        }
        .component-error {
            padding: 2rem;
            background: #f8d7da;
            border-left: 4px solid #dc3545;
        }
        .component-error h1 {
            color: #721c24;
            margin: 0 0 1rem 0;
        }
        .component-error p {
            margin: 0.5rem 0;
        }
        .component-error pre {
            background: #f5c6cb;
            border: 1px solid #f1aeb5;
            border-radius: 4px;
            padding: 1rem;
            margin: 1rem 0;
            white-space: pre-wrap;
            font-size: 0.875rem;
        }
    </style>
</head>
<body>
<div id="vue_environment">';

        if ($errorMessage) {
            $html .=
                '
    <div class="component-error">
        <h1>Rendering Error</h1>
        <p><strong>Component:</strong> '
                .htmlspecialchars((string) $component->path)
                .'</p>
        <p><strong>Error:</strong> '
                .htmlspecialchars((string) $errorMessage)
                .'</p>
    </div>';
        } else {
            $html .=
                '
    <div class="component-preview">
        <div class="component-info">
            <h1>'
                .htmlspecialchars((string) $component->name)
                .'</h1>
            <p>'
                .htmlspecialchars((string) $component->description)
                .'</p>

            <h2>Usage</h2>
            <pre><code>'
                .htmlspecialchars((string) $usage['include_example'])
                .'</code></pre>';

            if (! empty($usage['required_variables'])) {
                $html .=
                    '<p><strong>Required variables:</strong> '
                    .implode(', ', array_map(htmlspecialchars(...), $usage['required_variables']))
                    .'</p>';
            }

            if (! empty($usage['optional_variables'])) {
                $html .=
                    '<p><strong>Optional variables:</strong> '
                    .implode(', ', array_map(htmlspecialchars(...), $usage['optional_variables']))
                    .'</p>';
            }

            $html .= '
        </div>

        <div class="component-output">
            <h3>Component Preview</h3>
            '.$componentOutput.'
        </div>
    </div>';
        }

        $html .= '
</div>
    <script src="'.htmlspecialchars((string) $jsUrl).'" type="module"></script>
</body>
</html>';

        return $html;
    }
}
