<?php

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Reusable shortcode variables dropdown.
 *
 * Usage (post-meta context, CSS class "input-with-dropdown"):
 *   SEO_Fury_Shortcode_Variables::render_dropdown();
 *
 * Usage (admin settings context, CSS class "seo-admin-input-with-dropdown"):
 *   SEO_Fury_Shortcode_Variables::render_admin_dropdown();
 */
class SEO_Fury_Shortcode_Variables
{

    /**
     * Return the full list of available shortcode variables.
     *
     * @return array [ ['var' => '%sep%', 'label' => '...', 'desc' => '...'], ... ]
     */
    public static function get_variables()
    {
        return array(
            // ── Separator ──
            array('var' => '%sep%',        'label' => __('Separator', 'seo-fury'),        'desc' => __('Separator between title parts. Set in: Meta Titles → Separator setting.', 'seo-fury')),
            // ── Search Query ──
            array('var' => '%search_query%', 'label' => __('Search Query', 'seo-fury'),        'desc' => __('Search query (only available on the search results page)', 'seo-fury')),
            // ── Counter ──
            array('var' => '%count(varname)%', 'label' => __('Counter', 'seo-fury'),              'desc' => __('Starts at 1 and increments by 1.', 'seo-fury')),
            // ── File ──
            array('var' => '%filename%',   'label' => __('Filename', 'seo-fury'),                'desc' => __('Attachment filename', 'seo-fury')),
            // ── Site ──
            array('var' => '%sitename%',   'label' => __('Site Name', 'seo-fury'),           'desc' => __('Site title from Settings → General → Site Title.', 'seo-fury')),
            array('var' => '%sitedesc%',   'label' => __('Site Description', 'seo-fury'),           'desc' => __('Site tagline from Settings → General → Tagline (short site description).', 'seo-fury')),
            // ── Current Date/Time ──
            array('var' => '%currentdate%',     'label' => __('Current Date', 'seo-fury'),        'desc' => __('Current server date', 'seo-fury')),
            array('var' => '%currentday%',      'label' => __('Current Day', 'seo-fury'),        'desc' => __('Current server day', 'seo-fury')),
            array('var' => '%currentmonth%',    'label' => __('Current Month', 'seo-fury'),       'desc' => __('Current server month', 'seo-fury')),
            array('var' => '%currentyear%',     'label' => __('Current Year', 'seo-fury'),         'desc' => __('Current server year', 'seo-fury')),
            array('var' => '%currenttime%',     'label' => __('Current Time', 'seo-fury'),       'desc' => __('Current server time', 'seo-fury')),
            array('var' => '%currenttime(F jS, Y)%', 'label' => __('Current Time (advanced)', 'seo-fury'), 'desc' => __('Current server time with a customizable formatting pattern.', 'seo-fury')),
            // ── Organization ──
            array('var' => '%org_name%',   'label' => __('Organization Name', 'seo-fury'),     'desc' => __('Organization name added in Local SEO settings.', 'seo-fury')),
            array('var' => '%org_logo%',   'label' => __('Organization Logo', 'seo-fury'),      'desc' => __('Organization logo added in Local SEO settings.', 'seo-fury')),
            array('var' => '%org_url%',    'label' => __('Organization URL', 'seo-fury'),          'desc' => __('Organization URL added in Local SEO settings.', 'seo-fury')),
            // ── Post ──
            array('var' => '%title%',           'label' => __('Post Title', 'seo-fury'),    'desc' => __('Title of the current post/page (the title field in the editor).', 'seo-fury')),
            array('var' => '%parent_title%',    'label' => __('Parent Page Title', 'seo-fury'), 'desc' => __('Title of the parent page of the current post/page', 'seo-fury')),
            array('var' => '%excerpt%',         'label' => __('Post Excerpt', 'seo-fury'),      'desc' => __('Excerpt of the current post (from the Excerpt field, or auto-generated from content if empty).', 'seo-fury')),
            array('var' => '%excerpt_only%',    'label' => __('Post Excerpt (only)', 'seo-fury'), 'desc' => __('Excerpt of the current post (without auto-generation)', 'seo-fury')),
            array('var' => '%seo_title%',       'label' => __('SEO Title', 'seo-fury'),       'desc' => __('Custom or generated SEO title of the current post/page', 'seo-fury')),
            array('var' => '%seo_description%', 'label' => __('SEO Description', 'seo-fury'),        'desc' => __('Custom or generated SEO description of the current post/page', 'seo-fury')),
            array('var' => '%url%',             'label' => __('Post URL', 'seo-fury'),          'desc' => __('URL of the current post/page', 'seo-fury')),
            array('var' => '%post_thumbnail%',  'label' => __('Post Thumbnail', 'seo-fury'),    'desc' => __('Thumbnail of the current post', 'seo-fury')),
            // ── Dates ──
            array('var' => '%date%',            'label' => __('Publish Date', 'seo-fury'),     'desc' => __('Publish date of the current post/page OR the specified date in a date archive', 'seo-fury')),
            array('var' => '%modified%',        'label' => __('Modified Date', 'seo-fury'),      'desc' => __('Last modified date of the current post/page', 'seo-fury')),
            array('var' => '%date(F jS, Y)%',   'label' => __('Publish Date (advanced)', 'seo-fury'), 'desc' => __('Publish date with a customizable formatting pattern.', 'seo-fury')),
            array('var' => '%modified(F jS, Y)%', 'label' => __('Modified Date (advanced)', 'seo-fury'), 'desc' => __('Modified date with a customizable formatting pattern.', 'seo-fury')),
            // ── Categories / Tags ──
            array('var' => '%category%',        'label' => __('Post Category', 'seo-fury'),      'desc' => __('First category (alphabetically) associated with the current post, OR the current category in category archives', 'seo-fury')),
            array('var' => '%categories%',      'label' => __('Post Categories', 'seo-fury'),      'desc' => __('Comma-separated list of categories associated with the current post', 'seo-fury')),
            array('var' => '%categories(limit=3&separator= | &exclude=12,23)%', 'label' => __('Categories (advanced)', 'seo-fury'), 'desc' => __('Customizable list of categories associated with the current post.', 'seo-fury')),
            array('var' => '%primary_taxonomy_terms%', 'label' => __('Primary Taxonomy Terms', 'seo-fury'), 'desc' => __('List of terms from the primary taxonomy associated with the current post.', 'seo-fury')),
            array('var' => '%tag%',             'label' => __('Post Tag', 'seo-fury'),          'desc' => __('First tag (alphabetically) associated with the current post, OR the current tag from archives', 'seo-fury')),
            array('var' => '%tags%',            'label' => __('Post Tags', 'seo-fury'),         'desc' => __('Comma-separated list of tags associated with the current post', 'seo-fury')),
            array('var' => '%tags(limit=3&separator= | &exclude=12,23)%', 'label' => __('Tags (advanced)', 'seo-fury'), 'desc' => __('Customizable list of tags associated with the current post.', 'seo-fury')),
            // ── Terms ──
            array('var' => '%term%',                          'label' => __('Current Term', 'seo-fury'),                'desc' => __('Current term name', 'seo-fury')),
            array('var' => '%term_description%',              'label' => __('Term Description', 'seo-fury'),              'desc' => __('Current term description', 'seo-fury')),
            array('var' => '%customterm(taxonomy-name)%',     'label' => __('Custom Term (advanced)', 'seo-fury'), 'desc' => __('Custom term value.', 'seo-fury')),
            array('var' => '%customterm_desc(taxonomy-name)%', 'label' => __('Custom Term Description', 'seo-fury'), 'desc' => __('Custom term description.', 'seo-fury')),
            // ── Author ──
            array('var' => '%userid%',          'label' => __('Author ID', 'seo-fury'),           'desc' => __('Author ID of the current post, page, or author archive.', 'seo-fury')),
            array('var' => '%name%',            'label' => __('Post Author', 'seo-fury'),        'desc' => __('Display name of the author of the current post, page, or author archive.', 'seo-fury')),
            array('var' => '%post_author%',     'label' => __('Post Author', 'seo-fury'),        'desc' => __('Display name of the author of the current post, page, or author archive.', 'seo-fury')),
            array('var' => '%user_description%', 'label' => __('Author Description', 'seo-fury'),    'desc' => __('Biography of the author of the current post, page, or author archive.', 'seo-fury')),
            // ── ID / Keywords ──
            array('var' => '%id%',              'label' => __('Post ID', 'seo-fury'),           'desc' => __('ID of the current post/page', 'seo-fury')),
            array('var' => '%focuskw%',         'label' => __('Focus Keyword', 'seo-fury'),   'desc' => __('Focus keyword of the current post', 'seo-fury')),
            array('var' => '%keywords%',        'label' => __('Focus Keywords', 'seo-fury'),  'desc' => __('Focus keywords of the current post', 'seo-fury')),
            // ── Custom Field ──
            array('var' => '%customfield(field-name)%', 'label' => __('Custom Field (advanced)', 'seo-fury'), 'desc' => __('Custom field value.', 'seo-fury')),
            // ── Pagination ──
            array('var' => '%page%',            'label' => __('Page', 'seo-fury'),            'desc' => __('Page number with context (e.g., page 2 of 4). Only displayed on page 2 and above.', 'seo-fury')),
            array('var' => '%pagenumber%',      'label' => __('Page Number', 'seo-fury'),      'desc' => __('Current page number', 'seo-fury')),
            array('var' => '%pagetotal%',       'label' => __('Total Pages', 'seo-fury'),        'desc' => __('Maximum number of pages', 'seo-fury')),
            // ── Post Type ──
            array('var' => '%pt_single%',       'label' => __('Post Type Name (singular)', 'seo-fury'), 'desc' => __('Name of the current post type (singular)', 'seo-fury')),
            array('var' => '%pt_plural%',       'label' => __('Post Type Name (plural)', 'seo-fury'), 'desc' => __('Name of the current post type (plural)', 'seo-fury')),
            // ── Random Word ──
            array('var' => '%randomword(word1|word2|word3)%',      'label' => __('Random Word', 'seo-fury'),             'desc' => __('Persistent random word chosen from a list', 'seo-fury')),
            array('var' => '%randomword_np(word1|word2|word3)%',   'label' => __('Random Word (non-persistent)', 'seo-fury'),   'desc' => __('Non-persistent random word chosen from a list. A new random word will be selected on each page load.', 'seo-fury')),
            // ── WooCommerce ──
            array('var' => '%wc_price%',        'label' => __('Product Price', 'seo-fury'),         'desc' => __('Price of the current product', 'seo-fury')),
            array('var' => '%wc_sku%',          'label' => __('Product SKU', 'seo-fury'),      'desc' => __('SKU of the current product', 'seo-fury')),
            array('var' => '%wc_shortdesc%',    'label' => __('Product Short Description', 'seo-fury'), 'desc' => __('Short description of the current product', 'seo-fury')),
            array('var' => '%wc_brand%',        'label' => __('Product Brand', 'seo-fury'),        'desc' => __('Brand (manufacturer) of the current product', 'seo-fury')),
        );
    }

    /**
     * Resolve all shortcode variables in a template string for a given post.
     *
     * @param string   $template  String containing %variable% placeholders.
     * @param \WP_Post $post      The post object to resolve against.
     * @return string
     */
    public static function resolve($template, $post)
    {
        if (empty($template) || strpos($template, '%') === false) {
            return $template;
        }

        // ── Author ──
        $author_name = '';
        $author_desc = '';
        $author_id = '';
        if (!empty($post->post_author)) {
            $user = get_userdata($post->post_author);
            if ($user) {
                $author_name = $user->display_name;
                $author_desc = $user->description;
                $author_id = $user->ID;
            }
        }

        // ── Excerpt ──
        $content_raw = $post->post_content ?? '';
        $content_stripped = wp_strip_all_tags(strip_shortcodes($content_raw));
        $auto_excerpt = wp_trim_words($content_stripped, 20, '...');
        $manual_excerpt = !empty($post->post_excerpt) ? $post->post_excerpt : '';

        // ── Categories ──
        $categories = get_the_category($post->ID);
        $first_category = !empty($categories) ? $categories[0]->name : '';
        $all_categories = !empty($categories) ? implode(', ', wp_list_pluck($categories, 'name')) : '';

        // ── Tags ──
        $tags = get_the_tags($post->ID);
        $first_tag = (!empty($tags) && !is_wp_error($tags)) ? $tags[0]->name : '';
        $all_tags = (!empty($tags) && !is_wp_error($tags)) ? implode(', ', wp_list_pluck($tags, 'name')) : '';

        // ── Dates ──
        $date_format = get_option('date_format');
        $post_date = '';
        $post_modified = '';
        if (!empty($post->post_date) && $post->post_date !== '0000-00-00 00:00:00') {
            $post_date = date_i18n($date_format, strtotime($post->post_date));
        }
        if (!empty($post->post_modified) && $post->post_modified !== '0000-00-00 00:00:00') {
            $post_modified = date_i18n($date_format, strtotime($post->post_modified));
        }

        // ── Parent title ──
        $parent_title = '';
        if (!empty($post->post_parent)) {
            $parent_title = get_the_title($post->post_parent);
        }

        // ── SEO meta ──
        $seo_title = get_post_meta($post->ID, '_seo_fury_title', true);
        $seo_description = get_post_meta($post->ID, '_seo_fury_description', true);

        // ── Focus keyword ──
        $focuskw = get_post_meta($post->ID, '_seo_fury_focus_keyword', true);

        // ── Post thumbnail ──
        $thumbnail = has_post_thumbnail($post->ID) ? get_the_post_thumbnail_url($post->ID, 'full') : '';

        // ── Filename (attachments) ──
        $filename = '';
        if ($post->post_type === 'attachment') {
            $filename = pathinfo(get_attached_file($post->ID), PATHINFO_FILENAME);
            $filename = str_replace(array('-', '_'), ' ', $filename);
            $filename = ucfirst($filename);
        }

        // ── Post type labels ──
        $pt_obj = get_post_type_object($post->post_type);
        $pt_single = $pt_obj ? $pt_obj->labels->singular_name : '';
        $pt_plural = $pt_obj ? $pt_obj->labels->name : '';

        // ── Organization (Local SEO) ──
        // Keys must match what class-local-seo.php actually saves
        // (seo_fury_local_*), not the never-registered *_business_* variants.
        $org_name = get_option('seo_fury_local_name', '');
        $org_logo = get_option('seo_fury_local_logo', '');
        $org_url = get_option('seo_fury_local_url', home_url('/'));

        // ── Separator ──
        $separator = get_option('seo_fury_title_separator', '-');

        // ── WooCommerce ──
        $wc_price = '';
        $wc_sku = '';
        $wc_shortdesc = '';
        $wc_brand = '';
        if (class_exists('WC_Product') && ($post->post_type === 'product' || $post->post_type === 'product_variation')) {
            $product = wc_get_product($post->ID);
            if ($product) {
                $wc_price = $product->get_price();
                $wc_sku = $product->get_sku();
                $wc_shortdesc = $product->get_short_description();
                // Brand from taxonomy or attribute
                $brand_terms = wp_get_post_terms($post->ID, 'product_brand', array('fields' => 'names'));
                if (!is_wp_error($brand_terms) && !empty($brand_terms)) {
                    $wc_brand = $brand_terms[0];
                } else {
                    $wc_brand = $product->get_attribute('brand');
                }
            }
        }

        // ── Simple replacements map ──
        $replacements = array(
            '%sep%'              => $separator,
            '%search_query%'     => is_search() ? get_search_query() : '',
            '%filename%'         => $filename,
            '%sitename%'         => get_bloginfo('name'),
            '%sitedesc%'         => get_bloginfo('description'),
            '%currentdate%'      => date_i18n($date_format),
            '%currentday%'       => date_i18n('j'),
            '%currentmonth%'     => date_i18n('F'),
            '%currentyear%'      => wp_date('Y'),
            '%currenttime%'      => date_i18n('H:i'),
            '%org_name%'         => $org_name,
            '%org_logo%'         => $org_logo,
            '%org_url%'          => $org_url,
            '%title%'            => get_the_title($post),
            '%parent_title%'     => $parent_title,
            '%excerpt%'          => $manual_excerpt ?: $auto_excerpt,
            '%excerpt_only%'     => $manual_excerpt,
            '%seo_title%'        => $seo_title ?: get_the_title($post),
            '%seo_description%'  => $seo_description ?: ($manual_excerpt ?: $auto_excerpt),
            '%url%'              => get_permalink($post->ID) ?: '',
            '%post_thumbnail%'   => $thumbnail,
            '%date%'             => $post_date,
            '%modified%'         => $post_modified,
            '%category%'         => $first_category,
            '%categories%'       => $all_categories,
            '%tag%'              => $first_tag,
            '%tags%'             => $all_tags,
            '%userid%'           => $author_id,
            '%name%'             => $author_name,
            '%post_author%'      => $author_name,
            '%user_description%' => $author_desc,
            '%id%'               => $post->ID,
            '%focuskw%'          => $focuskw ?: '',
            '%keywords%'         => $focuskw ?: '',
            '%pagenumber%'       => '',
            '%pagetotal%'        => '',
            '%page%'             => '',
            '%pt_single%'        => $pt_single,
            '%pt_plural%'        => $pt_plural,
            '%wc_price%'         => $wc_price,
            '%wc_sku%'           => $wc_sku,
            '%wc_shortdesc%'     => $wc_shortdesc,
            '%wc_brand%'         => $wc_brand,
        );

        // Apply simple replacements first
        $result = strtr($template, $replacements);

        // ── Dynamic pattern: %currenttime(FORMAT)% ──
        $result = preg_replace_callback('/%currenttime\(([^)]+)\)%/', function ($m) {
            return date_i18n($m[1]);
        }, $result);

        // ── Dynamic pattern: %date(FORMAT)% ──
        $result = preg_replace_callback('/%date\(([^)]+)\)%/', function ($m) use ($post) {
            if (!empty($post->post_date) && $post->post_date !== '0000-00-00 00:00:00') {
                return date_i18n($m[1], strtotime($post->post_date));
            }
            return '';
        }, $result);

        // ── Dynamic pattern: %modified(FORMAT)% ──
        $result = preg_replace_callback('/%modified\(([^)]+)\)%/', function ($m) use ($post) {
            if (!empty($post->post_modified) && $post->post_modified !== '0000-00-00 00:00:00') {
                return date_i18n($m[1], strtotime($post->post_modified));
            }
            return '';
        }, $result);

        // ── Dynamic pattern: %customfield(field-name)% ──
        $result = preg_replace_callback('/%customfield\(([^)]+)\)%/', function ($m) use ($post) {
            return get_post_meta($post->ID, $m[1], true) ?: '';
        }, $result);

        // ── Dynamic pattern: %customterm(taxonomy-name)% ──
        $result = preg_replace_callback('/%customterm\(([^)]+)\)%/', function ($m) use ($post) {
            $terms = wp_get_post_terms($post->ID, $m[1], array('fields' => 'names'));
            if (!is_wp_error($terms) && !empty($terms)) {
                return $terms[0];
            }
            return '';
        }, $result);

        // ── Dynamic pattern: %customterm_desc(taxonomy-name)% ──
        $result = preg_replace_callback('/%customterm_desc\(([^)]+)\)%/', function ($m) use ($post) {
            $terms = wp_get_post_terms($post->ID, $m[1]);
            if (!is_wp_error($terms) && !empty($terms)) {
                return wp_strip_all_tags(term_description($terms[0]->term_id));
            }
            return '';
        }, $result);

        // ── Dynamic pattern: %categories(limit=N&separator=S&exclude=IDs)% ──
        $result = preg_replace_callback('/%categories\(([^)]+)\)%/', function ($m) use ($post) {
            parse_str(html_entity_decode($m[1]), $params);
            $limit = isset($params['limit']) ? intval($params['limit']) : 0;
            $sep = isset($params['separator']) ? $params['separator'] : ', ';
            $exclude = isset($params['exclude']) ? array_map('intval', explode(',', $params['exclude'])) : array();
            $cats = get_the_category($post->ID);
            $names = array();
            foreach ($cats as $cat) {
                if (in_array($cat->term_id, $exclude)) continue;
                $names[] = $cat->name;
                if ($limit > 0 && count($names) >= $limit) break;
            }
            return implode($sep, $names);
        }, $result);

        // ── Dynamic pattern: %tags(limit=N&separator=S&exclude=IDs)% ──
        $result = preg_replace_callback('/%tags\(([^)]+)\)%/', function ($m) use ($post) {
            parse_str(html_entity_decode($m[1]), $params);
            $limit = isset($params['limit']) ? intval($params['limit']) : 0;
            $sep = isset($params['separator']) ? $params['separator'] : ', ';
            $exclude = isset($params['exclude']) ? array_map('intval', explode(',', $params['exclude'])) : array();
            $tags = get_the_tags($post->ID);
            if (empty($tags) || is_wp_error($tags)) return '';
            $names = array();
            foreach ($tags as $tag) {
                if (in_array($tag->term_id, $exclude)) continue;
                $names[] = $tag->name;
                if ($limit > 0 && count($names) >= $limit) break;
            }
            return implode($sep, $names);
        }, $result);

        // ── Dynamic pattern: %randomword(w1|w2|w3)% — deterministic per post ──
        $result = preg_replace_callback('/%randomword\(([^)]+)\)%/', function ($m) use ($post) {
            $words = array_map('trim', explode('|', $m[1]));
            if (empty($words)) return '';
            // abs() BEFORE the modulo: crc32() can be negative on 32-bit PHP,
            // and "abs(neg % n)" skews the distribution vs an unsigned modulo.
            $index = abs(crc32($post->ID . $m[1])) % count($words);
            return $words[$index];
        }, $result);

        // ── Dynamic pattern: %randomword_np(w1|w2|w3)% — non-persistent ──
        $result = preg_replace_callback('/%randomword_np\(([^)]+)\)%/', function ($m) {
            $words = array_map('trim', explode('|', $m[1]));
            if (empty($words)) return '';
            return $words[array_rand($words)];
        }, $result);

        // ── Dynamic pattern: %count(varname)% ──
        static $counters = array();
        $result = preg_replace_callback('/%count\(([^)]+)\)%/', function ($m) use (&$counters) {
            $key = $m[1];
            if (!isset($counters[$key])) {
                $counters[$key] = 0;
            }
            $counters[$key]++;
            return $counters[$key];
        }, $result);

        // ── %term% / %term_description% / %primary_taxonomy_terms% ──
        // These are context-dependent (taxonomy archives); resolve with best-effort for singular posts
        if (strpos($result, '%term%') !== false || strpos($result, '%term_description%') !== false) {
            $queried = get_queried_object();
            $term_name = '';
            $term_desc = '';
            if ($queried instanceof \WP_Term) {
                $term_name = $queried->name;
                $term_desc = wp_strip_all_tags(term_description($queried->term_id));
            }
            $result = str_replace('%term%', $term_name, $result);
            $result = str_replace('%term_description%', $term_desc, $result);
        }

        if (strpos($result, '%primary_taxonomy_terms%') !== false) {
            $primary_tax = get_post_meta($post->ID, '_primary_taxonomy', true);
            $terms_str = '';
            if ($primary_tax) {
                $terms = wp_get_post_terms($post->ID, $primary_tax, array('fields' => 'names'));
                if (!is_wp_error($terms)) {
                    $terms_str = implode(', ', $terms);
                }
            }
            $result = str_replace('%primary_taxonomy_terms%', $terms_str, $result);
        }

        return $result;
    }

    /**
     * Resolve all shortcode variables inside a flat data array (recursive for nested arrays).
     *
     * @param array    $data  Array with string values that may contain %variable% placeholders.
     * @param \WP_Post $post  The post object.
     * @return array
     */
    public static function resolve_data(array $data, $post)
    {
        $resolved = array();
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $resolved[$key] = self::resolve_data($value, $post);
            } elseif (is_string($value)) {
                $resolved[$key] = self::resolve($value, $post);
            } else {
                $resolved[$key] = $value;
            }
        }
        return $resolved;
    }

    /**
     * Render shortcode dropdown for the post-meta context.
     * Must be placed inside a container with class "input-with-dropdown".
     *
     * @param string|null $target_id  Optional: ID of the target input (data-target attribute).
     */
    public static function render_dropdown($target_id = null)
    {
        $variables = self::get_variables();
        $data_target = $target_id ? ' data-target="' . esc_attr($target_id) . '"' : '';
        ?>
        <button type="button" class="shortcode-dropdown-btn"<?php echo wp_kses_post( $data_target ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
            <span class="dashicons dashicons-arrow-down-alt2"></span>
        </button>
        <div class="shortcode-dropdown-menu">
            <div class="sf-shortcode-search-wrap">
                <input type="text" class="sf-shortcode-search" placeholder="<?php esc_attr_e('Search...', 'seo-fury'); ?>" />
            </div>
            <?php foreach ($variables as $item): ?>
                <div class="shortcode-item" data-var="<?php echo esc_attr($item['var']); ?>">
                    <div class="shortcode-item-info">
                        <strong><?php echo esc_html($item['label']); ?></strong>
                        <span><?php echo esc_html($item['desc']); ?></span>
                    </div>
                    <code class="shortcode-item-var"><?php echo esc_html($item['var']); ?></code>
                </div>
            <?php endforeach; ?>
        </div>
        <?php
    }

    /**
     * Render shortcode dropdown for the admin settings context.
     * Must be placed inside a container with class "seo-admin-input-with-dropdown".
     *
     * @param string $target_id  The ID of the target input (data-target attribute).
     */
    public static function render_admin_dropdown($target_id)
    {
        $variables = self::get_variables();
        ?>
        <button type="button" class="seo-admin-shortcode-btn" data-target="<?php echo esc_attr($target_id); ?>">
            <span class="dashicons dashicons-arrow-down-alt2"></span>
        </button>
        <div class="seo-admin-shortcode-menu">
            <div class="sf-shortcode-search-wrap">
                <input type="text" class="sf-shortcode-search" placeholder="<?php esc_attr_e('Search...', 'seo-fury'); ?>" />
            </div>
            <?php foreach ($variables as $item): ?>
                <div class="seo-admin-shortcode-item" data-var="<?php echo esc_attr($item['var']); ?>">
                    <strong><?php echo esc_html($item['var']); ?></strong>
                    <span><?php echo esc_html($item['label']); ?></span>
                </div>
            <?php endforeach; ?>
        </div>
        <?php
    }
}
