<?php

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

class SEO_Fury_Meta_Titles
{

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

    private function init_hooks()
    {
        if ($this->is_rest_request()) {
            return;
        }

        add_filter('wp_robots', array($this, 'disable_wp_robots'), 999);

        add_action('wp_head', array($this, 'output_meta_tags'), 0);

        add_filter('wp_title', array($this, 'modify_title'), 10, 3);
        add_filter('document_title_parts', array($this, 'modify_document_title_parts'));

        add_action('wp_ajax_seo_fury_delete_post_type_schema',    array($this, 'ajax_delete_post_type_schema'));
        add_action('wp_ajax_seo_fury_apply_template_to_post_type', array($this, 'ajax_apply_template_to_post_type'));
    }

    private function is_rest_request()
    {
        if (defined('REST_REQUEST') && REST_REQUEST) {
            return true;
        }

        if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false) {
            return true;
        }

        return false;
    }

    public function disable_wp_robots($robots)
    {
        if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false) {
            return $robots;
        }

        if (is_admin()) {
            return $robots;
        }

        if (wp_doing_ajax()) {
            return $robots;
        }

        return array();
    }

    /**
     * AJAX: Delete all custom Schema from posts of a given post type.
     */
    public function ajax_delete_post_type_schema()
    {
        check_ajax_referer('seo_fury_meta_titles_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Permission denied', 'seo-fury')));
        }

        $post_type = sanitize_key(wp_unslash($_POST['post_type'] ?? ''));
        if (empty($post_type)) {
            wp_send_json_error(array('message' => __('Invalid post type', 'seo-fury')));
        }

        $posts = get_posts(array(
            'post_type'      => $post_type,
            'post_status'    => 'any',
            'numberposts'    => -1,
            'fields'         => 'ids',
            'no_found_rows'  => true,
        ));

        $count = 0;
        foreach ($posts as $post_id) {
            delete_post_meta($post_id, '_seo_fury_schema_items');
            delete_post_meta($post_id, '_seo_fury_schema_active');
            delete_post_meta($post_id, '_seo_fury_schema_mode');
            delete_post_meta($post_id, '_seo_fury_schema_type');
            delete_post_meta($post_id, '_seo_fury_schema_custom');
            delete_post_meta($post_id, '_seo_fury_schema_data');
            $count++;
        }

        wp_send_json_success(array(
            'count'   => $count,
            'message' => sprintf(
                /* translators: %d is the number of posts updated. */
                __('Schema deleted from %d posts.', 'seo-fury'),
                $count
            ),
        ));
    }

    /**
     * AJAX: Apply a saved Schema template to all posts of a given post type.
     */
    public function ajax_apply_template_to_post_type()
    {
        check_ajax_referer('seo_fury_meta_titles_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Permission denied', 'seo-fury')));
        }

        $post_type   = sanitize_key(wp_unslash($_POST['post_type'] ?? ''));
        $template_id = intval($_POST['template_id'] ?? 0);

        if (empty($post_type) || !$template_id) {
            wp_send_json_error(array('message' => __('Invalid parameters', 'seo-fury')));
        }

        $template_post = get_post($template_id);
        if (!$template_post || $template_post->post_type !== 'seo_fury_schema_tpl') {
            wp_send_json_error(array('message' => __('Template not found', 'seo-fury')));
        }

        $tpl_mode    = get_post_meta($template_id, '_seo_fury_tpl_mode', true) ?: 'generator';
        $tpl_type    = get_post_meta($template_id, '_seo_fury_tpl_type', true) ?: 'none';
        $tpl_data    = get_post_meta($template_id, '_seo_fury_tpl_data', true) ?: '{}';
        $tpl_custom  = get_post_meta($template_id, '_seo_fury_tpl_custom', true) ?: '';
        $tpl_builder = get_post_meta($template_id, '_seo_fury_tpl_builder_data', true) ?: '';

        $schema_item = array(
            'id'     => uniqid('schema_', true),
            'type'   => $tpl_type,
            'mode'   => $tpl_mode,
            'label'  => $template_post->post_title,
            'data'   => json_decode($tpl_data, true) ?: array(),
            'custom' => $tpl_custom,
        );
        if (!empty($tpl_builder)) {
            $bd = json_decode($tpl_builder, true);
            if (is_array($bd)) {
                $schema_item['builder_data'] = $bd;
            }
        }

        $schema_items = array($schema_item);

        $posts = get_posts(array(
            'post_type'     => $post_type,
            'post_status'   => 'any',
            'numberposts'   => -1,
            'fields'        => 'ids',
            'no_found_rows' => true,
        ));

        $count = 0;
        foreach ($posts as $post_id) {
            update_post_meta($post_id, '_seo_fury_schema_items', $schema_items);
            update_post_meta($post_id, '_seo_fury_schema_mode', $tpl_mode);
            update_post_meta($post_id, '_seo_fury_schema_type', $tpl_type);
            $count++;
        }

        wp_send_json_success(array(
            'count'   => $count,
            'message' => sprintf(
                /* translators: %d is the number of posts updated. */
                __('Schema template applied to %d posts.', 'seo-fury'),
                $count
            ),
        ));
    }

    public function register_settings()
    {
        $sanitize_checkbox = array('sanitize_callback' => 'absint');
        $sanitize_text     = array('sanitize_callback' => 'sanitize_text_field');
        $sanitize_int      = array('sanitize_callback' => 'intval');

        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_index', $sanitize_checkbox);
        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_noindex', $sanitize_checkbox);
        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_nofollow', $sanitize_checkbox);
        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_noarchive', $sanitize_checkbox);
        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_noimageindex', $sanitize_checkbox);
        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_nosnippet', $sanitize_checkbox);

        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_max_snippet', $sanitize_int);
        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_max_video_preview', $sanitize_int);
        register_setting('seo_fury_meta_group', 'seo_fury_robots_meta_max_image_preview', $sanitize_text);

        register_setting('seo_fury_meta_group', 'seo_fury_noindex_empty_archives', $sanitize_checkbox);

        register_setting('seo_fury_meta_group', 'seo_fury_title_separator', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_title_capitalize', $sanitize_checkbox);

        register_setting('seo_fury_meta_group', 'seo_fury_twitter_card_type', $sanitize_text);

        register_setting('seo_fury_meta_group', 'seo_fury_title_template_home', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_description_template_home', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_title_template_author', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_description_template_author', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_title_template_search', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_description_template_search', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_title_template_404', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_description_template_404', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_title_template_date', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_description_template_date', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_title_template_blog', $sanitize_text);
        register_setting('seo_fury_meta_group', 'seo_fury_description_template_blog', $sanitize_text);

        $post_types = get_post_types(array('public' => true), 'objects');
        foreach ($post_types as $post_type) {
            register_setting('seo_fury_meta_group', 'seo_fury_title_template_' . $post_type->name, $sanitize_text);
            register_setting('seo_fury_meta_group', 'seo_fury_description_template_' . $post_type->name, $sanitize_text);

            // Default Schema type per post type
            register_setting('seo_fury_meta_group', 'seo_fury_default_schema_' . $post_type->name, $sanitize_text);

            // Robots meta per post type
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_enabled_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_index_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_noindex_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_nofollow_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_noarchive_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_noimageindex_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_nosnippet_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_advanced_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_max_snippet_' . $post_type->name, $sanitize_int);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_max_video_' . $post_type->name, $sanitize_int);
            register_setting('seo_fury_meta_group', 'seo_fury_pt_robots_max_image_' . $post_type->name, $sanitize_text);

            register_setting('seo_fury_meta_group', 'seo_fury_schema_headline_' . $post_type->name, $sanitize_text);
            register_setting('seo_fury_meta_group', 'seo_fury_schema_description_' . $post_type->name, $sanitize_text);
            register_setting('seo_fury_meta_group', 'seo_fury_schema_article_type_' . $post_type->name, $sanitize_text);
            register_setting('seo_fury_meta_group', 'seo_fury_schema_author_source_' . $post_type->name, $sanitize_text);
            register_setting('seo_fury_meta_group', 'seo_fury_schema_author_custom_' . $post_type->name, $sanitize_text);

            // Schema graph inclusion per post type (PRO)
            register_setting('seo_fury_meta_group', 'seo_fury_schema_graph_organization_' . $post_type->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_schema_graph_website_' . $post_type->name, $sanitize_checkbox);
        }

        $taxonomies = get_taxonomies(array('public' => true), 'objects');
        foreach ($taxonomies as $taxonomy) {
            register_setting('seo_fury_meta_group', 'seo_fury_title_template_tax_' . $taxonomy->name, $sanitize_text);
            register_setting('seo_fury_meta_group', 'seo_fury_description_template_tax_' . $taxonomy->name, $sanitize_text);

            // Robots meta per taxonomy
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_enabled_' . $taxonomy->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_noindex_' . $taxonomy->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_nofollow_' . $taxonomy->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_noarchive_' . $taxonomy->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_noimageindex_' . $taxonomy->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_nosnippet_' . $taxonomy->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_advanced_' . $taxonomy->name, $sanitize_checkbox);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_max_snippet_' . $taxonomy->name, $sanitize_int);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_max_video_' . $taxonomy->name, $sanitize_int);
            register_setting('seo_fury_meta_group', 'seo_fury_tax_robots_max_image_' . $taxonomy->name, $sanitize_text);
        }

        add_settings_section(
            'seo_fury_robots_meta_section',
            __('Robots Meta', 'seo-fury'),
            array($this, 'robots_meta_section_callback'),
            'seo_fury_meta_group'
        );

        add_settings_field(
            'seo_fury_robots_meta_tags',
            __('Robots Meta Tags', 'seo-fury'),
            array($this, 'robots_meta_tags_callback'),
            'seo_fury_meta_group',
            'seo_fury_robots_meta_section'
        );

        add_settings_section(
            'seo_fury_advanced_robots_section',
            __('Advanced Robots Meta', 'seo-fury'),
            array($this, 'advanced_robots_section_callback'),
            'seo_fury_meta_group'
        );

        add_settings_field(
            'seo_fury_robots_snippet',
            __('Snippet', 'seo-fury'),
            array($this, 'robots_snippet_callback'),
            'seo_fury_meta_group',
            'seo_fury_advanced_robots_section'
        );

        add_settings_field(
            'seo_fury_robots_video',
            __('Video Preview', 'seo-fury'),
            array($this, 'robots_video_callback'),
            'seo_fury_meta_group',
            'seo_fury_advanced_robots_section'
        );

        add_settings_field(
            'seo_fury_robots_image',
            __('Image Preview Size', 'seo-fury'),
            array($this, 'robots_image_callback'),
            'seo_fury_meta_group',
            'seo_fury_advanced_robots_section'
        );

        add_settings_section(
            'seo_fury_noindex_archives_section',
            __('Noindex Empty Archives', 'seo-fury'),
            array($this, 'noindex_archives_section_callback'),
            'seo_fury_meta_group'
        );

        add_settings_field(
            'seo_fury_noindex_empty',
            __('Empty Archives', 'seo-fury'),
            array($this, 'noindex_empty_callback'),
            'seo_fury_meta_group',
            'seo_fury_noindex_archives_section'
        );

        add_settings_section(
            'seo_fury_title_settings_section',
            __('Title Settings', 'seo-fury'),
            array($this, 'title_settings_section_callback'),
            'seo_fury_meta_group'
        );

        add_settings_field(
            'seo_fury_title_sep',
            __('Title Separator', 'seo-fury'),
            array($this, 'title_separator_callback'),
            'seo_fury_meta_group',
            'seo_fury_title_settings_section'
        );

        add_settings_field(
            'seo_fury_title_cap',
            __('Capitalize Titles', 'seo-fury'),
            array($this, 'title_capitalize_callback'),
            'seo_fury_meta_group',
            'seo_fury_title_settings_section'
        );

        add_settings_section(
            'seo_fury_twitter_card_section',
            __('Twitter Card', 'seo-fury'),
            array($this, 'twitter_card_section_callback'),
            'seo_fury_meta_group'
        );

        add_settings_section(
            'seo_fury_content_types_section',
            __('Content Type Templates', 'seo-fury'),
            array($this, 'content_types_section_callback'),
            'seo_fury_meta_group'
        );

        add_settings_field(
            'seo_fury_content_types_templates',
            __('Templates', 'seo-fury'),
            array($this, 'content_types_templates_callback'),
            'seo_fury_meta_group',
            'seo_fury_content_types_section'
        );

        add_settings_field(
            'seo_fury_twitter_card_type_field',
            __('Twitter Card Type', 'seo-fury'),
            array($this, 'twitter_card_type_callback'),
            'seo_fury_meta_group',
            'seo_fury_twitter_card_section'
        );
    }

    public function robots_meta_section_callback()
    {
        echo '<p>' . esc_html__('Default values for the robots meta tag.', 'seo-fury') . '</p>';
    }

    public function robots_meta_tags_callback()
    {
        $index = get_option('seo_fury_robots_meta_index', 0);
        $noindex = get_option('seo_fury_robots_meta_noindex', 0);
        $nofollow = get_option('seo_fury_robots_meta_nofollow', 0);
        $noarchive = get_option('seo_fury_robots_meta_noarchive', 0);
        $noimageindex = get_option('seo_fury_robots_meta_noimageindex', 0);
        $nosnippet = get_option('seo_fury_robots_meta_nosnippet', 0);
?>
        <div style="padding: 10px 14px; background: var(--sf-warning-light,#fff3cd); border-left: 4px solid var(--sf-warning,#ffc107); border-radius: var(--sf-radius-sm,6px); color: var(--sf-gray-700); margin-bottom: 15px;">
            <strong class="sf-info-box-title"><?php esc_html_e('Important:', 'seo-fury'); ?></strong> <?php
            printf(
                /* translators: 1: Index setting name, 2: NoIndex setting name */
                esc_html__('Do not enable %1$s and %2$s at the same time. If both are enabled, %2$s takes priority.', 'seo-fury'),
                '<code>Index</code>',
                '<code>NoIndex</code>'
            ); ?>
        </div>

        <fieldset>
            <label style="display: block; margin-bottom: 10px;">
                <input type="checkbox" name="seo_fury_robots_meta_index" value="1" <?php checked($index, 1); ?>>
                <strong><?php esc_html_e('Index', 'seo-fury'); ?></strong> - <?php esc_html_e('Allow search engines to index and show these pages in results', 'seo-fury'); ?>
            </label>

            <label style="display: block; margin-bottom: 10px;">
                <input type="checkbox" name="seo_fury_robots_meta_noindex" value="1" <?php checked($noindex, 1); ?>>
                <strong><?php esc_html_e('NoIndex', 'seo-fury'); ?></strong> - <?php esc_html_e('Prevent indexing and showing pages in search results', 'seo-fury'); ?>
            </label>

            <label style="display: block; margin-bottom: 10px;">
                <input type="checkbox" name="seo_fury_robots_meta_nofollow" value="1" <?php checked($nofollow, 1); ?>>
                <strong><?php esc_html_e('NoFollow', 'seo-fury'); ?></strong> - <?php esc_html_e('Prevent search engines from following links on the page', 'seo-fury'); ?>
            </label>

            <label style="display: block; margin-bottom: 10px;">
                <input type="checkbox" name="seo_fury_robots_meta_noarchive" value="1" <?php checked($noarchive, 1); ?>>
                <strong><?php esc_html_e('NoArchive', 'seo-fury'); ?></strong> - <?php esc_html_e('Prevent cached links in search results', 'seo-fury'); ?>
            </label>

            <label style="display: block; margin-bottom: 10px;">
                <input type="checkbox" name="seo_fury_robots_meta_noimageindex" value="1" <?php checked($noimageindex, 1); ?>>
                <strong><?php esc_html_e('NoImageIndex', 'seo-fury'); ?></strong> - <?php esc_html_e('Prevent indexing page images by search engines', 'seo-fury'); ?>
            </label>

            <label style="display: block; margin-bottom: 10px;">
                <input type="checkbox" name="seo_fury_robots_meta_nosnippet" value="1" <?php checked($nosnippet, 1); ?>>
                <strong><?php esc_html_e('NoSnippet', 'seo-fury'); ?></strong> - <?php esc_html_e('Prevents displaying snippets in search results', 'seo-fury'); ?>
            </label>
        </fieldset>
    <?php
    }


    public function advanced_robots_section_callback()
    {
        echo '<p>' . esc_html__('Additional settings to control content appearance in search results.', 'seo-fury') . '</p>';
    }

    public function robots_snippet_callback()
    {
        $value = get_option('seo_fury_robots_meta_max_snippet', -1);
    ?>
        <input type="number"
            name="seo_fury_robots_meta_max_snippet"
            value="<?php echo esc_attr($value); ?>"
            min="-1" max="500"
            class="small-text">
        <span><?php esc_html_e('characters', 'seo-fury'); ?></span>

        <p class="description">
            <?php esc_html_e('Set the maximum snippet length in characters.', 'seo-fury'); ?><br>
            <code>-1</code> <?php esc_html_e('means unlimited.', 'seo-fury'); ?><br>
            <code>0</code> <?php esc_html_e('disables snippets.', 'seo-fury'); ?>
        </p>
    <?php
    }



    public function robots_video_callback()
    {
        $value = get_option('seo_fury_robots_meta_max_video_preview', -1);
    ?>
        <input type="number"
            name="seo_fury_robots_meta_max_video_preview"
            value="<?php echo esc_attr($value); ?>"
            min="-1" max="999"
            class="small-text">
        <span><?php esc_html_e('seconds', 'seo-fury'); ?></span>

        <p class="description">
            <?php esc_html_e('Set the maximum video preview length in seconds.', 'seo-fury'); ?><br>
            <code>-1</code> <?php esc_html_e('means unlimited.', 'seo-fury'); ?><br>
            <code>0</code> <?php esc_html_e('disables video previews.', 'seo-fury'); ?>
        </p>
    <?php
    }


    public function robots_image_callback()
    {
        $value = get_option('seo_fury_robots_meta_max_image_preview', 'standard');
    ?>
        <select name="seo_fury_robots_meta_max_image_preview">
            <option value="none" <?php selected($value, 'none'); ?>><?php esc_html_e('None', 'seo-fury'); ?></option>
            <option value="standard" <?php selected($value, 'standard'); ?>><?php esc_html_e('Standard', 'seo-fury'); ?></option>
            <option value="large" <?php selected($value, 'large'); ?>><?php esc_html_e('Large', 'seo-fury'); ?></option>
        </select>

        <p class="description">
            <?php esc_html_e('Set the maximum image preview size for images on this page.', 'seo-fury'); ?><br>
            <code>None</code> <?php esc_html_e('disables image previews.', 'seo-fury'); ?><br>
            <code>Standard</code> / <code>Large</code> <?php esc_html_e('are standard limits.', 'seo-fury'); ?>
        </p>
    <?php
    }


    public function noindex_archives_section_callback()
    {
        echo '<p>' . esc_html__('Adding noindex for empty archives helps avoid indexing empty pages.', 'seo-fury') . '</p>';
    }

    public function noindex_empty_callback()
    {
        $value = get_option('seo_fury_noindex_empty_archives', 0);
    ?>
        <label>
            <input type="checkbox" name="seo_fury_noindex_empty_archives" value="1" <?php checked($value, 1); ?>>
            <?php
            /* translators: %s is the <code>noindex</code> HTML tag, do not translate. */
            printf(esc_html__('Add %s for empty category and tag archives', 'seo-fury'), '<code>noindex</code>'); ?>
        </label>
        <p class="description">
            <?php
            /* translators: %s is the <code>index</code> HTML tag, do not translate. */
            printf(esc_html__('When a post is added, the archive switches back to %s.', 'seo-fury'), '<code>index</code>'); ?>
        </p>
    <?php
    }

    public function title_settings_section_callback()
    {
        echo '<p>' . esc_html__('Configure how page titles are displayed on your site.', 'seo-fury') . '</p>';
    }

    public function title_separator_callback()
    {
        $separator = get_option('seo_fury_title_separator', '-');
        $separators = array(
            '-' => '-',
            '–' => '–',
            '—' => '—',
            '»' => '»',
            '|' => '|',
            '•' => '•'
        );
    ?>
        <select name="seo_fury_title_separator" id="title-separator-select">
            <?php foreach ($separators as $value => $label): ?>
                <option value="<?php echo esc_attr($value); ?>" <?php selected($separator, $value); ?>>
                    <?php echo esc_html($label); ?>
                </option>
            <?php endforeach; ?>
        </select>
        <p class="description">
            <?php
            /* translators: %1$s and %2$s are template variable names wrapped in <code> tags, do not translate. */
            printf(esc_html__('Use the separator in title templates with %1$s or %2$s.', 'seo-fury'), '<code>%separator%</code>', '<code>%sep%</code>'); ?>
        </p>

        <div style="margin-top: 15px; padding: 15px; background: var(--sf-gray-50,#f5f5f5); border-left: 4px solid var(--sf-primary,#0073aa); border-radius: var(--sf-radius-sm,6px); color: var(--sf-gray-700);">
            <strong class="sf-info-box-title"><?php esc_html_e('Preview:', 'seo-fury'); ?></strong>
            <div id="separator-preview" style="margin-top: 10px; font-size: 16px;">
                <?php esc_html_e('Page title', 'seo-fury'); ?> <span id="preview-sep"><?php echo esc_html($separator); ?></span> <?php esc_html_e('Site name', 'seo-fury'); ?>
            </div>
        </div>

        <script>
            jQuery(document).ready(function($) {
                $('#title-separator-select').on('change', function() {
                    var sep = $(this).val();
                    $('#preview-sep').text(sep);
                });
            });
        </script>
    <?php
    }

    public function title_capitalize_callback()
    {
        $value = get_option('seo_fury_title_capitalize', 0);
    ?>
        <label>
            <input type="checkbox" name="seo_fury_title_capitalize" value="1" <?php checked($value, 1); ?>>
            <?php esc_html_e('Automatically capitalize each word in titles', 'seo-fury'); ?>
        </label>
        <p class="description">
            <?php
            /* translators: %1$s is the before example, %2$s is the after example. */
            printf(esc_html__('Example: "%1$s" → "%2$s"', 'seo-fury'), 'page title example', 'Page Title Example'); ?>
        </p>
    <?php
    }

    public function twitter_card_section_callback()
    {
        echo '<p>' . esc_html__('Configure the Twitter card type for your pages.', 'seo-fury') . '</p>';
    }

    public function twitter_card_type_callback()
    {
        $value = get_option('seo_fury_twitter_card_type', 'summary_large_image');
    ?>
        <select name="seo_fury_twitter_card_type">
            <option value="summary_large_image" <?php selected($value, 'summary_large_image'); ?>>
                <?php esc_html_e('Summary with large image', 'seo-fury'); ?>
            </option>
            <option value="summary" <?php selected($value, 'summary'); ?>>
                <?php esc_html_e('Summary', 'seo-fury'); ?>
            </option>
        </select>

        <p class="description">
            <?php esc_html_e('This card type is used for new posts and for posts without a selected card type.', 'seo-fury'); ?>
        </p>
<?php
    }

    public function content_types_section_callback()
    {
        echo '<p>' . esc_html__('Set default title and description templates for each content type.', 'seo-fury') . '</p>';
        echo '<p class="description">' . esc_html__('Available variables:', 'seo-fury') . ' <code>%title%</code>, <code>%excerpt%</code>, <code>%sitename%</code>, <code>%sep%</code></p>';
    }

    public function content_types_templates_callback()
    {
        $post_types = get_post_types(array('public' => true), 'objects');
        ?>
        <table class="widefat striped" style="max-width: 100%;">
            <thead>
                <tr>
                    <th><?php esc_html_e('Content Type', 'seo-fury'); ?></th>
                    <th><?php esc_html_e('Title Template', 'seo-fury'); ?></th>
                    <th><?php esc_html_e('Description Template', 'seo-fury'); ?></th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($post_types as $post_type): ?>
                    <?php
                    $title_key = 'seo_fury_title_template_' . $post_type->name;
                    $desc_key = 'seo_fury_description_template_' . $post_type->name;
                    $title_val = get_option($title_key, '%title% %sep% %sitename%');
                    $desc_val = get_option($desc_key, '%excerpt%');
                    ?>
                    <tr>
                        <td><?php echo esc_html($post_type->label); ?> <span class="description">(<?php echo esc_html($post_type->name); ?>)</span></td>
                        <td>
                            <input type="text" name="<?php echo esc_attr($title_key); ?>" value="<?php echo esc_attr($title_val); ?>" class="regular-text" />
                        </td>
                        <td>
                            <input type="text" name="<?php echo esc_attr($desc_key); ?>" value="<?php echo esc_attr($desc_val); ?>" class="regular-text" />
                        </td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        <?php
    }

    private function get_available_variables_note() {
        $vars = array('%title%', '%excerpt%', '%sitename%', '%sitedesc%', '%sep%');
        $descriptions = array();
        if ( class_exists( 'SEO_Fury_Shortcode_Variables' ) ) {
            foreach ( SEO_Fury_Shortcode_Variables::get_variables() as $row ) {
                if ( isset( $row['var'] ) ) {
                    $descriptions[ $row['var'] ] = array(
                        'label' => isset( $row['label'] ) ? $row['label'] : '',
                        'desc'  => isset( $row['desc'] )  ? $row['desc']  : '',
                    );
                }
            }
        }

        $chips = array();
        foreach ( $vars as $var ) {
            $info  = isset( $descriptions[ $var ] ) ? $descriptions[ $var ] : array( 'label' => '', 'desc' => '' );
            $title = trim( $info['label'] . ( $info['desc'] !== '' ? ' — ' . $info['desc'] : '' ) );
            $chips[] = '<code title="' . esc_attr( $title ) . '" style="cursor: help;">' . esc_html( $var ) . '</code>';
        }

        return esc_html__('Available variables:', 'seo-fury') . ' ' . implode( ', ', $chips );
    }

    private function render_template_pair($title_key, $desc_key, $title_label, $desc_label, $default_title = '', $default_desc = '')
    {
        $title_val = get_option($title_key, $default_title);
        $desc_val = get_option($desc_key, $default_desc);
        ?>
        <div class="seo-meta-template-row">
            <div class="seo-meta-template-field">
                <label for="<?php echo esc_attr($title_key); ?>"><?php echo esc_html($title_label); ?></label>
                <div class="seo-admin-input-with-dropdown">
                    <input type="text" id="<?php echo esc_attr($title_key); ?>" name="<?php echo esc_attr($title_key); ?>" value="<?php echo esc_attr($title_val); ?>" class="regular-text" />
                    <?php SEO_Fury_Shortcode_Variables::render_admin_dropdown($title_key); ?>
                </div>
            </div>
            <div class="seo-meta-template-field">
                <label for="<?php echo esc_attr($desc_key); ?>"><?php echo esc_html($desc_label); ?></label>
                <div class="seo-admin-input-with-dropdown">
                    <input type="text" id="<?php echo esc_attr($desc_key); ?>" name="<?php echo esc_attr($desc_key); ?>" value="<?php echo esc_attr($desc_val); ?>" class="regular-text" />
                    <?php SEO_Fury_Shortcode_Variables::render_admin_dropdown($desc_key); ?>
                </div>
            </div>
        </div>
        <div class="seo-fury-settings-preview" data-title-input="<?php echo esc_attr($title_key); ?>" data-desc-input="<?php echo esc_attr($desc_key); ?>">
            <div class="seo-serp-preview">
                <h5><?php esc_html_e('Google Preview', 'seo-fury'); ?></h5>
                <div class="serp-preview-box">
                    <div class="serp-title"></div>
                    <div class="serp-url"><?php echo esc_html(home_url('/')); ?>example-page</div>
                    <div class="serp-description"></div>
                </div>
                <div class="serp-char-counts">
                    <span class="serp-title-count">0/60</span>
                    <span class="serp-desc-count">0/160</span>
                </div>
            </div>
            <div class="seo-social-preview">
                <h5><?php esc_html_e('Social Preview', 'seo-fury'); ?></h5>
                <div class="social-preview-box">
                    <div class="social-preview-image"></div>
                    <div class="social-preview-content">
                        <div class="social-preview-domain"><?php echo esc_html(wp_parse_url(home_url(), PHP_URL_HOST)); ?></div>
                        <div class="social-preview-title"></div>
                        <div class="social-preview-desc"></div>
                    </div>
                </div>
            </div>
        </div>
        <?php
    }

    public function render_settings_page()
    {
        $post_types = get_post_types(array('public' => true), 'objects');
        $taxonomies = get_taxonomies(array('public' => true), 'objects');
        ?>
        <form method="post" action="options.php">
            <?php settings_fields('seo_fury_meta_group'); ?>
            <div class="seo-meta-titles-layout">
                <div class="seo-meta-titles-nav">
                    <button type="button" class="seo-meta-nav-item active" data-panel="general">
                        <span class="dashicons dashicons-admin-generic"></span>
                        <?php esc_html_e('General Meta', 'seo-fury'); ?>
                    </button>
                    <button type="button" class="seo-meta-nav-item" data-panel="home">
                        <span class="dashicons dashicons-admin-home"></span>
                        <?php esc_html_e('Home', 'seo-fury'); ?>
                    </button>
                    <button type="button" class="seo-meta-nav-item" data-panel="authors">
                        <span class="dashicons dashicons-admin-users"></span>
                        <?php esc_html_e('Authors', 'seo-fury'); ?>
                    </button>
                    <button type="button" class="seo-meta-nav-item" data-panel="misc">
                        <span class="dashicons dashicons-admin-page"></span>
                        <?php esc_html_e('Misc Pages', 'seo-fury'); ?>
                    </button>
                    <?php if (!empty($taxonomies)): ?>
                        <div class="seo-meta-nav-heading"><?php esc_html_e('Taxonomies', 'seo-fury'); ?></div>
                        <?php foreach ($taxonomies as $taxonomy): ?>
                            <button type="button" class="seo-meta-nav-item" data-panel="tax-<?php echo esc_attr($taxonomy->name); ?>">
                                <span class="dashicons dashicons-tag"></span>
                                <?php echo esc_html($taxonomy->label); ?>
                            </button>
                        <?php endforeach; ?>
                    <?php endif; ?>
                    <div class="seo-meta-nav-heading"><?php esc_html_e('Post Types', 'seo-fury'); ?></div>
                    <?php foreach ($post_types as $post_type): ?>
                        <button type="button" class="seo-meta-nav-item" data-panel="post-<?php echo esc_attr($post_type->name); ?>">
                            <span class="dashicons dashicons-media-document"></span>
                            <?php echo esc_html($post_type->label); ?>
                        </button>
                    <?php endforeach; ?>
                </div>
                <div class="seo-meta-titles-panels">
                    <div class="seo-meta-panel active" data-panel="general">
                        <h3><?php esc_html_e('General Meta', 'seo-fury'); ?></h3>
                        <p class="description"><?php echo wp_kses_post( $this->get_available_variables_note() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
                        <div class="seo-meta-section">
                            <h4><?php esc_html_e('Robots Meta', 'seo-fury'); ?></h4>
                            <?php $this->robots_meta_tags_callback(); ?>
                        </div>
                        <div class="seo-meta-section">
                            <h4><?php esc_html_e('Advanced Robots Meta', 'seo-fury'); ?></h4>
                            <?php $this->robots_snippet_callback(); ?>
                            <?php $this->robots_video_callback(); ?>
                            <?php $this->robots_image_callback(); ?>
                        </div>
                        <div class="seo-meta-section">
                            <h4><?php esc_html_e('Noindex Empty Archives', 'seo-fury'); ?></h4>
                            <?php $this->noindex_empty_callback(); ?>
                        </div>
                        <div class="seo-meta-section">
                            <h4><?php esc_html_e('Title Settings', 'seo-fury'); ?></h4>
                            <?php $this->title_separator_callback(); ?>
                            <?php $this->title_capitalize_callback(); ?>
                        </div>
                        <div class="seo-meta-section">
                            <h4><?php esc_html_e('Twitter Card', 'seo-fury'); ?></h4>
                            <?php $this->twitter_card_type_callback(); ?>
                        </div>
                    </div>

                    <div class="seo-meta-panel" data-panel="home">
                        <h3><?php esc_html_e('Home', 'seo-fury'); ?></h3>
                        <p class="description"><?php echo wp_kses_post( $this->get_available_variables_note() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
                        <?php $this->render_template_pair('seo_fury_title_template_home', 'seo_fury_description_template_home', __('Homepage Title', 'seo-fury'), __('Homepage Description', 'seo-fury'), '%sitename% %sep% %sitedesc%', '%sitedesc%'); ?>
                    </div>

                    <div class="seo-meta-panel" data-panel="authors">
                        <h3><?php esc_html_e('Authors', 'seo-fury'); ?></h3>
                        <p class="description"><?php echo wp_kses_post( $this->get_available_variables_note() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
                        <?php $this->render_template_pair('seo_fury_title_template_author', 'seo_fury_description_template_author', __('Author Archive Title', 'seo-fury'), __('Author Archive Description', 'seo-fury'), '%title% %sep% %sitename%', '%excerpt%'); ?>
                    </div>

                    <div class="seo-meta-panel" data-panel="misc">
                        <h3><?php esc_html_e('Misc Pages', 'seo-fury'); ?></h3>
                        <p class="description"><?php echo wp_kses_post( $this->get_available_variables_note() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
                        <?php $this->render_template_pair('seo_fury_title_template_blog', 'seo_fury_description_template_blog', __('Blog Page Title', 'seo-fury'), __('Blog Page Description', 'seo-fury'), '%title% %sep% %sitename%', '%excerpt%'); ?>
                        <?php $this->render_template_pair('seo_fury_title_template_search', 'seo_fury_description_template_search', __('Search Results Title', 'seo-fury'), __('Search Results Description', 'seo-fury'), 'Search Results for %title% %sep% %sitename%', 'Search results for %title%'); ?>
                        <?php $this->render_template_pair('seo_fury_title_template_date', 'seo_fury_description_template_date', __('Date Archive Title', 'seo-fury'), __('Date Archive Description', 'seo-fury'), '%title% %sep% %sitename%', '%excerpt%'); ?>
                        <?php $this->render_template_pair('seo_fury_title_template_404', 'seo_fury_description_template_404', __('404 Title', 'seo-fury'), __('404 Description', 'seo-fury'), 'Page Not Found %sep% %sitename%', 'The page you are looking for could not be found.'); ?>
                    </div>

                    <?php foreach ($taxonomies as $taxonomy): ?>
                        <div class="seo-meta-panel" data-panel="tax-<?php echo esc_attr($taxonomy->name); ?>">
                            <h3><?php echo esc_html($taxonomy->label); ?></h3>
                            <p class="description"><?php echo wp_kses_post( $this->get_available_variables_note() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
                            <?php
                            $title_key = 'seo_fury_title_template_tax_' . $taxonomy->name;
                            $desc_key = 'seo_fury_description_template_tax_' . $taxonomy->name;
                            /* translators: %s is the taxonomy name (e.g. Categories, Tags). */
                            $this->render_template_pair($title_key, $desc_key, sprintf(__('%s Title', 'seo-fury'), $taxonomy->label), sprintf(__('%s Description', 'seo-fury'), $taxonomy->label), '%title% %sep% %sitename%', '%excerpt%');
                            ?>

                            <?php $this->render_taxonomy_robots_meta($taxonomy->name, $taxonomy->label); ?>
                        </div>
                    <?php endforeach; ?>

                    <?php foreach ($post_types as $post_type): ?>
                        <div class="seo-meta-panel" data-panel="post-<?php echo esc_attr($post_type->name); ?>">
                            <h3><?php echo esc_html($post_type->label); ?></h3>
                            <p class="description"><?php echo wp_kses_post( $this->get_available_variables_note() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
                            <?php
                            $title_key = 'seo_fury_title_template_' . $post_type->name;
                            $desc_key = 'seo_fury_description_template_' . $post_type->name;
                            /* translators: %s is the post type name (e.g. Posts, Pages). */
                            $this->render_template_pair($title_key, $desc_key, sprintf(__('%s Title', 'seo-fury'), $post_type->label), sprintf(__('%s Description', 'seo-fury'), $post_type->label), '%title% %sep% %sitename%', '%excerpt%');
                            ?>

                            <div class="seo-meta-section seo-meta-schema-group">
                                <h4>
                                    <span class="dashicons dashicons-editor-code" style="font-size:16px;width:16px;height:16px;vertical-align:text-bottom;margin-right:4px;color:var(--sf-primary);"></span>
                                    <?php esc_html_e('Schema Markup', 'seo-fury'); ?>
                                </h4>
                                <?php $this->render_post_type_schema_selector($post_type->name, $post_type->label); ?>
                                <?php $this->render_post_type_schema_graph($post_type->name, $post_type->label); ?>
                            </div>
                            <?php $this->render_post_type_robots_meta($post_type->name, $post_type->label); ?>
                        </div>
                    <?php endforeach; ?>
                </div>
            </div>
            <?php submit_button(); ?>
        </form>

        <script>
            jQuery(document).ready(function($) {
                // Restore active panel from localStorage
                var savedPanel = localStorage.getItem('seo_fury_meta_panel');
                if (savedPanel && $('.seo-meta-panel[data-panel="' + savedPanel + '"]').length) {
                    $('.seo-meta-nav-item').removeClass('active');
                    $('.seo-meta-nav-item[data-panel="' + savedPanel + '"]').addClass('active');
                    $('.seo-meta-panel').removeClass('active');
                    $('.seo-meta-panel[data-panel="' + savedPanel + '"]').addClass('active');
                }

                // Panel navigation
                $('.seo-meta-nav-item').on('click', function() {
                    var target = $(this).data('panel');
                    localStorage.setItem('seo_fury_meta_panel', target);
                    $('.seo-meta-nav-item').removeClass('active');
                    $(this).addClass('active');
                    $('.seo-meta-panel').removeClass('active');
                    $('.seo-meta-panel[data-panel="' + target + '"]').addClass('active');
                });

                // Shortcode dropdown toggle
                $(document).on('click', '.seo-admin-shortcode-btn', function(e) {
                    e.stopPropagation();
                    var menu = $(this).siblings('.seo-admin-shortcode-menu');
                    $('.seo-admin-shortcode-menu').not(menu).removeClass('active');
                    menu.toggleClass('active');

                    // Reset search when opening
                    if (menu.hasClass('active')) {
                        var $search = menu.find('.sf-shortcode-search');
                        $search.val('');
                        menu.find('.seo-admin-shortcode-item').show();
                        setTimeout(function() { $search.focus(); }, 50);
                    }
                });

                // Insert shortcode into field
                $(document).on('click', '.seo-admin-shortcode-item', function() {
                    var variable = $(this).data('var');
                    var wrapper = $(this).closest('.seo-admin-input-with-dropdown');
                    var input = wrapper.find('input, textarea').first();
                    if (input.length) {
                        var cursorPos = input[0].selectionStart || input.val().length;
                        var val = input.val();
                        input.val(val.substring(0, cursorPos) + variable + val.substring(cursorPos));
                        input.focus();
                        var newPos = cursorPos + variable.length;
                        input[0].setSelectionRange(newPos, newPos);
                    }
                    $(this).closest('.seo-admin-shortcode-menu').removeClass('active');
                });

                // Close dropdowns when clicking outside
                $(document).on('click', function() {
                    $('.seo-admin-shortcode-menu').removeClass('active');
                });

                // Admin shortcode dropdown search filter
                $(document).on('input', '.seo-admin-shortcode-menu .sf-shortcode-search', function() {
                    var query = $(this).val().toLowerCase();
                    $(this).closest('.seo-admin-shortcode-menu').find('.seo-admin-shortcode-item').each(function() {
                        var text = $(this).text().toLowerCase();
                        var varName = ($(this).data('var') || '').toLowerCase();
                        $(this).toggle(text.indexOf(query) !== -1 || varName.indexOf(query) !== -1);
                    });
                });

                // Prevent search input clicks from closing the dropdown
                $(document).on('click', '.seo-admin-shortcode-menu .sf-shortcode-search', function(e) {
                    e.stopPropagation();
                });

                // Robots meta toggle per post type
                $(document).on('change', '.seo-pt-robots-toggle', function() {
                    var pt = $(this).data('pt');
                    $('#seo-pt-robots-' + pt).toggle(this.checked);
                });

                // Advanced robots toggle per post type
                $(document).on('change', '.seo-pt-robots-adv-toggle', function() {
                    var pt = $(this).data('pt');
                    $('#seo-pt-robots-adv-' + pt).toggle(this.checked);
                });

                // Robots meta toggle per taxonomy
                $(document).on('change', '.seo-tax-robots-toggle', function() {
                    var tax = $(this).data('tax');
                    $('#seo-tax-robots-' + tax).toggle(this.checked);
                });

                // Advanced robots toggle per taxonomy
                $(document).on('change', '.seo-tax-robots-adv-toggle', function() {
                    var tax = $(this).data('tax');
                    $('#seo-tax-robots-adv-' + tax).toggle(this.checked);
                });

                $(document).on('change', '.seo-schema-type-select', function() {
                    var pt = $(this).data('pt');
                    var val = $(this).val();
                    if (val === '') {
                        $('#seo-schema-fields-' + pt).hide();
                    } else {
                        $('#seo-schema-fields-' + pt).show();
                        if (val === 'article') {
                            $('#seo-schema-article-' + pt).show();
                        } else {
                            $('#seo-schema-article-' + pt).hide();
                        }
                    }
                });

                $(document).on('change', '.seo-schema-author-select', function() {
                    var pt = $(this).data('pt');
                    if ($(this).val() === 'custom') {
                        $('#seo-schema-author-custom-' + pt).show();
                    } else {
                        $('#seo-schema-author-custom-' + pt).hide();
                    }
                });
            });
        </script>
        <?php
    }


    /**
     * Render the default Schema type selector for a post type panel.
     */
    private function render_post_type_schema_selector($post_type_name, $post_type_label)
    {
        $schema_key = 'seo_fury_default_schema_' . $post_type_name;
        $schema_val = get_option($schema_key, '');
        $schema_types = array(
            ''              => __('None (click to set)', 'seo-fury'),
            'article'       => __('Article', 'seo-fury'),
            'book'          => __('Book', 'seo-fury'),
            'course'        => __('Course', 'seo-fury'),
            'dataset'       => __('Dataset', 'seo-fury'),
            'event'         => __('Event', 'seo-fury'),
            'factcheck'     => __('Fact Check', 'seo-fury'),
            'jobposting'    => __('Job Posting', 'seo-fury'),
            'movie'         => __('Movie', 'seo-fury'),
            'music'         => __('Music', 'seo-fury'),
            'person'        => __('Person', 'seo-fury'),
            'product'       => __('Product', 'seo-fury'),
            'recipe'        => __('Recipe', 'seo-fury'),
            'restaurant'    => __('Restaurant', 'seo-fury'),
            'service'       => __('Service', 'seo-fury'),
            'software'      => __('Software', 'seo-fury'),
            'video'         => __('Video', 'seo-fury'),
        );
        ?>
        <?php
        $headline_key = 'seo_fury_schema_headline_' . $post_type_name;
        $desc_schema_key = 'seo_fury_schema_description_' . $post_type_name;
        $article_type_key = 'seo_fury_schema_article_type_' . $post_type_name;
        $author_source_key = 'seo_fury_schema_author_source_' . $post_type_name;
        $author_custom_key = 'seo_fury_schema_author_custom_' . $post_type_name;

        $headline_val = get_option($headline_key, '%title%');
        $desc_schema_val = get_option($desc_schema_key, '%excerpt%');
        $article_type_val = get_option($article_type_key, 'article');
        $author_source_val = get_option($author_source_key, 'auto');
        $author_custom_val = get_option($author_custom_key, '');
        ?>
        <div class="seo-schema-selector-content">
            <p class="description"><?php esc_html_e('Select the default Schema markup type for this post type. Will be used when no custom schema is set per post.', 'seo-fury'); ?></p>
            <div style="margin-bottom: 12px;">
                <select name="<?php echo esc_attr($schema_key); ?>" id="<?php echo esc_attr($schema_key); ?>" class="seo-schema-type-select" data-pt="<?php echo esc_attr($post_type_name); ?>">
                    <?php foreach ($schema_types as $value => $label): ?>
                        <option value="<?php echo esc_attr($value); ?>" <?php selected($schema_val, $value); ?>><?php echo esc_html($label); ?></option>
                    <?php endforeach; ?>
                </select>
            </div>

            <div class="seo-schema-extra-fields" id="seo-schema-fields-<?php echo esc_attr($post_type_name); ?>" style="<?php echo esc_attr( empty($schema_val) ? 'display:none;' : '' ); ?>margin-top: 16px;">
                <div class="seo-meta-template-row">
                    <div class="seo-meta-template-field">
                        <label for="<?php echo esc_attr($headline_key); ?>"><?php esc_html_e('Schema Headline', 'seo-fury'); ?></label>
                        <div class="seo-admin-input-with-dropdown">
                            <input type="text" id="<?php echo esc_attr($headline_key); ?>" name="<?php echo esc_attr($headline_key); ?>" value="<?php echo esc_attr($headline_val); ?>" class="regular-text" />
                            <?php SEO_Fury_Shortcode_Variables::render_admin_dropdown($headline_key); ?>
                        </div>
                    </div>
                    <div class="seo-meta-template-field">
                        <label for="<?php echo esc_attr($desc_schema_key); ?>"><?php esc_html_e('Schema Description', 'seo-fury'); ?></label>
                        <div class="seo-admin-input-with-dropdown">
                            <input type="text" id="<?php echo esc_attr($desc_schema_key); ?>" name="<?php echo esc_attr($desc_schema_key); ?>" value="<?php echo esc_attr($desc_schema_val); ?>" class="regular-text" />
                            <?php SEO_Fury_Shortcode_Variables::render_admin_dropdown($desc_schema_key); ?>
                        </div>
                    </div>
                </div>

                <div class="seo-schema-article-fields" id="seo-schema-article-<?php echo esc_attr($post_type_name); ?>" style="<?php echo ($schema_val === 'article') ? '' : 'display:none;'; ?>">
                    <div class="seo-meta-template-row">
                        <div class="seo-meta-template-field">
                            <label for="<?php echo esc_attr($article_type_key); ?>"><?php esc_html_e('Article Type', 'seo-fury'); ?></label>
                            <select name="<?php echo esc_attr($article_type_key); ?>" id="<?php echo esc_attr($article_type_key); ?>">
                                <option value="article" <?php selected($article_type_val, 'article'); ?>>Article</option>
                                <option value="blog_posting" <?php selected($article_type_val, 'blog_posting'); ?>>BlogPosting</option>
                                <option value="news_article" <?php selected($article_type_val, 'news_article'); ?>>NewsArticle</option>
                            </select>
                        </div>
                        <div class="seo-meta-template-field">
                            <label for="<?php echo esc_attr($author_source_key); ?>"><?php esc_html_e('Author in Schema', 'seo-fury'); ?></label>
                            <select name="<?php echo esc_attr($author_source_key); ?>" id="<?php echo esc_attr($author_source_key); ?>" class="seo-schema-author-select" data-pt="<?php echo esc_attr($post_type_name); ?>">
                                <option value="auto" <?php selected($author_source_val, 'auto'); ?>><?php esc_html_e('Auto (from post author)', 'seo-fury'); ?></option>
                                <option value="custom" <?php selected($author_source_val, 'custom'); ?>><?php esc_html_e('Custom', 'seo-fury'); ?></option>
                            </select>
                        </div>
                    </div>
                    <div class="seo-schema-author-custom-wrap" id="seo-schema-author-custom-<?php echo esc_attr($post_type_name); ?>" style="<?php echo ($author_source_val === 'custom') ? '' : 'display:none;'; ?>margin-top: 8px;">
                        <div class="seo-meta-template-field">
                            <label for="<?php echo esc_attr($author_custom_key); ?>"><?php esc_html_e('Custom Author Name', 'seo-fury'); ?></label>
                            <div class="seo-admin-input-with-dropdown">
                                <input type="text" id="<?php echo esc_attr($author_custom_key); ?>" name="<?php echo esc_attr($author_custom_key); ?>" value="<?php echo esc_attr($author_custom_val); ?>" class="regular-text" />
                                <?php SEO_Fury_Shortcode_Variables::render_admin_dropdown($author_custom_key); ?>
                            </div>
                        </div>
                    </div>
                    <p class="description" style="margin-top: 10px;">
                        <span class="dashicons dashicons-info" style="font-size: 16px; width: 16px; height: 16px; vertical-align: text-bottom; color: var(--sf-primary);"></span>
                        <?php esc_html_e('Publication and modification dates are automatically pulled from WordPress post dates for each post.', 'seo-fury'); ?>
                    </p>
                </div>
            </div>

            <div class="seo-schema-bulk-actions" style="margin-top:16px; padding:12px 16px; background:var(--sf-gray-50); border:1px solid var(--sf-gray-100); border-radius:var(--sf-radius-sm);">
                <p style="margin:0 0 8px 0; font-weight:600; font-size:13px; color:var(--sf-gray-700);">
                    <span class="dashicons dashicons-admin-tools" style="font-size:14px;width:14px;height:14px;vertical-align:text-bottom;margin-right:4px;"></span>
                    <?php esc_html_e('Bulk Actions', 'seo-fury'); ?>
                </p>
                <div style="display:flex; gap:8px; flex-wrap:wrap; align-items:center;">
                    <select class="seo-fury-pt-template-select" data-pt="<?php echo esc_attr($post_type_name); ?>" style="min-width: 200px;">
                        <option value=""><?php esc_html_e('— Apply saved Schema —', 'seo-fury'); ?></option>
                    </select>
                    <button type="button"
                            class="button seo-fury-apply-pt-template"
                            data-pt="<?php echo esc_attr($post_type_name); ?>"
                            data-label="<?php echo esc_attr($post_type_label); ?>">
                        <?php esc_html_e('Apply to all posts', 'seo-fury'); ?>
                    </button>
                    <button type="button"
                            class="button seo-fury-delete-pt-schema"
                            data-pt="<?php echo esc_attr($post_type_name); ?>"
                            data-label="<?php echo esc_attr($post_type_label); ?>"
                            style="color: #b32d2e; border-color: #b32d2e;">
                        <span class="dashicons dashicons-trash" style="font-size: 16px; width: 16px; height: 16px; margin-top: 3px; vertical-align: middle;"></span>
                        <?php esc_html_e('Delete Schema from all posts', 'seo-fury'); ?>
                    </button>
                </div>
            </div>
        </div>
        <?php
    }

    /**
     * Render the Robots meta toggle + advanced robots for a post type panel.
     */
    private function render_post_type_robots_meta($post_type_name, $post_type_label)
    {
        $enabled_key = 'seo_fury_pt_robots_enabled_' . $post_type_name;
        $enabled = get_option($enabled_key, 0);

        $robots_fields = array(
            'index'        => array('label' => 'Index', 'desc' => __('Allow search engines to index and show these pages in results.', 'seo-fury')),
            'noindex'      => array('label' => 'No Index', 'desc' => __('Prevent indexing and showing pages in search results.', 'seo-fury')),
            'nofollow'     => array('label' => 'No Follow', 'desc' => __('Prevent search engines from following links on the page.', 'seo-fury')),
            'noarchive'    => array('label' => __('No Archive', 'seo-fury'), 'desc' => __('Prevent cached links in search results.', 'seo-fury')),
            'noimageindex'  => array('label' => __('No Image Index', 'seo-fury'), 'desc' => __('Prevent indexing page images by search engines.', 'seo-fury')),
            'nosnippet'    => array('label' => __('No Snippet', 'seo-fury'), 'desc' => __('Prevents displaying snippets in search results.', 'seo-fury')),
        );

        $adv_key = 'seo_fury_pt_robots_advanced_' . $post_type_name;
        $adv_enabled = get_option($adv_key, 0);
        $max_snippet = get_option('seo_fury_pt_robots_max_snippet_' . $post_type_name, -1);
        $max_video = get_option('seo_fury_pt_robots_max_video_' . $post_type_name, -1);
        $max_image = get_option('seo_fury_pt_robots_max_image_' . $post_type_name, 'large');
        ?>
        <div class="seo-meta-section seo-meta-robots-section">
            <h4>
                <span class="dashicons dashicons-visibility" style="font-size:16px;width:16px;height:16px;vertical-align:text-bottom;margin-right:4px;color:var(--sf-primary);"></span>
                <?php esc_html_e('Custom Robots Meta', 'seo-fury'); ?>
            </h4>
            <label class="seo-fury-toggle">
                <input type="checkbox" name="<?php echo esc_attr($enabled_key); ?>" value="1" <?php checked($enabled, 1); ?> class="seo-pt-robots-toggle" data-pt="<?php echo esc_attr($post_type_name); ?>">
                <span class="seo-fury-toggle-slider"></span>
                <?php
                /* translators: %s is the post type name (e.g. Posts, Pages). */
                printf(esc_html__('Enable custom Robots meta for %s', 'seo-fury'), esc_html($post_type_label)); ?>
            </label>

            <div class="seo-pt-robots-options" id="seo-pt-robots-<?php echo esc_attr($post_type_name); ?>" style="<?php echo esc_attr( $enabled ? '' : 'display:none;' ); ?>">
                <fieldset style="margin-top: 10px;">
                    <?php foreach ($robots_fields as $field_key => $field): ?>
                        <?php
                        $opt_key = 'seo_fury_pt_robots_' . $field_key . '_' . $post_type_name;
                        $opt_val = get_option($opt_key, 0);
                        ?>
                        <label style="display: block; margin-bottom: 8px;">
                            <input type="checkbox" name="<?php echo esc_attr($opt_key); ?>" value="1" <?php checked($opt_val, 1); ?>>
                            <strong><?php echo esc_html($field['label']); ?></strong> — <?php echo esc_html($field['desc']); ?>
                        </label>
                    <?php endforeach; ?>
                </fieldset>

                <div style="margin-top: 15px;">
                    <label class="seo-fury-toggle">
                        <input type="checkbox" name="<?php echo esc_attr($adv_key); ?>" value="1" <?php checked($adv_enabled, 1); ?> class="seo-pt-robots-adv-toggle" data-pt="<?php echo esc_attr($post_type_name); ?>">
                        <span class="seo-fury-toggle-slider"></span>
                        <?php esc_html_e('Advanced Robots Meta', 'seo-fury'); ?>
                    </label>
                </div>

                <div class="seo-pt-robots-advanced" id="seo-pt-robots-adv-<?php echo esc_attr($post_type_name); ?>" style="<?php echo esc_attr( $adv_enabled ? '' : 'display:none;' ); ?>margin-top: 10px;">
                    <div style="margin-bottom: 10px;">
                        <label><strong><?php esc_html_e('Snippet', 'seo-fury'); ?></strong></label>
                        <p class="description"><?php esc_html_e('Maximum snippet length in characters.', 'seo-fury'); ?></p>
                        <input type="number" name="seo_fury_pt_robots_max_snippet_<?php echo esc_attr($post_type_name); ?>" value="<?php echo esc_attr($max_snippet); ?>" min="-1" max="500" class="small-text">
                    </div>
                    <div style="margin-bottom: 10px;">
                        <label><strong><?php esc_html_e('Video Preview', 'seo-fury'); ?></strong></label>
                        <p class="description"><?php esc_html_e('Maximum video preview duration in seconds.', 'seo-fury'); ?></p>
                        <input type="number" name="seo_fury_pt_robots_max_video_<?php echo esc_attr($post_type_name); ?>" value="<?php echo esc_attr($max_video); ?>" min="-1" max="999" class="small-text">
                    </div>
                    <div style="margin-bottom: 10px;">
                        <label><strong><?php esc_html_e('Image Preview Size', 'seo-fury'); ?></strong></label>
                        <p class="description"><?php esc_html_e('Maximum image preview size for images on this page.', 'seo-fury'); ?></p>
                        <select name="seo_fury_pt_robots_max_image_<?php echo esc_attr($post_type_name); ?>">
                            <option value="large" <?php selected($max_image, 'large'); ?>><?php esc_html_e('Large', 'seo-fury'); ?></option>
                            <option value="standard" <?php selected($max_image, 'standard'); ?>><?php esc_html_e('Standard', 'seo-fury'); ?></option>
                            <option value="none" <?php selected($max_image, 'none'); ?>><?php esc_html_e('None', 'seo-fury'); ?></option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
        <?php
    }

    /**
     * Render the Robots meta toggle + advanced robots for a taxonomy panel.
     */
    private function render_taxonomy_robots_meta($tax_name, $tax_label)
    {
        $enabled_key = 'seo_fury_tax_robots_enabled_' . $tax_name;
        $enabled = get_option($enabled_key, 0);

        $robots_fields = array(
            'noindex'      => array('label' => 'No Index', 'desc' => __('Prevent indexing and showing pages in search results.', 'seo-fury')),
            'nofollow'     => array('label' => 'No Follow', 'desc' => __('Prevent search engines from following links on the page.', 'seo-fury')),
            'noarchive'    => array('label' => __('No Archive', 'seo-fury'), 'desc' => __('Prevent cached links in search results.', 'seo-fury')),
            'noimageindex'  => array('label' => __('No Image Index', 'seo-fury'), 'desc' => __('Prevent indexing page images by search engines.', 'seo-fury')),
            'nosnippet'    => array('label' => __('No Snippet', 'seo-fury'), 'desc' => __('Prevents displaying snippets in search results.', 'seo-fury')),
        );

        $adv_key = 'seo_fury_tax_robots_advanced_' . $tax_name;
        $adv_enabled = get_option($adv_key, 0);
        $max_snippet = get_option('seo_fury_tax_robots_max_snippet_' . $tax_name, -1);
        $max_video = get_option('seo_fury_tax_robots_max_video_' . $tax_name, -1);
        $max_image = get_option('seo_fury_tax_robots_max_image_' . $tax_name, 'large');
        ?>
        <div class="seo-meta-section seo-meta-robots-section">
            <h4>
                <span class="dashicons dashicons-visibility" style="font-size:16px;width:16px;height:16px;vertical-align:text-bottom;margin-right:4px;color:var(--sf-primary);"></span>
                <?php esc_html_e('Custom Robots Meta', 'seo-fury'); ?>
            </h4>
            <label class="seo-fury-toggle">
                <input type="checkbox" name="<?php echo esc_attr($enabled_key); ?>" value="1" <?php checked($enabled, 1); ?> class="seo-tax-robots-toggle" data-tax="<?php echo esc_attr($tax_name); ?>">
                <span class="seo-fury-toggle-slider"></span>
                <?php
                /* translators: %s is the taxonomy name (e.g. Categories, Tags). */
                printf(esc_html__('Enable custom Robots meta for %s', 'seo-fury'), esc_html($tax_label)); ?>
            </label>

            <div class="seo-tax-robots-options" id="seo-tax-robots-<?php echo esc_attr($tax_name); ?>" style="<?php echo esc_attr( $enabled ? '' : 'display:none;' ); ?>">
                <fieldset style="margin-top: 10px;">
                    <?php foreach ($robots_fields as $field_key => $field): ?>
                        <?php
                        $opt_key = 'seo_fury_tax_robots_' . $field_key . '_' . $tax_name;
                        $opt_val = get_option($opt_key, 0);
                        ?>
                        <label style="display: block; margin-bottom: 8px;">
                            <input type="checkbox" name="<?php echo esc_attr($opt_key); ?>" value="1" <?php checked($opt_val, 1); ?>>
                            <strong><?php echo esc_html($field['label']); ?></strong> — <?php echo esc_html($field['desc']); ?>
                        </label>
                    <?php endforeach; ?>
                </fieldset>

                <div style="margin-top: 15px;">
                    <label class="seo-fury-toggle">
                        <input type="checkbox" name="<?php echo esc_attr($adv_key); ?>" value="1" <?php checked($adv_enabled, 1); ?> class="seo-tax-robots-adv-toggle" data-tax="<?php echo esc_attr($tax_name); ?>">
                        <span class="seo-fury-toggle-slider"></span>
                        <?php esc_html_e('Advanced Robots Meta', 'seo-fury'); ?>
                    </label>
                </div>

                <div class="seo-tax-robots-advanced" id="seo-tax-robots-adv-<?php echo esc_attr($tax_name); ?>" style="<?php echo esc_attr( $adv_enabled ? '' : 'display:none;' ); ?>margin-top: 10px;">
                    <div style="margin-bottom: 10px;">
                        <label><strong><?php esc_html_e('Snippet', 'seo-fury'); ?></strong></label>
                        <p class="description"><?php esc_html_e('Maximum snippet length in characters.', 'seo-fury'); ?></p>
                        <input type="number" name="seo_fury_tax_robots_max_snippet_<?php echo esc_attr($tax_name); ?>" value="<?php echo esc_attr($max_snippet); ?>" min="-1" max="500" class="small-text">
                    </div>
                    <div style="margin-bottom: 10px;">
                        <label><strong><?php esc_html_e('Video Preview', 'seo-fury'); ?></strong></label>
                        <p class="description"><?php esc_html_e('Maximum video preview duration in seconds.', 'seo-fury'); ?></p>
                        <input type="number" name="seo_fury_tax_robots_max_video_<?php echo esc_attr($tax_name); ?>" value="<?php echo esc_attr($max_video); ?>" min="-1" max="999" class="small-text">
                    </div>
                    <div style="margin-bottom: 10px;">
                        <label><strong><?php esc_html_e('Image Preview Size', 'seo-fury'); ?></strong></label>
                        <p class="description"><?php esc_html_e('Maximum image preview size for images on this page.', 'seo-fury'); ?></p>
                        <select name="seo_fury_tax_robots_max_image_<?php echo esc_attr($tax_name); ?>">
                            <option value="large" <?php selected($max_image, 'large'); ?>><?php esc_html_e('Large', 'seo-fury'); ?></option>
                            <option value="standard" <?php selected($max_image, 'standard'); ?>><?php esc_html_e('Standard', 'seo-fury'); ?></option>
                            <option value="none" <?php selected($max_image, 'none'); ?>><?php esc_html_e('None', 'seo-fury'); ?></option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
        <?php
    }

    /**
     * Render Schema graph inclusion checkboxes for a post type (PRO feature).
     */
    private function render_post_type_schema_graph($post_type_name, $post_type_label)
    {
        $org_key = 'seo_fury_schema_graph_organization_' . $post_type_name;
        $web_key = 'seo_fury_schema_graph_website_' . $post_type_name;
        $org_val = get_option($org_key, 0);
        $web_val = get_option($web_key, 0);

        $is_pro = false;
        if (class_exists('SEO_Fury_Core')) {
            $core = SEO_Fury_Core::get_instance();
            $pro = $core->get_pro_features();
            if ($pro) {
                $is_pro = $pro->has_feature('advanced_seo');
            }
        }
        ?>
        <div class="seo-schema-graph-subsection" style="margin-top:16px; padding-top:16px; border-top:1px solid var(--sf-gray-100);">
            <p style="margin:0 0 8px 0; font-weight:600; font-size:13px; color:var(--sf-gray-700);">
                <?php esc_html_e('Schema Graph', 'seo-fury'); ?>
                <?php if (!$is_pro): ?>
                    <span class="seo-fury-pro-badge">PRO</span>
                <?php endif; ?>
            </p>
            <p class="description"><?php esc_html_e('Include global schema types in the JSON-LD graph for this post type.', 'seo-fury'); ?></p>
            <fieldset <?php echo esc_attr( !$is_pro ? 'class="seo-fury-pro-disabled"' : '' ); ?>>
                <label style="display: block; margin-bottom: 8px;">
                    <input type="checkbox" name="<?php echo esc_attr($org_key); ?>" value="1" <?php checked($org_val, 1); ?> <?php echo esc_attr( !$is_pro ? 'disabled' : '' ); ?>>
                    <strong><?php esc_html_e('Organization', 'seo-fury'); ?></strong> — <?php esc_html_e('Include Organization schema from Local SEO settings.', 'seo-fury'); ?>
                </label>
                <label style="display: block; margin-bottom: 8px;">
                    <input type="checkbox" name="<?php echo esc_attr($web_key); ?>" value="1" <?php checked($web_val, 1); ?> <?php echo esc_attr( !$is_pro ? 'disabled' : '' ); ?>>
                    <strong><?php esc_html_e('Website', 'seo-fury'); ?></strong> — <?php esc_html_e('Include WebSite schema with site info and search action.', 'seo-fury'); ?>
                </label>
            </fieldset>
            <?php if (!$is_pro): ?>
                <p class="seo-fury-pro-notice"><?php esc_html_e('Upgrade to PRO to customize schema graph per post type.', 'seo-fury'); ?></p>
            <?php endif; ?>
        </div>
        <?php
    }

    public function output_meta_tags()
    {
        remove_action('wp_head', 'noindex', 1);
        remove_action('wp_head', 'wp_no_robots');

        $brand = function_exists('seo_fury_get_brand_name') ? seo_fury_get_brand_name() : 'SEO Fury';
        ob_start();

        if (is_singular()) {
            $current_post = get_post();

            if ($current_post && isset($current_post->ID)) {
                // Check per-page custom robots first (highest priority)
                $has_custom_robots = metadata_exists('post', $current_post->ID, '_seo_fury_page_robots_noindex')
                    || metadata_exists('post', $current_post->ID, '_seo_fury_page_robots_nofollow')
                    || metadata_exists('post', $current_post->ID, '_seo_fury_page_robots_noarchive')
                    || metadata_exists('post', $current_post->ID, '_seo_fury_page_robots_nosnippet')
                    || metadata_exists('post', $current_post->ID, '_seo_fury_page_robots_noimageindex');

                if ($has_custom_robots) {
                    // Per-page robots are handled by class-post-meta-basic.php
                    // twitter:card is handled by class-post-meta-social.php for singular pages
                    ob_end_clean();
                    return;
                }

                // Check per-post-type robots settings (medium priority)
                $pt = $current_post->post_type;
                $pt_robots_enabled = get_option('seo_fury_pt_robots_enabled_' . $pt, 0);
                if ($pt_robots_enabled) {
                    $pt_robots_parts = array();

                    $pt_noindex = get_option('seo_fury_pt_robots_noindex_' . $pt, 0);
                    $pt_index = get_option('seo_fury_pt_robots_index_' . $pt, 0);
                    if ($pt_noindex) {
                        $pt_robots_parts[] = 'noindex';
                    } elseif ($pt_index) {
                        $pt_robots_parts[] = 'index';
                    }

                    if (get_option('seo_fury_pt_robots_nofollow_' . $pt, 0)) {
                        $pt_robots_parts[] = 'nofollow';
                    } else {
                        $pt_robots_parts[] = 'follow';
                    }

                    if (get_option('seo_fury_pt_robots_noarchive_' . $pt, 0)) $pt_robots_parts[] = 'noarchive';
                    if (get_option('seo_fury_pt_robots_noimageindex_' . $pt, 0)) $pt_robots_parts[] = 'noimageindex';
                    if (get_option('seo_fury_pt_robots_nosnippet_' . $pt, 0)) $pt_robots_parts[] = 'nosnippet';

                    $pt_adv = get_option('seo_fury_pt_robots_advanced_' . $pt, 0);
                    if ($pt_adv) {
                        $pt_max_snippet = get_option('seo_fury_pt_robots_max_snippet_' . $pt, -1);
                        if ($pt_max_snippet !== '') {
                            $pt_robots_parts[] = 'max-snippet:' . intval($pt_max_snippet);
                        }
                        $pt_max_video = get_option('seo_fury_pt_robots_max_video_' . $pt, -1);
                        if ($pt_max_video !== '') {
                            $pt_robots_parts[] = 'max-video-preview:' . intval($pt_max_video);
                        }
                        $pt_max_image = get_option('seo_fury_pt_robots_max_image_' . $pt, 'large');
                        if ($pt_max_image) {
                            $pt_robots_parts[] = 'max-image-preview:' . $pt_max_image;
                        }
                    }

                    if (!empty($pt_robots_parts)) {
                        echo '<meta name="robots" content="' . esc_attr(implode(', ', $pt_robots_parts)) . '">' . "\n";
                    }

                    // twitter:card is handled by class-post-meta-social.php for singular pages
                    $output = ob_get_clean();
                    if (!empty(trim($output))) {
                        echo "\n<!-- " . esc_html($brand) . " -->\n" . wp_kses_post( $output ) . "<!-- /" . esc_html($brand) . " -->\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                    }
                    return;
                }
            }
        }

        // Check per-taxonomy robots settings for taxonomy archive pages
        $tax_robots_handled = false;
        if (is_category() || is_tag() || is_tax()) {
            $term = get_queried_object();
            if ($term && !empty($term->taxonomy)) {
                $tax_name = $term->taxonomy;
                $tax_robots_enabled = get_option('seo_fury_tax_robots_enabled_' . $tax_name, 0);
                if ($tax_robots_enabled) {
                    $tax_robots_parts = array();
                    if (get_option('seo_fury_tax_robots_noindex_' . $tax_name, 0)) $tax_robots_parts[] = 'noindex';
                    if (get_option('seo_fury_tax_robots_nofollow_' . $tax_name, 0)) $tax_robots_parts[] = 'nofollow';
                    if (get_option('seo_fury_tax_robots_noarchive_' . $tax_name, 0)) $tax_robots_parts[] = 'noarchive';
                    if (get_option('seo_fury_tax_robots_noimageindex_' . $tax_name, 0)) $tax_robots_parts[] = 'noimageindex';
                    if (get_option('seo_fury_tax_robots_nosnippet_' . $tax_name, 0)) $tax_robots_parts[] = 'nosnippet';

                    $tax_adv = get_option('seo_fury_tax_robots_advanced_' . $tax_name, 0);
                    if ($tax_adv) {
                        $tax_max_snippet = get_option('seo_fury_tax_robots_max_snippet_' . $tax_name, '');
                        if ($tax_max_snippet !== '') $tax_robots_parts[] = 'max-snippet:' . intval($tax_max_snippet);
                        $tax_max_video = get_option('seo_fury_tax_robots_max_video_' . $tax_name, '');
                        if ($tax_max_video !== '') $tax_robots_parts[] = 'max-video-preview:' . intval($tax_max_video);
                        $tax_max_image = get_option('seo_fury_tax_robots_max_image_' . $tax_name, '');
                        if ($tax_max_image && in_array($tax_max_image, array('none', 'standard', 'large'), true)) {
                            $tax_robots_parts[] = 'max-image-preview:' . $tax_max_image;
                        }
                    }

                    if (!empty($tax_robots_parts)) {
                        echo '<meta name="robots" content="' . esc_attr(implode(', ', $tax_robots_parts)) . '">' . "\n";
                    }
                    $tax_robots_handled = true;
                }
            }
        }

        if (!$tax_robots_handled) {

        $robots_parts = array();

        $index_set = get_option('seo_fury_robots_meta_index', 0);
        $noindex_set = get_option('seo_fury_robots_meta_noindex', 0);

        if ($noindex_set) {
            $robots_parts[] = 'noindex';
        } elseif ($index_set) {
            $robots_parts[] = 'index';
        }

        if (get_option('seo_fury_robots_meta_nofollow', 0)) {
            $robots_parts[] = 'nofollow';
        } else {
            $robots_parts[] = 'follow';
        }

        if (get_option('seo_fury_robots_meta_noarchive', 0)) {
            $robots_parts[] = 'noarchive';
        }
        if (get_option('seo_fury_robots_meta_noimageindex', 0)) {
            $robots_parts[] = 'noimageindex';
        }
        if (get_option('seo_fury_robots_meta_nosnippet', 0)) {
            $robots_parts[] = 'nosnippet';
        }

        if (get_option('seo_fury_noindex_empty_archives', 0)) {
            if ((is_category() || is_tag() || is_tax()) && !have_posts()) {
                $robots_parts = array_diff($robots_parts, array('index'));
                if (!in_array('noindex', $robots_parts)) {
                    $robots_parts[] = 'noindex';
                }
            }
        }

        $max_snippet = get_option('seo_fury_robots_meta_max_snippet', -1);
        if ($max_snippet !== '') {
            $robots_parts[] = 'max-snippet:' . intval($max_snippet);
        }

        $max_video_preview = get_option('seo_fury_robots_meta_max_video_preview', -1);
        if ($max_video_preview !== '') {
            $robots_parts[] = 'max-video-preview:' . intval($max_video_preview);
        }

        $max_image_preview = get_option('seo_fury_robots_meta_max_image_preview', 'standard');
        if ($max_image_preview) {
            $robots_parts[] = 'max-image-preview:' . $max_image_preview;
        }

        if (!empty($robots_parts)) {
            echo '<meta name="robots" content="' . esc_attr(implode(', ', $robots_parts)) . '">' . "\n";
        }

        } // end if (!$tax_robots_handled)

        if (!is_singular()) {
            $desc_template = '';
            if (is_front_page()) {
                $desc_template = get_option('seo_fury_description_template_home', '');
            } elseif (is_home()) {
                $desc_template = get_option('seo_fury_description_template_blog', '');
            } elseif (is_author()) {
                $desc_template = get_option('seo_fury_description_template_author', '');
            } elseif (is_search()) {
                $desc_template = get_option('seo_fury_description_template_search', '');
            } elseif (is_404()) {
                $desc_template = get_option('seo_fury_description_template_404', '');
            } elseif (is_date()) {
                $desc_template = get_option('seo_fury_description_template_date', '');
            } elseif (is_category() || is_tag() || is_tax()) {
                $term = get_queried_object();
                if ($term && !empty($term->taxonomy)) {
                    $desc_template = get_option('seo_fury_description_template_tax_' . $term->taxonomy, '');
                }
            } elseif (is_post_type_archive()) {
                $post_type = get_query_var('post_type');
                if ($post_type) {
                    $desc_template = get_option('seo_fury_description_template_' . $post_type, '');
                }
            }

            if ($desc_template !== '') {
                $description = $this->apply_template($desc_template, $this->get_context_replacements());
                if ($description !== '') {
                    echo '<meta name="description" content="' . esc_attr($description) . '">' . "\n";
                }
            }
        }

        // OG and Twitter tags for non-singular pages (singular handled by post-meta-social.php)
        if (!is_singular()) {
            $og_title = wp_get_document_title();
            $og_description = isset($description) && $description !== '' ? $description : get_bloginfo('description');
            $og_url = home_url(add_query_arg(array()));
            $og_image = '';

            // Try to get a relevant image
            if (is_category() || is_tag() || is_tax()) {
                $term = get_queried_object();
                if ($term) {
                    $term_image = get_term_meta($term->term_id, '_seo_fury_og_image', true);
                    if ($term_image) {
                        $og_image = $term_image;
                    }
                }
            }

            // Fallback to site logo or custom OG image
            if (!$og_image) {
                $og_image = get_option('seo_fury_default_og_image', '');
            }
            if (!$og_image) {
                $custom_logo_id = get_theme_mod('custom_logo');
                if ($custom_logo_id) {
                    $og_image = wp_get_attachment_url($custom_logo_id);
                }
            }

            $og_type = is_front_page() ? 'website' : 'article';

            echo '<meta property="og:title" content="' . esc_attr($og_title) . '">' . "\n";
            echo '<meta property="og:description" content="' . esc_attr($og_description) . '">' . "\n";
            echo '<meta property="og:type" content="' . esc_attr($og_type) . '">' . "\n";
            echo '<meta property="og:url" content="' . esc_url($og_url) . '">' . "\n";
            echo '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '">' . "\n";
            echo '<meta property="og:locale" content="' . esc_attr(get_locale()) . '">' . "\n";

            if ($og_image) {
                echo '<meta property="og:image" content="' . esc_url($og_image) . '">' . "\n";
            }

            $twitter_card_type = get_option('seo_fury_twitter_card_type', 'summary_large_image');
            echo '<meta name="twitter:card" content="' . esc_attr($twitter_card_type) . '">' . "\n";
            echo '<meta name="twitter:title" content="' . esc_attr($og_title) . '">' . "\n";
            echo '<meta name="twitter:description" content="' . esc_attr($og_description) . '">' . "\n";

            $twitter_site = get_option('seo_fury_twitter_site_handle', '');
            if ($twitter_site) {
                echo '<meta name="twitter:site" content="' . esc_attr($twitter_site) . '">' . "\n";
            }

            if ($og_image) {
                echo '<meta name="twitter:image" content="' . esc_url($og_image) . '">' . "\n";
            }
        }

        $output = ob_get_clean();
        if (!empty(trim($output))) {
            echo "\n<!-- " . esc_html($brand) . " -->\n" . wp_kses_post( $output ) . "<!-- /" . esc_html($brand) . " -->\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        }
    }

    private function apply_template($template, array $replacements) {
        $separator = get_option('seo_fury_title_separator', '—');

        // ── Pagination context ──
        global $wp_query;
        $paged     = max(1, (int) get_query_var('paged', 1));
        $max_pages = (isset($wp_query->max_num_pages) && $wp_query->max_num_pages > 1)
            ? (int) $wp_query->max_num_pages
            : 1;

        $page_str = '';
        if ($paged > 1) {
            /* translators: 1: current page number, 2: total pages */
            $page_str = sprintf(__('page %1$d of %2$d', 'seo-fury'), $paged, $max_pages);
        }

        $date_format = get_option('date_format');

        $defaults = array(
            '%sitename%'    => get_bloginfo('name'),
            '%sitedesc%'    => get_bloginfo('description'),
            '%sep%'         => $separator,
            '%separator%'   => $separator,
            '%title%'       => '',
            '%excerpt%'     => '',
            '%page%'        => $page_str,
            '%pagenumber%'  => ($paged > 1) ? (string) $paged : '',
            '%pagetotal%'   => ($max_pages > 1) ? (string) $max_pages : '',
            '%currentyear%' => wp_date('Y'),
            '%currentmonth%' => date_i18n('F'),
            '%currentday%'  => date_i18n('j'),
            '%currentdate%' => date_i18n($date_format),
            '%currenttime%' => date_i18n('H:i'),
        );

        $result = strtr($template, array_merge($defaults, $replacements));

        // Clean up leftover whitespace from empty variables (e.g. "%page%" → "" leaving double spaces)
        $result = preg_replace('/\s{2,}/', ' ', $result);
        $result = trim($result);
        // Remove trailing/leading separators left by empty variables
        $result = trim($result, ' ' . $separator);
        $result = trim($result);

        return $result;
    }

    private function get_post_replacements($post) {
        $content = $post ? $post->post_content : '';
        $content = strip_shortcodes($content);
        $content = wp_strip_all_tags($content);
        $excerpt = wp_trim_words($content, 20, '...');

        return array(
            '%title%' => $post ? get_the_title($post) : '',
            '%excerpt%' => $excerpt,
        );
    }

    private function get_context_replacements() {
        if (is_front_page()) {
            return array(
                '%title%' => get_bloginfo('name'),
                '%excerpt%' => get_bloginfo('description')
            );
        }

        if (is_home()) {
            $title = get_the_title(get_option('page_for_posts')) ?: get_bloginfo('name');
            return array(
                '%title%' => $title,
                '%excerpt%' => get_bloginfo('description')
            );
        }

        if (is_author()) {
            $author = get_queried_object();
            return array(
                '%title%' => $author ? $author->display_name : '',
                '%excerpt%' => $author ? get_the_author_meta('description', $author->ID) : ''
            );
        }

        if (is_search()) {
            return array(
                '%title%' => get_search_query(),
                '%excerpt%' => ''
            );
        }

        if (is_404()) {
            return array(
                '%title%' => __('Page Not Found', 'seo-fury'),
                '%excerpt%' => ''
            );
        }

        if (is_date()) {
            return array(
                '%title%' => get_the_archive_title(),
                '%excerpt%' => get_the_archive_description()
            );
        }

        if (is_category() || is_tag() || is_tax()) {
            $term = get_queried_object();
            return array(
                '%title%' => $term ? $term->name : '',
                '%excerpt%' => $term ? wp_strip_all_tags(term_description($term->term_id)) : ''
            );
        }

        return array(
            '%title%' => get_the_archive_title(),
            '%excerpt%' => get_the_archive_description()
        );
    }



    public function modify_title($title, $sep, $seplocation)
    {
        if (is_admin() || wp_doing_ajax()) {
            return $title;
        }

        if (defined('REST_REQUEST') && REST_REQUEST) {
            return $title;
        }

        if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false) {
            return $title;
        }

        $separator  = get_option('seo_fury_title_separator', '—');
        $capitalize = get_option('seo_fury_title_capitalize', 0);

        $title = str_replace($sep ?? '', $separator, $title ?? '');

        if ($capitalize) {
            $title = mb_convert_case($title, MB_CASE_TITLE, 'UTF-8');
        }

        return $title;
    }


    public function modify_document_title_parts($title_parts)
    {
        if (is_admin() || wp_doing_ajax()) {
            return $title_parts;
        }

        if (defined('REST_REQUEST') && REST_REQUEST) {
            return $title_parts;
        }

        if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false) {
            return $title_parts;
        }

        $separator  = get_option('seo_fury_title_separator', '—');
        $capitalize = get_option('seo_fury_title_capitalize', 0);

        $custom_title = '';

        if (is_front_page()) {
            // Per-post custom title takes priority over global template
            $front_post = get_post();
            if ($front_post) {
                $meta_title = get_post_meta($front_post->ID, '_seo_fury_title', true);
                if (!empty($meta_title)) {
                    $custom_title = $this->apply_template($meta_title, array_merge(
                        $this->get_context_replacements(),
                        $this->get_post_replacements($front_post)
                    ));
                }
            }
            // Fall back to global homepage template
            if ($custom_title === '') {
                $template = get_option('seo_fury_title_template_home', '');
                if ($template) {
                    $custom_title = $this->apply_template($template, $this->get_context_replacements());
                }
            }
        } elseif (is_home()) {
            $template = get_option('seo_fury_title_template_blog', '');
            if ($template) {
                $custom_title = $this->apply_template($template, $this->get_context_replacements());
            }
        } elseif (is_author()) {
            $template = get_option('seo_fury_title_template_author', '');
            if ($template) {
                $custom_title = $this->apply_template($template, $this->get_context_replacements());
            }
        } elseif (is_search()) {
            $template = get_option('seo_fury_title_template_search', '');
            if ($template) {
                $custom_title = $this->apply_template($template, $this->get_context_replacements());
            }
        } elseif (is_404()) {
            $template = get_option('seo_fury_title_template_404', '');
            if ($template) {
                $custom_title = $this->apply_template($template, $this->get_context_replacements());
            }
        } elseif (is_date()) {
            $template = get_option('seo_fury_title_template_date', '');
            if ($template) {
                $custom_title = $this->apply_template($template, $this->get_context_replacements());
            }
        } elseif (is_category() || is_tag() || is_tax()) {
            $term = get_queried_object();
            if ($term && !empty($term->taxonomy)) {
                $template = get_option('seo_fury_title_template_tax_' . $term->taxonomy, '');
                if ($template) {
                    $custom_title = $this->apply_template($template, $this->get_context_replacements());
                }
            }
        } elseif (is_post_type_archive()) {
            $post_type = get_query_var('post_type');
            if ($post_type) {
                $template = get_option('seo_fury_title_template_' . $post_type, '');
                if ($template) {
                    $custom_title = $this->apply_template($template, $this->get_context_replacements());
                }
            }
        } elseif (is_singular()) {
            $post = get_post();
            if ($post) {
                $meta_title = get_post_meta($post->ID, '_seo_fury_title', true);
                if (!$meta_title) {
                    $meta_title = get_option('seo_fury_title_template_' . $post->post_type, '');
                }
                if (!empty($meta_title)) {
                    $custom_title = $this->apply_template($meta_title, $this->get_post_replacements($post));
                }
            }
        }

        if ($custom_title !== '') {
            if ($capitalize) {
                $custom_title = mb_convert_case($custom_title, MB_CASE_TITLE, 'UTF-8');
            }
            return array('title' => $custom_title);
        }

        $site = isset($title_parts['site']) ? $title_parts['site'] : get_bloginfo('name');
        $page = isset($title_parts['title']) ? $title_parts['title'] : '';

        if ($page !== '') {
            $title = $page . ' ' . $separator . ' ' . $site;
        } else {
            $title = $site;
        }

        if ($capitalize) {
            $title = mb_convert_case($title, MB_CASE_TITLE, 'UTF-8');
        }

        return array(
            'title' => $title,
        );
    }
}
