<?php

if (! defined('ABSPATH')) {
    exit;
} class PufferGo_Template_Loader
{
    private static $layouts = array();

    private static $headers = array();

    private static $footers = array();

    private static $content_templates = array();

    private static $initialized = false;

    public const THEME_FALLBACK_VARIANT = 'theme';

    private static $theme_fallback_layouts = array();

    private static $preview_session_synced = false;

    private const PREVIEW_SESSION_QUERY_KEY = 'puffergo_preview_session';

    private const PREVIEW_SESSION_TRANSIENT_PREFIX = 'pgo_preview_session_';

    private const PREVIEW_SESSION_TTL = 1800;

    public static function init()
    {
        if (self::$initialized) {
            return;
        } self::$initialized = true;
        self::$headers = self::discover_variants('templates/content-templates/header');
        self::$footers = self::discover_variants('templates/content-templates/footer');
        self::$content_templates = self::discover_content_templates();
        $categories = self::load_template_category_manifest();

        foreach ($categories as $category) {
            if (! is_array($category)) {
                continue;
            } $id = isset($category['id']) ? sanitize_key((string) $category['id']) : '';

            if ('' === $id) {
                continue;
            } $label = isset($category['label']) ? (string) $category['label'] : ucfirst(str_replace('-', ' ', $id));
            $file = isset($category['layoutFile']) ? sanitize_text_field((string) $category['layoutFile']) : '';
            $wp_template = isset($category['wp_template']) ? sanitize_text_field((string) $category['wp_template']) : '';
            $match = '__return_false';

            if (isset($category['matchStrategy']) && is_array($category['matchStrategy'])) {
                $match = self::build_match_callable_from_strategy($category['matchStrategy']);
            } self::register_layout($id, array('label' => __($label, 'puffergo'), 'file' => $file, 'wp_template' => $wp_template, 'match' => $match, ));

            if (! empty($category['themeFallback'])) {
                self::$theme_fallback_layouts[ $id ] = true;
                self::inject_theme_fallback_variant($id);
            }
        } add_filter('theme_page_templates', array(__CLASS__, 'filter_theme_page_templates'));
        add_filter('template_include', array(__CLASS__, 'filter_template_include'), 99);
        add_action('rest_api_init', array(__CLASS__, 'register_layout_template_rest_routes'));
        add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_scaffold_preview_navigation_persistence'), 5);
    }

    public static function register_layout($id, array $args)
    {
        self::$layouts[ $id ] = wp_parse_args($args, array('label' => '', 'wp_template' => '', 'file' => '', 'match' => '__return_false', ));
    }

    private static function build_match_callable_from_strategy(array $strategy)
    {
        $type = isset($strategy['type']) ? sanitize_key((string) $strategy['type']) : '';

        switch ($type) {
            case 'scaffold': return '__return_false';
            case 'singular': $post_type = isset($strategy['post_type']) ? sanitize_key((string) $strategy['post_type']) : '';

                return static function () use ($post_type) { return ('' !== $post_type) && is_singular($post_type); };
            case 'archive': $post_type = isset($strategy['post_type']) ? sanitize_key((string) $strategy['post_type']) : '';

                return static function () use ($post_type) { return ('' !== $post_type) && is_post_type_archive($post_type); };
            case 'tax': $taxonomy = isset($strategy['taxonomy']) ? sanitize_key((string) $strategy['taxonomy']) : '';

                return static function () use ($taxonomy) { return ('' !== $taxonomy) && is_tax($taxonomy); };
            case 'blog_home': return static function () { return is_home() && ! is_front_page(); };
            case 'woo_shop': return static function () { return function_exists('is_shop') && is_shop() && class_exists('PufferGo_Business_Mode') && PufferGo_Business_Mode::takeover_archive(); };
            case 'woo_product_cat': return static function () { return function_exists('is_product_category') && is_product_category() && class_exists('PufferGo_Business_Mode') && PufferGo_Business_Mode::takeover_archive(); };
            case 'woo_product': return static function () { return function_exists('is_product') && is_product() && class_exists('PufferGo_Business_Mode') && PufferGo_Business_Mode::takeover_single(); };
            case 'is_category': return static function () { return is_category(); };
            case 'is_404': return static function () { return is_404(); };
            case 'page_template': $template = isset($strategy['template']) ? sanitize_text_field((string) $strategy['template']) : '';

                return static function () use ($template) {
                    if ('' === $template || ! is_singular('page')) {
                        return false;
                    } $tpl = get_post_meta(get_the_ID(), '_wp_page_template', true);

                    return $tpl === $template;
                };
            case 'compound_or': $rules = isset($strategy['rules']) && is_array($strategy['rules']) ? $strategy['rules'] : array();
                $callables = array();

                foreach ($rules as $rule) {
                    if (is_array($rule)) {
                        $callables[] = self::build_match_callable_from_strategy($rule);
                    }
                }

return static function () use ($callables) {
                    foreach ($callables as $fn) {
                        if (is_callable($fn) && call_user_func($fn)) {
                            return true;
                        }
                    }

return false;
                };
            default: return '__return_false';
        }
    }

    private static function discover_content_templates()
    {
        $base_dir = PUFFERGO_PLUGIN_DIR . '/templates/content-templates';

        if (! is_dir($base_dir)) {
            return array();
        } $result = array();

        foreach (glob($base_dir . '/*', GLOB_ONLYDIR) as $type_dir) {
            $page_type = basename($type_dir);
            $result[ $page_type ] = self::discover_variants('templates/content-templates/' . $page_type);
        }

return $result;
    }

    private static function discover_variants($relative_dir)
    {
        $dir = PUFFERGO_PLUGIN_DIR . '/' . $relative_dir;

        if (! is_dir($dir)) {
            return array();
        } $variants = array();

        foreach (glob($dir . '/*', GLOB_ONLYDIR) as $variant_dir) {
            $template_file = self::resolve_variant_template_file($variant_dir);

            if (! $template_file) {
                continue;
            } $meta = array();
            $meta_file = $variant_dir . '/meta.json';

            if (file_exists($meta_file)) {
                $json = file_get_contents($meta_file);
                $decoded = json_decode($json, true);

                if (is_array($decoded)) {
                    $meta = $decoded;
                }
            }

if (empty($meta)) {
                $note_meta = self::extract_template_meta($template_file);
                $meta['id'] = basename($variant_dir);
                $meta['name'] = $note_meta['template_name'] ?? '';
                $meta['preview'] = $note_meta['template_preview'] ?? '';
                $meta['description'] = $note_meta['template_description'] ?? '';
            } $id = $meta['id'] ?? basename($variant_dir);
            $label = ! empty($meta['name']) ? $meta['name'] : self::generate_label_from_id($id);

            if (empty($meta['preview'])) {
                foreach (array('png', 'jpg', 'jpeg', 'webp', 'svg') as $ext) {
                    if (file_exists($variant_dir . '/preview.' . $ext)) {
                        $meta['preview'] = 'preview.' . $ext;
                        break;
                    }
                }
            } $uses = (isset($meta['uses']) && is_array($meta['uses'])) ? array_values($meta['uses']) : array();
            $defaults = (isset($meta['defaults']) && is_array($meta['defaults'])) ? $meta['defaults'] : array();
            $variants[ $id ] = array('id' => $id, 'file' => $template_file, 'label' => $label, 'preview' => $meta['preview'] ?? '', 'description' => $meta['description'] ?? '', 'uses' => $uses, 'defaults' => $defaults, );
        }

return $variants;
    }

    private static function resolve_variant_template_file($variant_dir)
    {
        $index_file = $variant_dir . '/index.php';

        if (file_exists($index_file)) {
            return $index_file;
        } $php_files = glob($variant_dir . '/*.php');

        if (empty($php_files)) {
            return null;
        }

return reset($php_files) ?: null;
    }

    private static function extract_template_name($file)
    {
        $meta = self::extract_template_meta($file);

        return isset($meta['name']) ? $meta['name'] : null;
    }

    private static function extract_template_meta($file)
    {
        $content = file_get_contents($file, false, null, 0, 2000);
        $meta = array();

        foreach (array('Template Name', 'Template Preview', 'Template Description') as $key) {
            if (preg_match('/\b' . preg_quote($key, '/') . ':\s*(.+)/i', $content, $m)) {
                $meta[ strtolower(str_replace(' ', '_', $key)) ] = trim($m[1]);
            }
        }

return $meta;
    }

    private static function generate_label_from_id($id)
    {
        $name = preg_replace('/^(header|footer)-/', '', $id);

        if ($name === $id) {
            return ucfirst(str_replace('-', ' ', $id));
        }

if (is_numeric($name)) {
            return sprintf(__('Variant %s', 'puffergo'), $name);
        }

return ucfirst(str_replace('-', ' ', $name));
    }

    private static function translate_label($label)
    {
        if (empty($label)) {
            return $label;
        }

return __($label, 'puffergo');
    }

    private static function translate_description($desc)
    {
        if (empty($desc)) {
            return $desc;
        }

return __($desc, 'puffergo');
    }

    private static function variant_css_class($id, $type)
    {
        $prefix = 'puffergo-' . $type . '-variant-';
        $name = preg_replace('/^(header|footer)-/', '', $id);

        return $prefix . $name;
    }

    public static function render_header()
    {
        $selected = self::get_active_header();
        self::render_variants('header', self::$headers, $selected);
    }

    public static function render_footer()
    {
        $selected = self::get_active_footer();
        self::render_variants('footer', self::$footers, $selected);
    }

    public static function render_layout_header()
    {
        if (self::needs_scaffold()) {
            require PUFFERGO_PLUGIN_DIR . '/templates/scaffold/init.php';
            require PUFFERGO_PLUGIN_DIR . '/templates/scaffold/document-open.php';
            self::render_header();
        } else {
            get_header();
        }
    }

    public static function render_layout_footer()
    {
        if (self::needs_scaffold()) {
            self::render_footer();
            require PUFFERGO_PLUGIN_DIR . '/templates/scaffold/document-close.php';
        } else {
            get_footer();
        }
    }

    private static function render_variants($type, $variants, $selected)
    {
        $scope = 'puffergo-fullpage-layout';
        $wrap = 'puffergo-' . $type . '-wrap';
        $data_attr = 'data-' . $type . '-template';
        $active_class = 'puffergo-' . $type . '-active';

        if (isset($variants[ $selected ])) {
            $data = self::create_variant_data($type);
            $css = self::variant_css_class($selected, $type);
            $behavior_class = '';

            if ('header' === $type && class_exists('PufferGo_Template_Config')) {
                $overlay = PufferGo_Template_Config::get_capability_values('header', 'header-overlay');

                if (isset($overlay['mode']) && 'on' === $overlay['mode']) {
                    $behavior_class = 'puffergo-header-overlay';
                }
            } printf('<div class="%s %s %s %s %s" %s="%s">', esc_attr($scope), esc_attr($wrap), esc_attr($css), esc_attr($active_class), esc_attr($behavior_class), esc_attr($data_attr), esc_attr($selected));

            if ('header' === $type && ! self::is_scaffold_preview_mode() && class_exists('PufferGo_Template_Config')) {
                PufferGo_Template_Config::print_header_style_block($selected);
            } require $variants[ $selected ]['file'];
            echo '</div>';
        }
    }

    private static function create_variant_data($type)
    {
        if ('header' === $type) {
            require_once PUFFERGO_PLUGIN_DIR . '/templates/data/class-puffergo-header-data.php';

            return PufferGo_Header_Data::from_current_page();
        }

if ('footer' === $type) {
            require_once PUFFERGO_PLUGIN_DIR . '/templates/data/class-puffergo-footer-data.php';

            return PufferGo_Footer_Data::from_global_context();
        }

return null;
    }

    public static function get_active_header()
    {
        return self::resolve_active_variant(self::get_active_scaffold_variant_option('header'), self::$headers, 'default');
    }

    public static function get_active_footer()
    {
        return self::resolve_active_variant(self::get_active_scaffold_variant_option('footer'), self::$footers, 'default');
    }

    private static function get_active_scaffold_variant_option($type)
    {
        if (self::is_edit_mode() || self::is_scaffold_preview_mode()) {
            $preview = isset($_GET['puffergo_preview'][ $type ]) ? sanitize_key(wp_unslash($_GET['puffergo_preview'][ $type ])) : '';
            $variants = 'header' === $type ? self::$headers : self::$footers;

            if ('' !== $preview && isset($variants[ $preview ])) {
                return $preview;
            }

if (self::is_scaffold_preview_mode()) {
                self::maybe_sync_preview_session_from_request();
                $preview_from_session = self::get_preview_variant_from_session($type, $variants);

                if ('' !== $preview_from_session) {
                    return $preview_from_session;
                }
            }
        } $new_option = get_option("puffergo_template_{$type}", '');

        if ('' !== $new_option) {
            return $new_option;
        }

return get_option("puffergo_{$type}_template", '');
    }

    private static function resolve_active_variant($selected, $variants, $fallback)
    {
        if (isset($variants[ $selected ])) {
            return $selected;
        }

return ! empty($variants) ? array_key_first($variants) : $fallback;
    }

    public static function is_edit_mode()
    {
        return ! empty($GLOBALS['puffergo_fullpage_template']) && current_user_can('edit_posts');
    }

    public static function filter_theme_page_templates($templates)
    {
        foreach (self::$layouts as $layout) {
            if (! empty($layout['wp_template']) && ! empty($layout['label'])) {
                $templates[ $layout['wp_template'] ] = $layout['label'];
            }
        }

return $templates;
    }

    public static function filter_template_include($template)
    {
        foreach (self::$layouts as $layout) {
            if (is_callable($layout['match']) && call_user_func($layout['match'])) {
                $file = PUFFERGO_PLUGIN_DIR . '/' . $layout['file'];

                if (file_exists($file)) {
                    return $file;
                }
            }
        }

return $template;
    }

    public static function is_puffergo_template()
    {
        foreach (self::$layouts as $layout) {
            if (is_callable($layout['match']) && call_user_func($layout['match'])) {
                return true;
            }
        }

return false;
    }

    public static function get_headers()
    {
        return self::$headers;
    }

    public static function get_footers()
    {
        return self::$footers;
    }

    private static function resolve_preview_url($preview, $file)
    {
        if (empty($preview)) {
            return '';
        }

if (preg_match('#^https?://#', $preview)) {
            return $preview;
        } $preview_path = dirname($file) . '/' . $preview;

        if (! file_exists($preview_path)) {
            return '';
        } $relative = str_replace(PUFFERGO_PLUGIN_DIR, '', $preview_path);
        $relative = ltrim($relative, '/');

        return plugin_dir_url(dirname(__FILE__)) . $relative;
    }

    private static function inject_theme_fallback_variant($layout_id)
    {
        $existing = isset(self::$content_templates[ $layout_id ]) && is_array(self::$content_templates[ $layout_id ]) ? self::$content_templates[ $layout_id ] : array();

        if (isset($existing[ self::THEME_FALLBACK_VARIANT ])) {
            return;
        } $theme_variant = array(self::THEME_FALLBACK_VARIANT => array('id' => self::THEME_FALLBACK_VARIANT, 'file' => null, 'label' => __('Theme default', 'puffergo'), 'preview' => '', 'description' => __('Keep your active theme / WooCommerce templates for this page. PufferGo does not take over.', 'puffergo'), 'uses' => array(), 'defaults' => array(), ), );
        self::$content_templates[ $layout_id ] = $theme_variant + $existing;
    }

    public static function layout_uses_puffergo_template($layout_id)
    {
        $active = self::get_active_content_template($layout_id);

        return '' !== $active && self::THEME_FALLBACK_VARIANT !== $active;
    }

    public static function get_content_templates($page_type)
    {
        return self::$content_templates[ $page_type ] ?? array();
    }

    public static function get_active_content_template($page_type)
    {
        $variants = self::$content_templates[ $page_type ] ?? array();
        $saved = get_option("puffergo_template_{$page_type}", '');

        if (self::is_edit_mode() || self::is_scaffold_preview_mode()) {
            $preview = isset($_GET['puffergo_preview'][ $page_type ]) ? sanitize_key(wp_unslash($_GET['puffergo_preview'][ $page_type ])) : '';

            if ($preview && isset($variants[ $preview ])) {
                return $preview;
            }

if (self::is_scaffold_preview_mode()) {
                self::maybe_sync_preview_session_from_request();
                $preview_from_session = self::get_preview_variant_from_session($page_type, $variants);

                if ('' !== $preview_from_session) {
                    return $preview_from_session;
                }
            }
        }

if ('' !== $saved && isset($variants[ $saved ])) {
            return $saved;
        }

return ! empty($variants) ? array_key_first($variants) : '';
    }

    public static function render_content_variant_isolated($page_type, $variant_id, $template_file, array $vars = array())
    {
        if ($template_file && self::try_render_template($template_file, $vars)) {
            return;
        } $default_file = self::get_content_template_file($page_type, 'default');

        if ($default_file && $default_file !== $template_file) {
            puffergo_log(sprintf('PufferGo: content variant "%s/%s" failed to render; falling back to default.', $page_type, $variant_id));

            if (self::try_render_template($default_file, $vars)) {
                return;
            }
        } echo '<main class="puffergo-fullpage-layout puffergo-content-wrapper"><p>' . esc_html__('Template not found.', 'puffergo') . '</p></main>';
    }

    private static function try_render_template($template_file, array $vars)
    {
        if (! $template_file || ! file_exists($template_file)) {
            return false;
        } $ob_level = ob_get_level();
        ob_start();

        try {
            extract($vars, EXTR_SKIP);
            require $template_file;
            echo ob_get_clean();

            return true;
        } catch (\Throwable $e) {
            while (ob_get_level() > $ob_level) {
                ob_end_clean();
            } puffergo_log(sprintf('PufferGo: template "%s" threw: %s', $template_file, $e->getMessage()));

            return false;
        }
    }

    public static function get_content_template_file($page_type, $variant_id)
    {
        return self::$content_templates[ $page_type ][ $variant_id ]['file'] ?? null;
    }

    public static function is_valid_content_template($page_type, $id)
    {
        return isset(self::$content_templates[ $page_type ][ $id ]);
    }

    public static function get_layouts()
    {
        $result = array();

        foreach (self::$layouts as $id => $args) {
            $ct = array();

            if (! empty(self::$content_templates[ $id ])) {
                foreach (self::$content_templates[ $id ] as $vid => $v) {
                    $ct[ $vid ] = array('id' => $vid, 'label' => self::translate_label($v['label']), 'preview' => self::resolve_preview_url($v['preview'] ?? '', $v['file']), 'description' => self::translate_description($v['description'] ?? ''), 'uses' => isset($v['uses']) && is_array($v['uses']) ? array_values($v['uses']) : array(), );
                }
            } $result[ $id ] = array('id' => $id, 'label' => self::translate_label($args['label'] ?: ucfirst(str_replace('-', ' ', $id))), 'has_content_templates' => ! empty($ct), 'content_templates' => $ct, );
        }

return $result;
    }

    public static function is_scaffold_preview_mode()
    {
        if (! isset($_GET['puffergo_preview_mode']) || (string) $_GET['puffergo_preview_mode'] !== '1') {
            return false;
        }

return current_user_can('manage_options');
    }

    private static function get_preview_session_id_from_request()
    {
        $raw = isset($_GET[ self::PREVIEW_SESSION_QUERY_KEY ]) ? wp_unslash($_GET[ self::PREVIEW_SESSION_QUERY_KEY ]) : '';
        $id = sanitize_key((string) $raw);

        if ('' === $id || strlen($id) < 16 || strlen($id) > 64) {
            return '';
        }

return $id;
    }

    private static function build_preview_session_transient_key($session_id)
    {
        return self::PREVIEW_SESSION_TRANSIENT_PREFIX . sanitize_key((string) $session_id);
    }

    private static function read_preview_session_payload($session_id)
    {
        $session_id = sanitize_key((string) $session_id);

        if ('' === $session_id) {
            return null;
        } $payload = get_transient(self::build_preview_session_transient_key($session_id));

        if (! is_array($payload)) {
            return null;
        } $owner_id = isset($payload['userId']) ? absint($payload['userId']) : 0;

        if ($owner_id <= 0 || get_current_user_id() !== $owner_id) {
            return null;
        } $expires_at = isset($payload['expiresAt']) ? absint($payload['expiresAt']) : 0;

        if ($expires_at <= time()) {
            delete_transient(self::build_preview_session_transient_key($session_id));

            return null;
        }

if (! isset($payload['previewMap']) || ! is_array($payload['previewMap'])) {
            $payload['previewMap'] = array();
        }

return $payload;
    }

    private static function write_preview_session_payload($session_id, $payload)
    {
        set_transient(self::build_preview_session_transient_key($session_id), $payload, self::PREVIEW_SESSION_TTL);
    }

    private static function maybe_sync_preview_session_from_request()
    {
        if (self::$preview_session_synced || ! self::is_scaffold_preview_mode()) {
            return;
        } self::$preview_session_synced = true;
        $session_id = self::get_preview_session_id_from_request();

        if ('' === $session_id) {
            return;
        } $payload = self::read_preview_session_payload($session_id);

        if (! is_array($payload)) {
            return;
        } $preview_raw = isset($_GET['puffergo_preview']) && is_array($_GET['puffergo_preview']) ? wp_unslash($_GET['puffergo_preview']) : array();

        if (empty($preview_raw)) {
            return;
        } $map = isset($payload['previewMap']) && is_array($payload['previewMap']) ? $payload['previewMap'] : array();
        $changed = false;

        foreach ($preview_raw as $layout_id => $variant_id) {
            $layout_id = sanitize_key((string) $layout_id);
            $variant_id = sanitize_key((string) $variant_id);

            if ('' === $layout_id || '' === $variant_id) {
                continue;
            }

if (! isset($map[ $layout_id ]) || (string) $map[ $layout_id ] !== $variant_id) {
                $map[ $layout_id ] = $variant_id;
                $changed = true;
            }
        }

if (! $changed) {
            return;
        } $payload['previewMap'] = $map;
        $payload['expiresAt'] = time() + self::PREVIEW_SESSION_TTL;
        self::write_preview_session_payload($session_id, $payload);
    }

    private static function get_preview_variant_from_session($layout_id, $variants)
    {
        if (! self::is_scaffold_preview_mode()) {
            return '';
        } $session_id = self::get_preview_session_id_from_request();

        if ('' === $session_id) {
            return '';
        } $payload = self::read_preview_session_payload($session_id);

        if (! is_array($payload) || empty($payload['previewMap']) || ! is_array($payload['previewMap'])) {
            return '';
        } $layout_id = sanitize_key((string) $layout_id);
        $candidate = isset($payload['previewMap'][ $layout_id ]) ? sanitize_key((string) $payload['previewMap'][ $layout_id ]) : '';

        if ('' === $candidate) {
            return '';
        }

return isset($variants[ $candidate ]) ? $candidate : '';
    }

    public static function enqueue_scaffold_preview_navigation_persistence()
    {
        if (! self::is_scaffold_preview_mode()) {
            return;
        } $path = PUFFERGO_PLUGIN_DIR . '/assets/js/puffergo-template-preview-nav.js';

        if (! is_readable($path)) {
            return;
        } wp_enqueue_script('puffergo-template-preview-nav', plugin_dir_url(PUFFERGO_PLUGIN_FILE) . 'assets/js/puffergo-template-preview-nav.js', array(), (string) filemtime($path), true);
        $bridge_path = PUFFERGO_PLUGIN_DIR . '/assets/js/puffergo-preview-bridge.js';

        if (is_readable($bridge_path)) {
            wp_enqueue_script('puffergo-preview-bridge', plugin_dir_url(PUFFERGO_PLUGIN_FILE) . 'assets/js/puffergo-preview-bridge.js', array(), (string) filemtime($bridge_path), true);
        }
    }

    public static function needs_scaffold()
    {
        return 'puffergo' === get_option('puffergo_scaffold_mode', 'puffergo');
    }

    public static function is_valid_header($id)
    {
        return isset(self::$headers[ $id ]);
    }

    public static function is_valid_footer($id)
    {
        return isset(self::$footers[ $id ]);
    }

    public static function register_layout_template_rest_routes()
    {
        register_rest_route('puffergo/v1', '/layout-template-settings', array(array('methods' => 'GET', 'callback' => array(__CLASS__, 'rest_get_layout_settings'), 'permission_callback' => function () { return current_user_can('manage_options'); }, ), array('methods' => 'POST', 'callback' => array(__CLASS__, 'rest_save_template_settings'), 'permission_callback' => function () { return current_user_can('manage_options'); }, ), ));
        register_rest_route('puffergo/v1', '/preview-url', array(array('methods' => 'GET', 'callback' => array(__CLASS__, 'rest_get_preview_url'), 'permission_callback' => function () { return current_user_can('manage_options'); }, ), ));
    }

    public static function rest_get_layout_settings()
    {
        $layouts = self::get_layouts();
        $global_header = self::get_active_header();
        $global_footer = self::get_active_footer();
        $scaffold_mode = self::needs_scaffold() ? 'puffergo' : 'theme';
        $layout_list = array();

        foreach ($layouts as $id => $layout) {
            $layout_list[] = array('id' => $id, 'label' => $layout['label'], 'hasContentTemplates' => $layout['has_content_templates'], 'contentTemplate' => self::get_active_content_template($id), );
        } $content_template_options = array();

        foreach ($layouts as $id => $layout) {
            if (! $layout['has_content_templates']) {
                continue;
            } $variants = self::get_content_templates($id);
            $opts = array();

            foreach ($variants as $vid => $v) {
                $opts[] = array('value' => $vid, 'label' => self::translate_label($v['label']), 'preview' => self::resolve_preview_url($v['preview'] ?? '', $v['file']), 'description' => $v['description'] ?? '', );
            } $content_template_options[ $id ] = $opts;
        }

return new WP_REST_Response(array('scaffoldMode' => $scaffold_mode, 'globalHeader' => $global_header, 'globalFooter' => $global_footer, 'copyrightTemplate' => get_option('puffergo_site_footer_copyright', ''), 'layouts' => $layout_list, 'contentTemplateOptions' => $content_template_options, ), 200);
    }

    public static function rest_save_template_settings($request)
    {
        $params = $request->get_json_params();
        $action = isset($params['action']) ? sanitize_key($params['action']) : '';

        if ('saveglobal' === $action) {
            return self::rest_save_global_settings($params);
        }

if ('saveallcontenttemplates' === $action) {
            return self::rest_save_all_content_templates($params);
        }

return new WP_REST_Response(array('success' => false, 'message' => __('Invalid action.', 'puffergo'), ), 400);
    }

    private static function rest_save_global_settings($params)
    {
        $scaffold_mode = isset($params['scaffoldMode']) ? sanitize_key($params['scaffoldMode']) : 'puffergo';
        $header_template = isset($params['headerTemplate']) ? sanitize_key($params['headerTemplate']) : '';
        $footer_template = isset($params['footerTemplate']) ? sanitize_key($params['footerTemplate']) : '';
        $copyright_template = isset($params['copyrightTemplate']) ? wp_kses_post($params['copyrightTemplate']) : '';

        if (! in_array($scaffold_mode, array('puffergo', 'theme'), true)) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Invalid scaffold mode.', 'puffergo'), ), 400);
        }

if ('puffergo' === $scaffold_mode) {
            if ('' !== $header_template && ! self::is_valid_header($header_template)) {
                return new WP_REST_Response(array('success' => false, 'message' => __('Invalid header template.', 'puffergo'), ), 400);
            }

if ('' !== $footer_template && ! self::is_valid_footer($footer_template)) {
                return new WP_REST_Response(array('success' => false, 'message' => __('Invalid footer template.', 'puffergo'), ), 400);
            }
        } update_option('puffergo_scaffold_mode', $scaffold_mode);

        if ('' !== $header_template) {
            self::persist_active_variant('header', $header_template);
        }

if ('' !== $footer_template) {
            self::persist_active_variant('footer', $footer_template);
        } update_option('puffergo_site_footer_copyright', $copyright_template);

        return new WP_REST_Response(array('success' => true, 'scaffoldMode' => $scaffold_mode, ), 200);
    }

    private static function rest_save_all_content_templates($params)
    {
        $templates = isset($params['templates']) && is_array($params['templates']) ? $params['templates'] : array();
        $layouts = self::get_layouts();

        foreach ($templates as $layout_id => $content_template) {
            $layout_id = sanitize_key($layout_id);
            $content_template = sanitize_key($content_template);

            if (! isset($layouts[ $layout_id ])) {
                continue;
            }

if ('' !== $content_template && ! self::is_valid_content_template($layout_id, $content_template)) {
                return new WP_REST_Response(array('success' => false, 'message' => sprintf(__('Invalid content template for %s.', 'puffergo'), $layout_id), ), 400);
            }

if ('header' === $layout_id || 'footer' === $layout_id) {
                self::persist_active_variant($layout_id, $content_template);
            } else {
                update_option("puffergo_template_{$layout_id}", $content_template);
            }
        }

return new WP_REST_Response(array('success' => true, ), 200);
    }

    public static function rest_get_preview_url($request)
    {
        $layout_id = sanitize_key((string) $request->get_param('layoutId'));
        $variant_id = sanitize_key((string) $request->get_param('variantId'));

        if (empty($layout_id) || empty($variant_id)) {
            return new WP_REST_Response(array('success' => false, 'message' => __('layoutId and variantId are required.', 'puffergo'), ), 400);
        }

if (! self::is_valid_content_template($layout_id, $variant_id)) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Invalid content template.', 'puffergo'), ), 400);
        } $preview_url = self::find_preview_url_for_layout($layout_id);

        if (! $preview_url) {
            return new WP_REST_Response(array('success' => false, 'message' => __('No preview page found for this layout type.', 'puffergo'), ), 404);
        } $session_id = self::get_preview_session_id_from_request();

        if ('' === $session_id) {
            try {
                $session_id = bin2hex(random_bytes(16));
            } catch (Exception $e) {
                $session_id = wp_generate_password(32, false, false);
            }
        } $payload = self::read_preview_session_payload($session_id);

        if (! is_array($payload)) {
            $payload = array('userId' => get_current_user_id(), 'expiresAt' => time() + self::PREVIEW_SESSION_TTL, 'previewMap' => array(), );
        } $map = isset($payload['previewMap']) && is_array($payload['previewMap']) ? $payload['previewMap'] : array();
        $map[ $layout_id ] = $variant_id;
        $payload['previewMap'] = $map;
        $payload['expiresAt'] = time() + self::PREVIEW_SESSION_TTL;
        $payload['userId'] = get_current_user_id();
        self::write_preview_session_payload($session_id, $payload);
        $preview_url = add_query_arg(array('puffergo_preview[' . $layout_id . ']' => $variant_id, 'puffergo_preview_mode' => '1', self::PREVIEW_SESSION_QUERY_KEY => $session_id, ), $preview_url);

        return new WP_REST_Response(array('success' => true, 'previewUrl' => $preview_url, ), 200);
    }

    private static function find_preview_url_for_layout($layout_id)
    {
        $strategy = self::get_preview_strategy_for_layout($layout_id);

        return self::resolve_preview_url_by_strategy($strategy);
    }

    private static function load_template_category_manifest()
    {
        static $cached = null;

        if (null !== $cached) {
            return $cached;
        } $path = PUFFERGO_PLUGIN_DIR . '/config/template-category-manifest.json';

        if (! is_readable($path)) {
            puffergo_log('PufferGo: template-category-manifest.json missing; using preview fallback map.');
            $cached = array();

            return $cached;
        } $raw = file_get_contents($path);

        if (false === $raw) {
            puffergo_log('PufferGo: template-category-manifest.json unreadable; using preview fallback map.');
            $cached = array();

            return $cached;
        } $decoded = json_decode($raw, true);

        if (! is_array($decoded) || empty($decoded['categories']) || ! is_array($decoded['categories'])) {
            puffergo_log('PufferGo: template-category-manifest.json malformed; using preview fallback map.');
            $cached = array();

            return $cached;
        } $cached = $decoded['categories'];

        return $cached;
    }

    private static function get_preview_strategy_for_layout($layout_id)
    {
        $layout_id = sanitize_key((string) $layout_id);
        $categories = self::load_template_category_manifest();

        foreach ($categories as $category) {
            $cat_id = isset($category['id']) ? sanitize_key((string) $category['id']) : '';

            if ('' === $cat_id || $cat_id !== $layout_id) {
                continue;
            }

return isset($category['previewStrategy']) ? sanitize_key((string) $category['previewStrategy']) : '';
        } puffergo_log(sprintf('PufferGo: no previewStrategy found for layout "%s" in manifest.', $layout_id));

        return '';
    }

    private static function persist_active_variant($type, $variant_id)
    {
        update_option("puffergo_template_{$type}", $variant_id, false);
        update_option("puffergo_{$type}_template", $variant_id, false);
    }

    private static function resolve_preview_url_by_strategy($strategy)
    {
        switch ($strategy) {
            case 'fullpage-page': $pages = get_posts(array('post_type' => 'page', 'post_status' => 'publish', 'meta_key' => '_wp_page_template', 'meta_value' => 'puffergo-fullpage.php', 'numberposts' => 1, ));

                return ! empty($pages) ? get_permalink($pages[0]) : null;
            case 'fullpage-or-home': $pages = get_posts(array('post_type' => 'page', 'post_status' => 'publish', 'meta_key' => '_wp_page_template', 'meta_value' => 'puffergo-fullpage.php', 'numberposts' => 1, ));

                if (! empty($pages)) {
                    return get_permalink($pages[0]);
                }

return get_home_url();
            case 'latest-product': $products = get_posts(array('post_type' => 'puffergo_product', 'post_status' => 'publish', 'numberposts' => 1, ));

                return ! empty($products) ? get_permalink($products[0]) : null;
            case 'product-archive': return get_post_type_archive_link('puffergo_product');
            case 'latest-post': $posts = get_posts(array('post_type' => 'post', 'post_status' => 'publish', 'numberposts' => 1, ));

                return ! empty($posts) ? get_permalink($posts[0]) : null;
            case 'archive-or-home': return get_post_type_archive_link('post') ?: get_home_url();
            case 'latest-solution': $solutions = get_posts(array('post_type' => 'puffergo_solution', 'post_status' => 'publish', 'numberposts' => 1, ));

                return ! empty($solutions) ? get_permalink($solutions[0]) : null;
            case 'solution-archive': return get_post_type_archive_link('puffergo_solution');
            case 'latest-case': $cases = get_posts(array('post_type' => 'puffergo_case', 'post_status' => 'publish', 'numberposts' => 1, ));

                return ! empty($cases) ? get_permalink($cases[0]) : null;
            case 'case-archive': return get_post_type_archive_link('puffergo_case');
            case 'latest-testimonial': $testimonials = get_posts(array('post_type' => 'puffergo_testimonial', 'post_status' => 'publish', 'numberposts' => 1, ));

                return ! empty($testimonials) ? get_permalink($testimonials[0]) : null;
            case 'testimonial-archive': return get_post_type_archive_link('puffergo_testimonial');
            case 'woo-shop': if (function_exists('wc_get_page_permalink')) {
                $shop = wc_get_page_permalink('shop');

                if ($shop) {
                    return $shop;
                }
            }

return get_post_type_archive_link('product') ?: null;
            case 'woo-product': $woo_products = get_posts(array('post_type' => 'product', 'post_status' => 'publish', 'numberposts' => 1, ));

                return ! empty($woo_products) ? get_permalink($woo_products[0]) : null;
            default: return null;
        }
    }
} function puffergo_render_component($name, $args = array())
{
    $file = PUFFERGO_PLUGIN_DIR . "/templates/components/{$name}.php";

    if (file_exists($file)) {
        require $file;
    }
}
