<?php
/**
* Plugin Name: SearchShifter AI Visibility
* Plugin URI: https://searchshifter.ai
* Description: Generates structured configuration files and metadata to support AI crawler access and content interpretation.
* Version: 1.0.0
* Author: Thrivx.ai
* Author URI: https://searchshifter.ai
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: searchshifter
* Requires at least: 6.0
* Requires PHP: 8.1
* Tested up to: 6.9
*/

/**
 * SearchShifter AI Visibility is free software. You can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License or any later version.
 *
 * SearchShifter AI Visibility is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SearchShifter AI Visibility. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
 */

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

define('SEARCHSHIFTER_MIN_PHP', '8.1');
    if (version_compare(PHP_VERSION, '8.1', '<')) {

        add_action('admin_notices', function () {
            ?>
            <div class="notice notice-error">
                <p><strong>SearchShifter was not activated.</strong></p>
                <p>
                    This plugin requires <strong>PHP 8.1 or higher</strong>.<br>
                    Your site is currently running <strong><?php echo esc_html(PHP_VERSION); ?></strong>.
                </p>
                <p>No changes were made to your site.</p>
            </div>
            <?php
        });

        register_activation_hook(__FILE__, function () {
            deactivate_plugins(plugin_basename(__FILE__));
        });

        return; 
    }

    function searchshifter_get_current_plan() {
        if ( class_exists( 'SS_Licensing' ) ) {
            return strtolower( SS_Licensing::plan() );
        }
        return 'free';
    }

    // --------------------------------------------------
    // PLAN CHECK HELPER (DO NOT REMOVE)
    // --------------------------------------------------

    function searchshifter_has_plan( $required_plan ) {

        $levels = [
            'free'      => 1,
            'pro'       => 2,
            'authority' => 3,
            'elite'     => 4
        ];

        $current = searchshifter_get_current_plan();

        if ( ! isset($levels[$current]) || ! isset($levels[$required_plan]) ) {
            return false;
        }

        return $levels[$current] >= $levels[$required_plan];
    }


    // Legacy / internal alias
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_get_current_plan() {
        return searchshifter_get_current_plan();
    }


    function searchshifter_locked_field_message($required_plan = 'pro') {
        $link = 'https://searchshifter.ai/pricing/';

        echo '<div style="padding:10px;border:1px solid #ddd;background:#f9f9f9;border-radius:6px;margin-top:8px;">
                <strong>Locked Feature</strong><br>
                This feature require <strong>' . esc_html( ucfirst( $required_plan ) ) . '</strong> plan.<br>
                <a href="' . esc_url( $link ) . '" target="_blank" style="color:#2271b1;font-weight:600;">Upgrade Now →</a>
            </div>';
    }
    // Legacy alias (internal use)
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_locked_field_message( $required_plan = 'pro' ) {
        searchshifter_locked_field_message( $required_plan );
    }

    require_once __DIR__ . '/includes/class-ss-api.php';

    if ( searchshifter_has_plan('pro') && file_exists(__DIR__ . '/vendor/autoload.php') ) {
        require_once __DIR__ . '/vendor/autoload.php';
    }

    // === Disable Yoast + Astra schema on Glossary page ===
    add_action('init', function() {
        add_filter('wpseo_schema_needs_to_output', function($out) {
            $glossary_id = (int) get_option('ss_glossary_page_id');
            if ($glossary_id && function_exists('is_page') && is_page($glossary_id))
            return false;
                    return $out;
        }, 1);
        // remove Astra theme schema
        add_action('template_redirect', function() {
            if (is_page(1978)) remove_action('astra_head', 'astra_add_schema');
        });
    }, 1);

    add_action( 'admin_init', function () {

        if ( ! is_admin() ) {
            return;
        }

        if (
            empty( $_POST['ss_export_csv_scanner'] ) ||
            ! isset( $_POST['ss_export_csv_nonce'] ) ||
            ! check_admin_referer( 'ss_export_csv', 'ss_export_csv_nonce' )
        ) {
            return;
        }

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_die( 'Unauthorized' );
        }

        global $wpdb;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $rows = $wpdb->get_results(
            "SELECT id, url, status, log, finished_at
            FROM {$wpdb->prefix}ss_scans"
        );

        if ( empty( $rows ) ) {
            wp_die( esc_html__( 'No data found to export.', 'searchshifter' ) );
        }

        if ( ob_get_length() ) {
            ob_end_clean();
        }

        header( 'Content-Type: text/csv; charset=utf-8' );
        header( 'Content-Disposition: attachment; filename=scanner-report.csv' );
        header( 'Pragma: no-cache' );
        header( 'Expires: 0' );

        $output = fopen( 'php://output', 'w' );
        fputcsv( $output, [ 'ID', 'URL', 'Status', 'Log', 'Finished At' ] );

        foreach ( $rows as $r ) {
            fputcsv(
                $output,
                [
                    $r->id,
                    $r->url,
                    $r->status,
                    wp_strip_all_tags( substr( (string) $r->log, 0, 200 ) ),
                    $r->finished_at,
                ]
            );
        }

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Closing php://output stream is required.
        fclose( $output );
        exit;
    });


    add_action( 'admin_init', 'searchshifter_handle_authority_import', 1 );
    function searchshifter_handle_authority_import() {

        if (
            ! isset( $_GET['ss_import_authority'], $_GET['_wpnonce'] ) ||
            ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'ss_import_authority' )
        ) {
            return;
        }

        $file = WP_CONTENT_DIR . '/uploads/searchshifter/authority_glossary.json';
        if (!file_exists($file)) {
            wp_die("authority_glossary.json not found");
        }

        $json = file_get_contents($file);
        $terms = json_decode($json, true);

        foreach ($terms as $t) {
            if (empty($t['term']) || empty($t['definition'])) continue;

            $title = sanitize_text_field($t['term']);
            $definition = wp_kses_post($t['definition']);
            $same_as = esc_url_raw($t['same_as'] ?? '');

            // 🔁 Replacement for get_page_by_title()
            $query = new WP_Query(
                [
                    'post_type'      => 'ss_glossary',
                    'post_status'    => 'any',
                    'title'          => $title,
                    'posts_per_page' => 1,
                    'no_found_rows'  => true,
                ]
            );

            $existing = $query->posts[0] ?? null;

            if ($existing) {
                wp_update_post([
                    'ID' => $existing->ID,
                    'post_content' => $definition,
                ]);

                if ($same_as) update_post_meta($existing->ID, 'ss_same_as', $same_as);
                continue;
            }

            $id = wp_insert_post([
                'post_title' => $title,
                'post_content' => $definition,
                'post_type' => 'ss_glossary',
                'post_status' => 'publish',
            ]);

            if ($id && $same_as) update_post_meta($id, 'ss_same_as', $same_as);
        }

        wp_safe_redirect(admin_url('edit.php?post_type=ss_glossary&imported=1'));
        exit;
    }
    // Legacy alias
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_handle_authority_import() {
        searchshifter_handle_authority_import();
    }


    /**
     * Multisite activation control — only Pro+ licenses can network activate.
     * Runs early so WordPress doesn't mark plugin as "single-site only".
     */
    add_action('muplugins_loaded', function() {
        if ( ! is_multisite() || ! is_network_admin() ) {
            return;
        }

        // Load licensing system early
        require_once plugin_dir_path(__FILE__) . 'includes/licensing.php';

        if ( ! class_exists('SS_Licensing') ) {
            return;
        }

        $license = SS_Licensing::get_cached_status();
        $plan    = strtolower($license['plan'] ?? 'free');

        // ✅ Allow Pro+ plans
        if ( in_array($plan, ['pro', 'authority', 'elite'], true) ) {
            return; // Allowed
        }

        // 🚫 Block Free plan
        deactivate_plugins( plugin_basename(__FILE__), true );
        wp_die(
            '<h2>🔒 SearchShifter Multisite is a Pro Feature</h2>
            <p>This plugin cannot be network-activated on a Free plan.</p>
            <p>Please activate it individually per site or upgrade to <strong>Pro</strong>.</p>',
            'Network Activation Blocked',
            ['back_link' => true]
        );
    }, 5);

    define( 'SEARCHSHIFTER_VERSION', '1.12.0' );
    define( 'SEARCHSHIFTER_PLUGIN_FILE', __FILE__ );
    define( 'SEARCHSHIFTER_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    define( 'SEARCHSHIFTER_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    define(
    'SEARCHSHIFTER_HUB_API',
    'https://phplaravel-1558676-6047273.cloudwaysapps.com'
    );
    // Thin client defaults (overridable via filters)
    // define('SEARCHSHIFTER_API_BASE', apply_filters('searchshifter/api_base', 'https://api.thrivx.ai'));
    define(
        'SEARCHSHIFTER_API_BASE',
            'https://phplaravel-1558676-6047273.cloudwaysapps.com'
    );

    define('SEARCHSHIFTER_APP_ORIGIN', apply_filters('searchshifter/app_origin', 'https://pilot.thrivx.ai'));
    define('SEARCHSHIFTER_BASENAME', plugin_basename(__FILE__));


    register_activation_hook(__FILE__, function () {

    if (!get_option('ss_site_uuid')) {
        update_option('ss_site_uuid', wp_generate_uuid4());
    }

    });

    // Simple autoloader (legacy SS_* and namespaced SS\* classes)
    spl_autoload_register(function ($class) {
        // Legacy: SS_Foo => includes/foo.php
        if (strpos($class, 'SS_') === 0) {
            $file = SEARCHSHIFTER_PLUGIN_DIR . 'includes/' . strtolower(str_replace('SS_', '', $class)) . '.php';
            if (file_exists($file)) { require_once $file; }
            return;
        }
        // New: SS\Core\Foo => includes/Core/Foo.php
        if (strpos($class, 'SS\\') === 0) {
            $rel = str_replace('\\', '/', substr($class, 3));
            $file = SEARCHSHIFTER_PLUGIN_DIR . 'includes/' . $rel . '.php';
            if (file_exists($file)) { require_once $file; }
            return;
        }
    });
    // --- SAFETY GUARD: prevent job-runner queries on Free plan ---
    add_filter('query', function($query) {
        global $wpdb;

        if (
            stripos( $query, 'SHOW FULL COLUMNS FROM' ) !== false &&
            stripos( $query, $wpdb->prefix . 'ss_jobs' ) !== false
        ) {

            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            if ( ! $wpdb->get_var(
                "SHOW TABLES LIKE '{$wpdb->prefix}ss_jobs'"
            ) ) {
                return ''; // prevent the query entirely
            }
        }

        return $query;
    });
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/class-ss-export.php';
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/schema-glossary.php';
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/schema-faq.php';
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/class-ss-free-features.php';
    SS_Free_Features::init();
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/glossary-admin.php';
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/glossary-runs.php';
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/auto-link.php';
    require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/rebuild-glossary.php';

    // Init core
    add_action( 'plugins_loaded', function() {
        SS_Setup::init();

        require_once SEARCHSHIFTER_PLUGIN_DIR . 'includes/Core/shortcodes.php';
            // Telemetry diagnostics page (autoloads from includes/telemetry_diagnostics.php)
            if ( class_exists('SS_Telemetry_Diagnostics') ) {
                SS_Telemetry_Diagnostics::init();
            }
            if (class_exists('SS_QA_Admin_UI')) { SS_QA_Admin_UI::init(); }
            if (is_admin()) {
                if (class_exists('SS_AdminAssets')) SS_AdminAssets::init();
                if (class_exists('SS_Ajax'))        SS_Ajax::init();

            }
     
        // do_action('ss_run_jobs_event');
            global $wpdb;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}ss_jobs'" ) ) {

            /**
             * Fires when SearchShifter jobs should run.
             *
             * @since 1.0.0
             */
            do_action( 'searchshifter_run_jobs_event' );

            // Legacy hook for backward compatibility.
            // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
            do_action( 'ss_run_jobs_event' );
        }



    });
    // Flush/ingest telemetry at end of request (non-blocking)
    add_action('shutdown', function () {
        if (class_exists('SearchShifter\\Core\\Telemetry')) {
            SearchShifter\Core\Telemetry::onShutdown();
        }
    });
    
    register_activation_hook(__FILE__, function () {
        searchshifter_register_site_with_hub();
    });

    // Registers site with external hub ONLY on plugin activation for Authority plan.
    function searchshifter_register_site_with_hub() {


        $existing = get_option('ss_api_token');
        if ($existing) {
            return; // already registered, do nothing
        }


        $uuid = get_option('ss_site_uuid');
        if (!$uuid) {
            return;
        }

        $response = wp_remote_post(
            SEARCHSHIFTER_HUB_API . '/register-site',
            [
                'timeout' => 10,
                'headers' => [
                    'Content-Type' => 'application/json',
                ],
                'body' => wp_json_encode([
                    'site_uuid' => $uuid,
                    'domain'    => wp_parse_url(home_url(), PHP_URL_HOST),
                ]),
            ]
        );

        if (is_wp_error($response)) {
           
            return;
        }

        


                if (is_wp_error($response)) {
                    return;
                }

        $data = json_decode(wp_remote_retrieve_body($response), true);

      

        $token = $data['token'] ?? $data['api_token'] ?? null;

    


        if ($token) {
            update_option('ss_api_token', sanitize_text_field($token));
        }

    }
    // Legacy alias (internal/backward compatibility)
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_register_site_with_hub() {
        searchshifter_register_site_with_hub();
    }

    register_activation_hook(__FILE__, 'searchshifter_prevent_network_activation');
    function searchshifter_prevent_network_activation($network_wide) {
        if ($network_wide) {
            deactivate_plugins(plugin_basename(__FILE__));
            wp_die(
                'SearchShifter cannot be network-activated on multisite installations. 
                Please activate it on each site individually to validate licenses.',
                'Network Activation Blocked',
                ['back_link' => true]
            );
        }
    }
    // Legacy alias (backward compatibility)
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_prevent_network_activation( $network_wide ) {
        searchshifter_prevent_network_activation( $network_wide );
    }
    /**
     * Install SearchShifter MU-Plugin bridge on activation
     */
    register_activation_hook(__FILE__, 'searchshifter_install_mu_bridge');
    function searchshifter_install_mu_bridge() {

        global $wp_filesystem;

        // Load filesystem API
        if ( ! function_exists('WP_Filesystem') ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        // Initialize filesystem
        WP_Filesystem();

        // If filesystem still not available, fail gracefully
        if ( ! $wp_filesystem ) {
            update_option('ss_mu_bridge_failed', 'filesystem_unavailable');
            return;
        }

        $mu_dir  = WP_CONTENT_DIR . '/mu-plugins';
        $mu_file = $mu_dir . '/searchshifter-bridge.php';

        // Create mu-plugins directory if missing
        if ( ! file_exists($mu_dir) ) {
            wp_mkdir_p($mu_dir);
        }

        // If already installed, do nothing
        if ( file_exists($mu_file) ) {
            return;
        }

        $code = "<?php
            /**
             * Plugin Name: SearchShifter System Bridge
             * Description: Internal SearchShifter bridge (auto-generated).
             */

            add_action('user_register', function (\$user_id) {
                update_user_meta(\$user_id, '_ss_registered', 1);
                update_user_meta(\$user_id, '_ss_registered_at', current_time('mysql'));
            });

            add_action('wp_login', function (\$user_login, \$user) {
                update_user_meta(\$user->ID, '_ss_last_login', current_time('mysql'));
            }, 10, 2);
            ";

        $written = $wp_filesystem->put_contents(
            $mu_file,
            $code,
            FS_CHMOD_FILE
        );

        if ( ! $written ) {
            update_option('ss_mu_bridge_failed', 'write_failed');
        }
    }
    // Legacy alias (backward compatibility)
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_install_mu_bridge() {
        searchshifter_install_mu_bridge();
    }

    // Activation / Deactivation hooks
    register_activation_hook( __FILE__, [ 'SS_Setup', 'activate' ] );
    register_deactivation_hook( __FILE__, [ 'SS_Setup', 'deactivate' ] );

    register_activation_hook(__FILE__, function () {
        global $wpdb;

        // --- 1. Create visibility scans table ---
        $table   = $wpdb->prefix . 'ss_visibility_scans';
        $charset = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE IF NOT EXISTS `$table` (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            url TEXT NOT NULL,
            score INT DEFAULT 0,
            issues TEXT,
            overview_flag TINYINT(1) DEFAULT 0,
            date_scanned DATETIME DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset;";

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        dbDelta($sql);

        // --- 2. Clear old LightChecker caches ---
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            "DELETE FROM {$wpdb->options}
            WHERE option_name LIKE '_transient_ss_light_%'
            OR option_name LIKE '_transient_timeout_ss_light_%'"
        );

        delete_option('ss_light_version');

        // --- 3. Optional log entry for debugging ---
        if (defined('WP_DEBUG') && WP_DEBUG) {

        }
    });
    // ---------- Ensure scanner & core tables exist (safe, idempotent) ----------
    if (!function_exists('searchshifter_ensure_core_tables')) {
        function searchshifter_ensure_core_tables() {
            global $wpdb;
            $charset = $wpdb->get_charset_collate();

            // Table names
            $tables = [
                'ss_scans' => "
                    CREATE TABLE {$wpdb->prefix}ss_scans (
                        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
                        url TEXT NOT NULL,
                        status VARCHAR(20) NOT NULL DEFAULT 'queued',
                        log LONGTEXT NULL,
                        attempts INT NOT NULL DEFAULT 0,
                        score INT NULL,
                        finished_at DATETIME NULL,
                        started_at DATETIME NULL,
                        created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                        PRIMARY KEY (id)
                    ) $charset;",

                // optional safe helper tables (create if you need)
                'ss_jobs' => "
                    CREATE TABLE {$wpdb->prefix}ss_jobs (
                        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
                        type VARCHAR(100) NULL,
                        payload LONGTEXT NULL,
                        status VARCHAR(20) NOT NULL DEFAULT 'queued',
                        attempts INT NOT NULL DEFAULT 0,
                        last_error TEXT NULL,
                        created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                        PRIMARY KEY (id)
                    ) $charset;"
            ];

            require_once ABSPATH . 'wp-admin/includes/upgrade.php';

            foreach ( $tables as $name => $sql ) {

                $full = $wpdb->prefix . $name;

                // Schema existence check (uncached by design)
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $table_exists = $wpdb->get_var(
                    $wpdb->prepare(
                        'SHOW TABLES LIKE %s',
                        $full
                    )
                );

                if ( $table_exists !== $full ) {

                    dbDelta( $sql );

                    if ( is_admin() && current_user_can( 'manage_options' ) ) {
                        add_action(
                            'admin_notices',
                            function () use ( $full ) {
                                echo '<div class="notice notice-success is-dismissible"><p>'
                                    . esc_html__(
                                        'SearchShifter: Table created or ensured:',
                                        'searchshifter'
                                    )
                                    . ' <code>' . esc_html( $full ) . '</code></p></div>';
                            }
                        );
                    }
                }
            }

        }
    }

    // Run on activation to be extra safe
    register_activation_hook(__FILE__, 'searchshifter_ensure_core_tables');

    // Legacy alias (backward compatibility)
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_ensure_core_tables() {
        searchshifter_ensure_core_tables();
    }


    // Also ensure tables on admin_init (useful if activation failed during install)
    add_action('admin_init', function() {
        if (! current_user_can('manage_options')) return;
        ss_ensure_core_tables();
    });


    add_action(
        'admin_init',
        function () {

            if ( ! current_user_can( 'manage_options' ) ) {
                return;
            }

            if (
                ! isset( $_GET['ss_force_create_tables'], $_GET['_wpnonce'] ) ||
                '1' !== $_GET['ss_force_create_tables'] ||
                ! wp_verify_nonce(
                    sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ),
                    'ss_force_create_tables'
                )
            ) {
                return;
            }

            ss_ensure_core_tables();

            // Redirect to remove query args
            wp_safe_redirect(
                remove_query_arg(
                    [ 'ss_force_create_tables', '_wpnonce' ]
                )
            );
            exit;
        }
    );


    // --- Add "Upgrade to Pro" button next to Deactivate ---
    add_filter('plugin_action_links_' . plugin_basename(__FILE__), function ($links) {

        $upgrade_link = '<a 
            href="' . esc_url('https://searchshifter.ai/pricing/') . '" 
            target="_blank"
            style="
                background:#0073aa;
                color:#fff;
                padding:3px 10px;
                border-radius:3px;
                font-weight:600;
                text-decoration:none;
            ">
            ' . esc_html__('Upgrade to Pro', 'searchshifter') . '
        </a>';

        if (class_exists('SS_Licensing')) {
            $license = SS_Licensing::get_cached_status();
            $plan = strtolower($license['plan'] ?? 'free');

            // Only show for Free plan
            if (!in_array($plan, ['pro', 'authority', 'elite'], true)) {
                $links[] = $upgrade_link;
            }
        } else {
            // Fallback if licensing not loaded
            $links[] = $upgrade_link;
        }

        return $links;
    });


    if (class_exists('SearchShifter\\Core\\SyncEngine')) {
        SearchShifter\Core\SyncEngine::init();
    }
    add_action('admin_notices', function() {
        if (!class_exists('SS_Licensing')) return;
        $license = SS_Licensing::get_cached_status();
        $plan = strtolower($license['plan'] ?? 'free');

        if (!in_array($plan, ['pro', 'authority', 'elite'], true)) {
            echo '<div class="notice notice-warning is-dismissible">
                <p><strong>🔒 Smart Sync Engine is a Pro feature.</strong><br>
                Upgrade to <a href="https://searchshifter.ai/pricing/" target="_blank">Pro</a> 
                to enable automatic llms.txt, ai.txt, and schema syncing.</p>
            </div>';
        }
    });


    add_action(
        'admin_notices',
        function () {

            if (
                empty( $_GET['scanner_table_created'] ) ||
                empty( $_GET['_wpnonce'] ) ||
                ! wp_verify_nonce(
                    sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ),
                    'scanner_table_notice'
                )
            ) {
                return;
            }

            $created = sanitize_text_field(
                wp_unslash( $_GET['scanner_table_created'] )
            );

            if ( '1' === $created ) {
                echo '<div class="notice notice-success is-dismissible"><p>✅ Table ss_scans created successfully.</p></div>';
            } else {
                echo '<div class="notice notice-error is-dismissible"><p>❌ SS_Scanner class not found.</p></div>';
            }
        }
    );



    add_action('wp_footer', function () {
        if (class_exists('SS_Licensing')) {
            $plan = SS_Licensing::plan();
           echo '<script>
                window.searchShifterPlan = "' . esc_js(strtolower($plan)) . '";
            </script>';

        }
    });

    add_action('admin_head', function() {
        echo '<style>
            .ss-modal-open { overflow: hidden !important; }
            .ss-modal { z-index: 9999999 !important; position: fixed !important; }
            .ss-modal-content { animation: fadeIn 0.2s ease-in-out; }
        </style>';
    });

    /**
     * 🔒 Disable Yoast SEO schema on Glossary page (ID 414)
     * Ensures only SearchShifter JSON-LD remains.
     */
    add_action('wp', function() {
        $glossary_id = (int) get_option('ss_glossary_page_id');
        $govern = (bool) get_option(SS_Settings::OPT_SCHEMA_GOVERNOR, true);

        if ($glossary_id && is_page($glossary_id) && $govern) {
            add_filter('wpseo_json_ld_output', '__return_empty_array', 9999);
            add_filter('wpseo_schema_needs_to_output', '__return_false', 9999);
            remove_all_actions('wpseo_json_ld');
        }

    }, 1);

    /**
     * 🔒 FORCE disable all Yoast schema on Glossary page (ID 414)
     * Ensures ONLY SearchShifter JSON-LD remains.
     */
    add_action('template_redirect', function() {
        $glossary_id = (int) get_option('ss_glossary_page_id');
        $govern = (bool) get_option(SS_Settings::OPT_SCHEMA_GOVERNOR, true);

        if ($glossary_id && is_page($glossary_id) && $govern) {
            add_filter('wpseo_json_ld_output', '__return_empty_array', 9999);
            add_filter('wpseo_schema_needs_to_output', '__return_false', 9999);
            remove_all_actions('wpseo_json_ld');
        }

    }, 9999);
    // Disable Yoast + Astra schema on FAQ page
    /**
     * 🔒 Disable Yoast + Astra schema on FAQ page (dynamic)
     * Ensures only SearchShifter JSON-LD remains active.
     */
    add_action('template_redirect', function() {
        $faq_page_id = (int) get_option('ss_faq_page_id');
        $govern = (bool) get_option(SS_Settings::OPT_SCHEMA_GOVERNOR, true);

        if ($faq_page_id && is_page($faq_page_id) && $govern) {
            add_filter('wpseo_json_ld_output', '__return_empty_array', 9999);
            add_filter('wpseo_schema_needs_to_output', '__return_false', 9999);
            remove_all_actions('wpseo_json_ld');
        }

    }, 9999);

    // add_action('init', function() {
    //     $affected = get_posts([
    //         'post_type' => 'page',
    //         'numberposts' => -1,
    //         's' => '<script type="application/ld+json">'
    //     ]);

    //     foreach ($affected as $p) {
    //         $content = $p->post_content;
    //         // Remove any JSON-LD script block
    //         $clean = preg_replace('/<script type="application\/ld\+json">.*?<\/script>/is', '', $content);
            
    //         if ($clean !== $content) {
    //             wp_update_post([
    //                 'ID' => $p->ID,
    //                 'post_content' => $clean
    //             ]);

    //         }
    //     }
    // });

    add_action('wp', function () {

        if (!is_singular('ss_glossary')) return;

        $govern = (bool) get_option(SS_Settings::OPT_SCHEMA_GOVERNOR, true);

        // Only disable Yoast on SINGLE posts if governor toggle is ON
        if ($govern) {
            add_filter('wpseo_json_ld_output', '__return_empty_array', 9999);
            add_filter('wpseo_schema_needs_to_output', '__return_false', 9999);
            remove_all_actions('wpseo_json_ld');
            remove_all_actions('wpseo_head');
            add_filter('wpseo_frontend_presenters', '__return_empty_array', 9999);
        }
    });

    /**
     * 💣 DISABLE ELEMENTOR JSON-LD (WEBPAGE SCHEMA)
     */
    add_action('wp', function () {
        if (!is_singular('ss_glossary')) return;

        if (class_exists('\Elementor\Core\Frontend\Document')) {
            remove_action(
                'wp_head',
                [\Elementor\Core\Frontend\Document::class, 'print_json_ld_metadata'],
                1
            );
        }
    });
    /**
     * 💣 DISABLE ASTRA SCHEMA ON BLOG POSTS
     */
    add_action('wp', function () {
        if (!is_singular('ss_glossary')) return;

        // Core Astra schema killers
        remove_action('astra_head', 'astra_add_schema');
        add_filter('astra_json_ld_schema', '__return_empty_array', 9999);
    });
    // add_action('template_redirect', function() {
    //     ob_start('ss_breadcrumb_html_scanner');
    // });
    function searchshifter_breadcrumb_html_scanner( $html ) {

        global $searchshifter_breadcrumb_detected;

        // Do NOT strip tags — must read raw HTML
        $plain = strtolower( $html );

        $patterns = [
            '/home\s*>\s*/',
            '/home\s*&gt;\s*/',
            '/<nav[^>]*breadcrumb/i',
            '/breadcrumb/i',
            '/you are here/i',
        ];

        foreach ( $patterns as $pattern ) {
            if ( preg_match( $pattern, $plain ) ) {
                $searchshifter_breadcrumb_detected = true;
                break;
            }
        }

        return $html;
    }

    // Legacy alias (backward compatibility)
    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
    function ss_breadcrumb_html_scanner( $html ) {
        return searchshifter_breadcrumb_html_scanner( $html );
    }


    /**
     * DEBUG MODE — Show if breadcrumb detected
     * Prints a hidden HTML comment in page source
     */
    add_action('wp_footer', function () {
        if (!is_singular()) return;

        global $ss_breadcrumb_detected;

        if (!empty($ss_breadcrumb_detected)) {
            echo "\n<!-- SearchShifter Breadcrumb Debug: FOUND -->\n";
        } else {
            echo "\n<!-- SearchShifter Breadcrumb Debug: NOT FOUND -->\n";
        }
    });

    function searchshifter_generate_defined_term_set($terms_used) {
        if (empty($terms_used)) return null;

        return [
            "@type" => "DefinedTermSet",
            "@id"   => site_url('/glossary/') . "#definedtermset",
            "name"  => "Glossary Terms Used On This Page",
            "hasDefinedTerm" => array_map(function($term){
                return [
                    "@id" => site_url('/glossary/') . '#' . sanitize_title($term)
                ];
            }, $terms_used)
        ];
    }

    function searchshifter_generate_schema($post_id) {

        $schema = [
            "@context" => "https://schema.org",
            "@graph"   => []
        ];

        $post_type = get_post_type($post_id);

        /* ===============================================================
        * 1. ARTICLE (Regular blog posts)
        * ==============================================================*/
        if ($post_type === 'post') {
            $schema["@graph"][] = [
                "@type" => "Article",
                "@id"   => get_permalink($post_id) . "#article",
                "headline" => get_the_title($post_id),
                "url"      => get_permalink($post_id),
                "author"   => [
                    "@type" => "Person",
                    "name"  => get_the_author_meta('display_name'),
                    "url"   => get_author_posts_url(get_the_author_meta('ID'))
                ],
                "image" => get_the_post_thumbnail_url($post_id, 'full') ?: null,
                "datePublished" => get_the_date('c', $post_id),
                "dateModified"  => get_the_modified_date('c', $post_id),
                "inLanguage"    => get_bloginfo('language')
            ];
        }

        /* ===============================================================
        * 2. GLOSSARY TERM (Internal Linking Auto-Generated)
        * ==============================================================*/
        if ($post_type === 'ss_glossary') {

            $term      = get_the_title($post_id);
            $def       = get_post_meta($post_id, 'ss_definition', true);
            $related   = (array) get_post_meta($post_id, 'ss_related_terms', true);
            $video     = get_post_meta($post_id, 'ss_video_url', true);

            $plan      = ss_get_current_plan();

            $term_id   = get_permalink($post_id) . "#definedterm";

            $entry = [
                "@type" => "DefinedTerm",
                "@id"   => $term_id,
                "name"  => $term,
                "description" => $def,
                "url"  => get_permalink($post_id),
                "inDefinedTermSet" => site_url('/glossary/#definedtermset')
            ];

            // PRO / AUTHORITY → internal linking auto-created
           if (!empty($related) && searchshifter_has_plan('pro')){
                $entry["relatedLink"] = [];

                foreach ($related as $rid) {
                    if (!get_post_status($rid)) continue;

                    $entry["relatedLink"][] = [
                        "@type" => "DefinedTerm",
                        "name"  => get_the_title($rid),
                        "@id"   => get_permalink($rid) . "#definedterm"
                    ];
                }
            }

            // AUTHORITY → include video for multimodal signals
            if ($video && searchshifter_has_plan('authority')) {
                $entry["subjectOf"] = [
                    "@type" => "VideoObject",
                    "url"   => $video
                ];
            }

            $schema["@graph"][] = $entry;

            // Add DefinedTermSet
            $schema["@graph"][] = [
                "@type" => "DefinedTermSet",
                "@id"   => site_url('/glossary/#definedtermset'),
                "name"  => "SearchShifter Glossary",
                "url"   => site_url('/glossary/')
            ];
        }

        /* ===============================================================
        * 3. FAQ (if available)
        * ==============================================================*/
        if (function_exists('ss_get_faq_schema_for_post')) {
            $faq = ss_get_faq_schema_for_post($post_id);
            if (!empty($faq["mainEntity"])) {
                $schema["@graph"][] = [
                    "@type" => "FAQPage",
                    "@id"   => get_permalink($post_id) . "#faq",
                    "name"  => get_the_title($post_id) . " FAQ",
                    "mainEntity" => $faq["mainEntity"]
                ];
            }
        }

        return wp_json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
    }
    // Admin meta box for term-level plan flag
    add_action('add_meta_boxes', function() {

        if ( ! searchshifter_has_plan('authority') ) return;


        add_meta_box(
            'ss_plan_flag',
            'Term Plan Flag',
            function($post) {
                $flag = get_post_meta($post->ID, 'ss_plan_flag', true) ?: 'free';
                ?>
                <label for="ss_plan_flag">Plan required to unlock this term</label>
                <select id="ss_plan_flag" name="ss_plan_flag" style="width:100%;margin-top:6px;">
                    <option value="free" <?php selected($flag, 'free'); ?>>Free</option>
                    <option value="pro" <?php selected($flag, 'pro'); ?>>Pro</option>
                    <option value="authority" <?php selected($flag, 'authority'); ?>>Authority</option>
                </select>
                <p class="description">Controls public indicator + gating in the UI.</p>
                <?php
            },
            'ss_glossary',
            'side',
            'default'
        );
    });

    add_filter('wpseo_json_ld_output', function ($data) {
    if (is_singular('ss_glossary')) {
        return [];
    }
    return $data;
    }, 99);


    // add_action('wp_head', function () {

    //     if (!is_singular('ss_glossary')) return;

    //     global $post;

    //     $definition = get_post_meta($post->ID, 'ss_definition', true);
    //     if (empty($definition)) {
    //         $definition = wp_strip_all_tags($post->post_content);
    //     }

    //     $schema = [
    //         "@context" => "https://schema.org",
    //         "@type"    => "DefinedTerm",
    //         "@id"      => get_permalink($post->ID) . "#definedterm",
    //         "name"     => get_the_title($post),
    //         "description" => $definition,
    //         "url"      => get_permalink($post->ID),
    //         "inDefinedTermSet" => site_url('/glossary/#definedtermset')
    //     ];

    //     echo '<script type="application/ld+json">' .
    //         wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) .
    //         '</script>';
    // }, 20);


    /**
     * -------------------------------------------------------
     * UNIVERSAL AI PREVIEW META BOX FOR POSTS + PAGES + CPTs
     * -------------------------------------------------------
     */

    add_action('add_meta_boxes', function () {

        // Post types where preview should appear
        $post_types = ['post', 'page', 'ss_glossary', 'ss_qa'];

        foreach ($post_types as $pt) {
            add_meta_box(
                'ss_universal_schema_preview',
                'AI Preview (What Models See)',
                'searchshifter_render_universal_schema_preview',
                $pt,
                'side',
                'high'
            );
        }
    });


    /**
     * Render the preview meta box
     */
    function searchshifter_render_universal_schema_preview($post) {

        $schema = get_post_meta($post->ID, '_ss_schema_json', true);

        echo '<p><strong>Generated Schema:</strong></p>';

        echo '<textarea readonly rows="14" style="width:100%;font-family:monospace;background:#fafafa;border:1px solid #ccc;padding:10px;">';

        if ($schema) {
            echo esc_textarea($schema);
        } else {
            echo "⚠️ Schema not generated yet.\n\n";
            echo "👉 Please refresh the page after clicking Publish/Update.\n";
            echo "This will load the latest AI Preview schema.\n";
        }

        echo '</textarea>';

        echo '<p style="font-size:12px;color:#555;">AI Preview updates after page refresh due to Gutenberg limitations.</p>';
    }

    /**
     * Save schema JSON for posts & pages when they are updated
     */
    /**
     * Generate final schema AFTER publish (proper permalink & title)
     */
    add_action('transition_post_status', function($new, $old, $post) {
        
        if ($new !== 'publish') return;
        if (!in_array($post->post_type, ['post', 'page'])) return;

        // Important: ensure permalink + meta is ready
        $post_id = $post->ID;

        // Generate schema
        $json = searchshifter_generate_schema($post_id);

        // Save schema for preview
        update_post_meta($post_id, '_ss_schema_json', $json);

    }, 10, 3);

    add_action('init', 'searchshifter_register_glossary_cpt');
    function searchshifter_register_glossary_cpt() {

        $plan = ss_get_current_plan(); // free / pro / authority

        $labels = array(
            'name'               => __('Glossary', 'searchshifter'),
            'singular_name'      => __('Glossary Term', 'searchshifter'),
            'add_new'            => __('Add New Term', 'searchshifter'),
            'add_new_item'       => __('Add New Term', 'searchshifter'),
            'edit_item'          => __('Edit Term', 'searchshifter'),
            'new_item'           => __('New Term', 'searchshifter'),
            'view_item'          => __('View Term', 'searchshifter'),
            'search_items'       => __('Search Glossary Terms', 'searchshifter'),
            'not_found'          => __('No glossary terms found.', 'searchshifter'),
            'not_found_in_trash' => __('No glossary terms found in trash.', 'searchshifter'),
        );

        // Base args
        $args = array(
            'labels'        => $labels,
            'public'        => true,
            'has_archive'   => false,
            'show_in_rest'  => true, // required for editor fields
            'supports'      => array('title', 'editor', 'custom-fields'),
            'rewrite'       => array(
                'slug' => 'term',
                'with_front' => false
            )
        );

        register_post_type('ss_glossary', $args);

        // -------------------------------
        // FREE PLAN → HIDE SLUG EDITOR
        // -------------------------------
        if ( ! searchshifter_has_plan('pro') ) {
            add_filter('get_sample_permalink_html', '__return_empty_string', 99);
        }
    }
    add_action('load-post.php', 'searchshifter_enable_slug_editor');
    add_action('load-post-new.php', 'searchshifter_enable_slug_editor');

    function searchshifter_enable_slug_editor() {
        $plan = ss_get_current_plan();

        if (!in_array($plan, ['pro', 'authority', 'elite'])) return;

        // Re-enable slug editor for PRO+
        remove_filter('get_sample_permalink_html', '__return_empty_string', 99);
    }

    register_activation_hook(__FILE__, 'searchshifter_create_glossary_page');

    function searchshifter_create_glossary_page() {

        // Check if page already exists
        $existing = get_page_by_path('glossary');

        if ($existing) {
            update_option('ss_glossary_page_id', $existing->ID);
            return;
        }

        // Create Glossary Page
        $page_id = wp_insert_post([
            'post_title'     => 'Glossary',
            'post_name'      => 'glossary',
            'post_type'      => 'page',
            'post_status'    => 'publish',
            'post_content'   => '[searchshifter_glossary]'
        ]);

        if ($page_id && !is_wp_error($page_id)) {
            update_option('ss_glossary_page_id', $page_id);
        }
    }

    add_action('admin_init', 'searchshifter_migrate_glossary_to_cpt');
    function searchshifter_migrate_glossary_to_cpt() {

        // Run only once
        if (get_option('ss_glossary_migrated') == 'yes') {
            return;
        }

        $old_terms = get_option('ss_glossary_terms', []);

        if (empty($old_terms)) {
            update_option('ss_glossary_migrated', 'yes');
            return;
        }

        foreach ($old_terms as $item) {

            $title      = sanitize_text_field($item['term'] ?? '');
            $definition = sanitize_textarea_field($item['definition'] ?? '');
            $same_as    = esc_url_raw($item['same_as'] ?? '');

            if (!$title || !$definition) continue;

            // Insert as CPT post
            $post_id = wp_insert_post([
                'post_title'   => $title,
                'post_content' => $definition,
                'post_type'    => 'ss_glossary',
                'post_status'  => 'publish'
            ]);

            if ($post_id) {
                if (!empty($same_as)) {
                    update_post_meta($post_id, 'ss_same_as', $same_as);
                }
            }
        }

        // Mark migration complete
        update_option('ss_glossary_migrated', 'yes');
    }
    function searchshifter_build_schema_for_post($post_id) {

        ob_start();
        // This forces your wp_head schema block to run
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
        do_action( 'wp_head' );
        $html = ob_get_clean();

        // Extract only JSON-LD from the output
        if (preg_match('/<script type="application\/ld\+json">(.*?)<\/script>/is', $html, $m)) {
            return trim($m[1]);
        }

        return '';
    }

    function searchshifter_definition_box($post) {
        $value = get_post_meta($post->ID, 'ss_definition', true);
        echo '<textarea style="width:100%;height:120px;" name="ss_definition">'.esc_textarea($value).'</textarea>';
    }

    function searchshifter_why_matters_box($post) {
        $plan = ss_get_current_plan();
        $value = get_post_meta($post->ID, 'ss_why_matters', true);

        if ( ! searchshifter_has_plan('pro') ) {
                ?>
                <div class="ss-locked" data-required-plan="pro" data-feature="Why It Matters" role="button" tabindex="0">
                    <textarea disabled style="width:100%;height:120px;background:#eee;"><?php echo esc_textarea($value); ?></textarea>
                    <?php ss_locked_field_message('pro'); ?>
                </div>
                <?php
                return;
        }

        echo '<textarea style="width:100%;height:120px;" name="ss_why_matters">'.esc_textarea($value).'</textarea>';
    }

    function searchshifter_simple_example_box($post) {
        $plan = ss_get_current_plan();
        $value = get_post_meta($post->ID, 'ss_simple_example', true);

        if ( ! searchshifter_has_plan('pro') ) {
            ?>
            <div class="ss-locked" data-required-plan="pro" data-feature="Simple Example" role="button" tabindex="0">
                <textarea disabled style="width:100%;height:120px;background:#eee;"><?php echo esc_textarea($value); ?></textarea>
                <?php ss_locked_field_message('pro'); ?>
            </div>
            <?php
            return;
        }

        echo '<textarea style="width:100%;height:120px;" name="ss_simple_example">'.esc_textarea($value).'</textarea>';
    }

    add_filter('get_sample_permalink_html', function($html, $post_id) {

        if (ss_get_current_plan() === 'free' && get_post_type($post_id) === 'ss_glossary') {
            return ''; // Remove permalink and slug UI (classic)
        }
        return $html;
    }, 10, 2);

    add_filter('rest_prepare_ss_glossary', function($response, $post, $request) {

        if (ss_get_current_plan() === 'free') {
            // Remove the slug field from REST response
            if (isset($response->data['slug'])) {
                unset($response->data['slug']);
            }
            // Remove permalink UI fields
            unset($response->data['permalink_template']);
            unset($response->data['generated_slug']);
        }
        return $response;
    }, 10, 3);

    function searchshifter_related_terms_box($post) {

        $plan  = ss_get_current_plan();
        $saved = (array) get_post_meta($post->ID, 'ss_related_terms', true);

        // Lock for Free plan
        if ( ! searchshifter_has_plan('pro') ) {
            ?>
            <div class="ss-locked" data-required-plan="pro" data-feature="Related Terms" role="button" tabindex="0">
                <select disabled multiple style="width:100%;height:120px;background:#eee;">
                    <option><?php esc_html_e('Locked', 'searchshifter'); ?></option>
                </select>
                <?php ss_locked_field_message('pro'); ?>
            </div>
            <?php
            return;
        }

        // Fetch ALL glossary terms
        $terms = get_posts([
            'post_type'   => 'ss_glossary',
            'numberposts' => -1,
            'orderby'     => 'title',
            'order'       => 'ASC',
        ]);

        echo '<select name="ss_related_terms[]" multiple style="width:100%;height:140px;">';

        foreach ($terms as $t) {
            if ($t->ID == $post->ID) {
                continue; // Prevent assigning itself
            }

            echo '<option value="' . esc_attr($t->ID) . '" ' .
                selected(in_array($t->ID, $saved, true), true, false) . '>' .
                esc_html($t->post_title) .
            '</option>';
        }

        echo '</select>';

        echo '<p style="font-size:12px;color:#555;">' .
            esc_html__('Hold CTRL (Windows) or CMD (Mac) to select multiple.', 'searchshifter') .
        '</p>';
    }


    function searchshifter_video_url_box($post) {
        $plan = ss_get_current_plan();
        $value = get_post_meta($post->ID, 'ss_video_url', true);

       if ( ! searchshifter_has_plan('authority') ){
            echo '<input type="text" disabled style="width:100%;background:#eee;" value="'.esc_attr($value).'" />';
            ss_locked_field_message('authority');
            return;
        }

        echo '<input type="text" style="width:100%;" name="ss_video_url" placeholder="https://youtube.com/..." value="'.esc_attr($value).'" />';
    }


    function searchshifter_where_appears_box($post) {
        $plan = ss_get_current_plan();

        if ( ! searchshifter_has_plan('authority') )  {
            ?>
            <div class="ss-locked" data-required-plan="authority" data-feature="Where This Term Appears" role="button" tabindex="0">
                <p>This feature requires <strong>Authority</strong> plan.</p>
                <?php ss_locked_field_message('authority'); ?>
            </div>
            <?php
            return;
        }

        echo '<p>This will auto-generate list of pages where this term appears.</p>';
    }

    /**
     * Enqueue frontend CSS for Glossary
     */
    add_action('wp_enqueue_scripts', function () {

        // Load only on Glossary page
        $glossary_id = (int) get_option('ss_glossary_page_id');

        if ($glossary_id && is_page($glossary_id)) {

            wp_enqueue_style(
                'searchshifter-glossary',
                plugin_dir_url(__FILE__) . 'assets/css/searchshifter.css',
                [],
                SEARCHSHIFTER_VERSION
            );
        }
    });

    add_action('wp_enqueue_scripts', function() {
        if (is_singular('ss_glossary')) {
            wp_enqueue_style(
                'ss-glossary-style',
                plugins_url('assets/css/searchshifter.css', __FILE__),
                [],
                SEARCHSHIFTER_VERSION
            );
        }
    });

    add_filter('single_template', 'searchshifter_glossary_single_template');
    function searchshifter_glossary_single_template($template) {
        if (is_singular('ss_glossary')) {
            $custom = SEARCHSHIFTER_PLUGIN_DIR . 'includes/glossary-single.php';
            if (file_exists($custom)) return $custom;
        }
        return $template;
    }


    add_action('save_post_ss_glossary', function($post_id){

        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
        if (!current_user_can('edit_post', $post_id)) return;

        $fields = [
            'ss_definition',
            'ss_why_matters',
            'ss_simple_example',
            'ss_video_url',
            'ss_same_as'
        ];

        foreach ($fields as $field) {

            if (isset($_POST[$field])) {
                update_post_meta(
                    $post_id,
                    $field,
                    wp_kses_post($_POST[$field])
                );
            } else {
                delete_post_meta($post_id, $field);
            }
        }

        // Related terms
        if (isset($_POST['ss_related_terms'])) {
            $clean = array_map('intval', $_POST['ss_related_terms']);
            update_post_meta($post_id, 'ss_related_terms', $clean);
        } else {
            delete_post_meta($post_id, 'ss_related_terms');
        }

    });

    function searchshifter_same_as_box($post) {
        $value = get_post_meta($post->ID, 'ss_same_as', true);
        ?>
        <label for="ss_same_as"><strong>SameAs URL</strong></label>
        <input type="url" 
            id="ss_same_as" 
            name="ss_same_as" 
            value="<?php echo esc_attr($value); ?>" 
            placeholder="https://example.com/authoritative-source"
            style="width:100%; padding:8px; margin-top:5px;" />
        <p class="description">Add an external authoritative source (Google, Wikipedia, Schema.org, etc.).</p>
        <?php
    }

    add_action('add_meta_boxes', 'searchshifter_glossary_meta_boxes');
    function searchshifter_glossary_meta_boxes() {
        add_meta_box('ss_definition', 'Definition', 'searchshifter_definition_box', 'ss_glossary', 'normal', 'high');
        add_meta_box('ss_why_matters', 'Why it Matters', 'searchshifter_why_matters_box', 'ss_glossary', 'normal', 'default');
        add_meta_box('ss_simple_example', 'Simple Example', 'searchshifter_simple_example_box', 'ss_glossary', 'normal', 'default');
        add_meta_box(
            'ss_related_terms',
            'Related Terms',
            'searchshifter_related_terms_box',
            'ss_glossary',
            'normal',
            'default'
        );

        add_meta_box('ss_video_url', 'YouTube Video', 'searchshifter_video_url_box', 'ss_glossary', 'normal', 'default');
        add_meta_box('ss_where_appears', 'Where this term appears', 'searchshifter_where_appears_box', 'ss_glossary', 'normal', 'default');
        add_meta_box('ss_same_as', 'External Reference (SameAs URL)', 'searchshifter_same_as_box', 'ss_glossary', 'normal', 'default');

    }
    add_action('admin_enqueue_scripts', function($hook){

        global $post;

        // Only load on glossary edit pages
        if ($hook !== 'post.php' && $hook !== 'post-new.php') return;
        if (empty($post) || $post->post_type !== 'ss_glossary') return;

        // Only for PRO & Authority
        $plan = ss_get_current_plan();
        if (!in_array($plan, ['pro','authority','elite'])) return;

        // Collect glossary terms for click-to-link suggestion
        $terms = get_posts([
            'post_type' => 'ss_glossary',
            'posts_per_page' => -1
        ]);

        $list = [];
        foreach ($terms as $t) {
            $list[] = [
                'title' => $t->post_title,
                'url'   => get_permalink($t->ID)
            ];
        }

        wp_enqueue_script(
            'ss-related-linker',
            SEARCHSHIFTER_PLUGIN_URL . 'assets/js/related-term-linker.js',
            ['jquery'],
            SEARCHSHIFTER_VERSION,
            true
        );

        wp_localize_script('ss-related-linker', 'SS_RELATED_TERMS', $list);
    });

    add_filter('template_include', function($template) {

        if (is_post_type_archive('ss_glossary')) {
            $custom = SEARCHSHIFTER_PLUGIN_DIR . 'includes/archive-glossary.php';
            if (file_exists($custom)) return $custom;
        }

        return $template;
    });

    /* ----------------------------
    * Upgrade Popup: Enqueue & Render
    * ---------------------------- */

    add_action('wp_enqueue_scripts', 'searchshifter_upgrade_popup_assets');
    add_action('admin_enqueue_scripts', 'searchshifter_upgrade_popup_assets');

    function searchshifter_upgrade_popup_assets($hook = '') {
        // Only load site-wide on glossary pages & admin glossary screens
        // but allow loading everywhere if you want global display.
        $ver = defined('SEARCHSHIFTER_VERSION') ? SEARCHSHIFTER_VERSION : time();

        wp_register_style('ss-upgrade-popup', SEARCHSHIFTER_PLUGIN_URL . 'assets/css/ss-upgrade-popup.css', [], $ver);
        wp_register_script('ss-upgrade-popup', SEARCHSHIFTER_PLUGIN_URL . 'assets/js/ss-upgrade-popup.js', ['jquery'], $ver, true);

        // Localize strings / plan info
        $license = class_exists('SS_Licensing') ? SS_Licensing::get_cached_status() : [];
        $current_plan = strtolower($license['plan'] ?? 'free');

        $local = [
            'currentPlan' => $current_plan,
            'pricingUrl'  => 'https://searchshifter.ai/pricing/',
            'plans'       => [
                'free' => [
                    'name' => 'Free',
                    'benefits' => ['Term name & definition', 'A–Z index']
                ],
                'pro' => [
                    'name' => 'Pro',
                    'benefits' => ['Why it Matters', 'Simple Example', 'Related Terms (click-to-link)']
                ],
                'authority' => [
                    'name' => 'Authority',
                    'benefits' => ['Video embed', 'Where term appears auto-list', 'Authority dataset import']
                ]
            ],
            'i18n' => [
                'title' => __('This feature requires a higher plan', 'searchshifter'),
                'cta'   => __('Upgrade now', 'searchshifter'),
                'close' => __('Close', 'searchshifter'),
            ],
            'ajaxNonce' => wp_create_nonce('ss_upgrade_popup')
        ];

        wp_localize_script('ss-upgrade-popup', 'SS_UPGRADE', $local);

        wp_enqueue_style('ss-upgrade-popup');
        wp_enqueue_script('ss-upgrade-popup');
    }

    // Render modal markup in both admin_footer & wp_footer
    add_action('admin_footer', 'searchshifter_upgrade_modal_html');
    add_action('wp_footer', 'searchshifter_upgrade_modal_html');

    function searchshifter_upgrade_modal_html() {
        // Only print once
        static $printed = false;
        if ($printed) return;
        $printed = true;

        ?>
        <div id="ss-upgrade-modal" class="ss-upgrade-modal" aria-hidden="true" role="dialog" aria-modal="true">
            <div class="ss-upgrade-modal-backdrop" data-ss-close></div>
            <div class="ss-upgrade-modal-inner" role="document">
                <button class="ss-upgrade-close" type="button" aria-label="<?php esc_attr_e('Close', 'searchshifter'); ?>" data-ss-close>&times;</button>

                <div class="ss-upgrade-content">
                    <h2 class="ss-upgrade-title" id="ss-upgrade-title"></h2>
                    <p class="ss-upgrade-feature" id="ss-upgrade-feature"></p>

                    <div class="ss-upgrade-compare" id="ss-upgrade-compare">
                        <!-- JS fills comparison rows here -->
                    </div>

                    <div class="ss-upgrade-actions">
                        <a id="ss-upgrade-cta" class="ss-upgrade-cta" href="#" target="_blank" rel="noopener noreferrer">
                            <?php esc_html_e('Upgrade to Pro', 'searchshifter'); ?>
                        </a>
                        <button class="ss-upgrade-secondary" type="button" data-ss-close>
                            <?php esc_html_e('Close', 'searchshifter'); ?>
                        </button>
                    </div>
                </div>
            </div>
        </div>
        <?php
    }

    add_action('restrict_manage_posts', function() {
            global $typenow;

            if ($typenow !== 'ss_glossary') {
                return;
            }

            $plan = ss_get_current_plan();
            if ($plan !== 'authority') {
                return;
            }

            $url = admin_url('edit.php?post_type=ss_glossary&ss_import_authority=1');

            echo '<a href="' . esc_url($url) . '" 
                class="button button-primary" 
                style="margin-left:10px;margin-right:10px;">' .
                esc_html__('Import Authority Dataset', 'searchshifter') .
            '</a>';
        });


        add_action(
            'admin_notices',
            function () {

                if (
                    empty( $_GET['imported'] ) ||
                    empty( $_GET['_wpnonce'] ) ||
                    ! wp_verify_nonce(
                        sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ),
                        'ss_import_notice'
                    )
                ) {
                    return;
                }

                echo '<div class="notice notice-success is-dismissible"><p>'
                    . esc_html__( 'Authority Glossary Dataset Imported Successfully.', 'searchshifter' )
                    . '</p></div>';
            }
        );


        /**
         * Add "Plan" column to Glossary table
         */
        add_filter('manage_ss_glossary_posts_columns', function($columns) {
            $columns['ss_plan_flag'] = __('Plan', 'searchshifter');
            return $columns;
        });


        /**
         * Display Plan flag inside the Plan column
         */
        add_action('manage_ss_glossary_posts_custom_column', function($column, $post_id) {

            if ($column === 'ss_plan_flag') {

                // Correct meta key
            $flag = get_post_meta($post_id, 'ss_plan_flag', true);


                // Default system-level value
                if (!$flag) {
                    $flag = 'free';
                }

                // Colors for each plan
                $colors = [
                    'free'      => '#43a047', // green
                    'pro'       => '#1e88e5', // blue
                    'authority' => '#8e24aa'  // purple
                ];

                $color = isset($colors[$flag]) ? $colors[$flag] : '#999';

                echo '<span style="
                    display:inline-block;
                    width:14px;
                    height:14px;
                    border-radius:50%;
                    background:' . esc_attr( $color ) . ';
                    margin-left:6px;
                " title="' . esc_attr( 'Term Plan: ' . ucfirst( $flag ) ) . '"></span>';

            }
        }, 10, 2);

        /**
         * Authority-only: output a single clean JSON-LD block
         *  - Glossary archive => DefinedTermSet (hasDefinedTerm -> list of term @id)
         *  - Single term => DefinedTerm + inDefinedTermSet (single JSON-LD block)
         *  - Includes relatedLink and VideoObject when available
         *  - Emits ONLY for Authority plan
         */

        // add_action('wp_head', function() {
        //     // Only run for front-end pages
        //     if (is_admin()) return;

        //     // Check plan
        //     $plan = ss_get_current_plan(); // expects ss_get_current_plan() exists
        //     if ( ! searchshifter_has_plan('authority') ) return;

        //     // ---------- GLOSSARY ARCHIVE: DefinedTermSet with references to all terms ----------
        //     if (is_post_type_archive('ss_glossary') || is_page(get_option('ss_glossary_page_id'))) {

        //         $terms = get_posts([
        //             'post_type' => 'ss_glossary',
        //             'posts_per_page' => -1,
        //             'post_status' => 'publish',
        //             'orderby' => 'title',
        //             'order' => 'ASC'
        //         ]);

        //         if (empty($terms)) return;

        //         $hasDefinedTerm = [];
        //         foreach ($terms as $t) {
        //             $hasDefinedTerm[] = [
        //                 "@id" => get_permalink($t->ID) . "#definedterm"
        //             ];
        //         }

        //         $payload = [
        //             "@context" => "https://schema.org",
        //             "@graph" => [
        //                 [
        //                     "@type" => "DefinedTermSet",
        //                     "@id"   => site_url('/glossary/') . "#definedtermset",
        //                     "name"  => "SearchShifter Glossary",
        //                     "url"   => get_post_type_archive_link('ss_glossary') ?: site_url('/glossary/'),
        //                     "hasDefinedTerm" => $hasDefinedTerm
        //                 ]
        //             ]
        //         ];

        //         echo '<script type="application/ld+json">' . wp_json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . '</script>';
        //         return;
        //     }

        //     // ---------- SINGLE GLOSSARY TERM: emit single DefinedTerm + its DefinedTermSet ----------
        //     if (is_singular('ss_glossary')) {
        //         global $post;
        //         if (empty($post) || $post->post_status !== 'publish') return;

        //         $term_title = get_the_title($post->ID);
        //         // Prefer explicit definition meta, fallback to content
        //         $definition = get_post_meta($post->ID, 'ss_definition', true);
        //         if (empty(trim($definition))) {
        //             $definition = wp_strip_all_tags(get_post_field('post_content', $post->ID));
        //         }

        //         // Build DefinedTerm
        //         $termEntity = [
        //             "@type" => "DefinedTerm",
        //             "@id"   => get_permalink($post->ID) . "#definedterm",
        //             "name"  => $term_title,
        //             "description" => wp_strip_all_tags($definition),
        //             "url"   => get_permalink($post->ID),
        //             "inDefinedTermSet" => site_url('/glossary/') . "#definedtermset"
        //         ];

        //         // Related links (if any) — only include published targets
        //         $related = (array) get_post_meta($post->ID, 'ss_related_terms', true);
        //         $relatedLinks = [];
        //         if (!empty($related) && is_array($related)) {
        //             foreach ($related as $rid) {
        //                 if (get_post_status($rid) === 'publish') {
        //                     $relatedLinks[] = [
        //                         "@type" => "DefinedTerm",
        //                         "name"  => get_the_title($rid),
        //                         "@id"   => get_permalink($rid) . "#definedterm"
        //                     ];
        //                 }
        //             }
        //             if (!empty($relatedLinks)) {
        //                 $termEntity['relatedLink'] = $relatedLinks;
        //             }
        //         }

        //         // VideoObject for authority plan (if a proper URL is set)
        //         $video = get_post_meta($post->ID, 'ss_video_url', true);
        //         if (!empty($video)) {
        //             // accept either full embed URL or youtube watch/embed links
        //             $termEntity['subjectOf'] = [
        //                 "@type" => "VideoObject",
        //                 "url"   => esc_url_raw($video)
        //             ];
        //         }

        //         // Optional: include plan flag inside schema (non-standard but helpful)
        //         $termPlan = get_post_meta($post->ID, 'ss_plan_flag', true) ?: 'free';
        //         $termEntity['termPlan'] = $termPlan;

        //         // Build the DefinedTermSet ref (single object, referenced by the term)
        //         $definedSet = [
        //             "@type" => "DefinedTermSet",
        //             "@id"   => site_url('/glossary/') . "#definedtermset",
        //             "name"  => "SearchShifter Glossary",
        //             "url"   => get_post_type_archive_link('ss_glossary') ?: site_url('/glossary/')
        //         ];

        //         $payload = [
        //             "@context" => "https://schema.org",
        //             "@graph" => [
        //                 $termEntity,
        //                 $definedSet
        //             ]
        //         ];

        //         // Print exactly one JSON-LD block
        //         echo '<script type="application/ld+json">' . wp_json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . '</script>';
        //         return;
        //     }

        // });
        // Disable Yoast schema for glossary terms
        add_filter('wpseo_json_ld_output', function($data, $context) {
            if (is_singular('ss_glossary')) {
                return [];
            }
            return $data;
        }, 10, 2);

        // Disable RankMath schema for glossary terms
        add_filter( 'rank_math/json_ld', function( $data, $jsonld ) {
            if (is_singular('ss_glossary')) {
                return [];
            }
            return $data;
        }, 99, 2);

        // Disable Elementor default Article schema for glossary terms
        add_filter('elementor/frontend/section/should_render', function($should_render, $section) {
            if (is_singular('ss_glossary')) {
                remove_action('wp_head', 'elementor_schema');
            }
            return $should_render;
        }, 10, 2);
        add_filter('wpseo_json_ld_output', function($data) {

            if (is_singular('ss_glossary') || is_page('glossary')) {

                foreach ($data as $key => $schema) {

                    if (isset($schema['@type']) && $schema['@type'] === 'Article') {
                        unset($data[$key]);
                    }
                }
            }

            return $data;
        });

    


        // add_action('wp_head', function() {
        //     if ( ! searchshifter_has_plan('authority') ) return;
        //     if (get_post_type() !== 'ss_glossary') return;

        //     $post_id = get_the_ID();
        //     $video   = get_post_meta($post_id, 'ss_video_url', true);

        //     $schema = [
        //         "@context" => "https://schema.org",
        //         "@type" => "DefinedTerm",
        //         "name" => get_the_title(),
        //         "url" => get_permalink(),
        //         "multimodal" => [
        //             "video" => $video ?: null,
        //             "image" => get_the_post_thumbnail_url($post_id) ?: null
        //         ]
        //     ];

        //     echo '<script type="application/ld+json">'.json_encode($schema).'</script>';
        // });
        add_filter('the_content', function($content) {
            if ( ! searchshifter_has_plan('authority') ) return $content;
            if (get_post_type() !== 'ss_glossary') return $content;

            $brand = get_option('ss_brand_name', 'Your Brand');

            $reinforcement = "<p class='ss-brand-reinforce'>
                This term is part of {$brand}'s AI Visibility reinforcement system.
            </p>";

            return $content . $reinforcement;
        });

    //     add_action('admin_init', function () {
    //     if (!get_option('ss_api_token')) {
    //         update_option(
    //             'ss_api_token',
    //             'nRqjIE1tIFHXHqcEgn4KGov2I3OI46K2FKoGwEPYEuOdLI99dm6OCysG2hvmduw7'
    //         );
    //     }
    // });


    add_action('wp_footer', function () {
        if (!is_singular('ss_glossary')) return;
        ?>
        <script>
            document.addEventListener("DOMContentLoaded", function () {

                let html = document.body.innerText.toLowerCase();

                let patterns = [
                    "home >",
                    "home ›",
                    "home /",
                    "home→",
                    "breadcrumb",
                    "you are here"
                ];

                let found = false;

                patterns.forEach(p => {
                    if (html.includes(p.trim())) {
                        found = true;
                    }
                });

                document.cookie = "ss_breadcrumb_found=" + (found ? "1" : "0") + "; path=/";
            });
        </script>
        <?php
    });
