<?php
/**
* Plugin Name: SearchShifter AI Visibility
* Plugin URI: <https://searchshifter.ai>
* Description: Helps site owners understand and improve their visibility to AI systems.
* Version: 1.0.0
* Author: [Thrivx.ai](http://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.6
*/

/**
 * 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.
 */
// Load translations


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
    });

    // Prevent activation
    register_activation_hook(__FILE__, function () {
        deactivate_plugins(plugin_basename(__FILE__));
    });

    return; // ⛔ STOP plugin execution safely
}



function searchshifter_load_textdomain() {
    load_plugin_textdomain(
        'searchshifter',
        false,
        dirname(plugin_basename(__FILE__)) . '/languages'
    );
}
add_action('plugins_loaded', 'searchshifter_load_textdomain');

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

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

function ss_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 requires <strong>' . ucfirst($required_plan) . '</strong> plan.<br>
            <a href="'.$link.'" target="_blank" style="color:#2271b1;font-weight:600;">Upgrade Now →</a>
          </div>';
}

if (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);


// ---- CSV Export (runs before HTML output) ----
if (isset($_POST['ss_export_csv_scanner'])) {
    global $wpdb;
    $table = $wpdb->prefix . 'ss_scans'; // ✅ automatically becomes amc3_ss_scans

    $rows = $wpdb->get_results("SELECT id, url, status, log, finished_at FROM {$table}");

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

    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,
            substr(strip_tags($r->log), 0, 200),
            $r->finished_at
        ]);
    }

    fclose($output);
    exit;
}

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

    if (!isset($_GET['ss_import_authority'])) return;

    $file = SEARCHSHIFTER_PLUGIN_DIR . 'data/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'] ?? '');

        $existing = get_page_by_title($title, OBJECT, 'ss_glossary');

        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;
}


/**
 * 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);

/**
 * Prevent SearchShifter from being network-activated on multisite installs
 * unless the plan is Pro or higher.
 */
// if ( is_multisite() && is_network_admin() ) {

//     // Load licensing class early (direct include)
//     require_once plugin_dir_path(__FILE__) . 'includes/licensing.php';

//     // Fetch license status from cache or API
//     $license = SS_Licensing::get_cached_status();
//     $plan    = strtolower($license['plan'] ?? 'free');

//     // Only allow Pro / Authority / Elite
//     if ( ! in_array($plan, ['pro', 'authority', 'elite'], true) ) {
//         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.<br>
//              Please activate it individually per site or upgrade to <strong>Pro</strong>.</p>',
//             'Network Activation Blocked',
//             ['back_link' => true]
//         );
//     }
// }

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__ ) );
// Thin client defaults (overridable via filters)
define('SEARCHSHIFTER_API_BASE', apply_filters('searchshifter/api_base', 'https://api.thrivx.ai'));
define('SEARCHSHIFTER_APP_ORIGIN', apply_filters('searchshifter/app_origin', 'https://pilot.thrivx.ai'));
define('SEARCHSHIFTER_BASENAME', plugin_basename(__FILE__));

// 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) {
        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() {
    load_plugin_textdomain( 'searchshifter', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
    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();

    }
//     global $wpdb;
// if ($wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}ss_jobs'")) {
//     do_action('ss_run_jobs_event');
// }

// do_action('ss_run_jobs_event');
global $wpdb;
if ($wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}ss_jobs'")) {
    do_action('ss_run_jobs_event');
}

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

function ss_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]
        );
    }
}
/**
 * Install SearchShifter MU-Plugin bridge on activation
 */
register_activation_hook(__FILE__, 'ss_install_mu_bridge');

function ss_install_mu_bridge() {

    $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
<?php
/**
 * Plugin Name: SearchShifter System Bridge
 * Description: Internal SearchShifter bridge (auto-generated).
 */

// Capture user registration (works with ANY registration plugin)
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'));
});

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

PHP;

    if (is_writable($mu_dir)) {
    file_put_contents($mu_file, $code);
} else {
    update_option('ss_mu_bridge_failed', 1);
}

}

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

require_once plugin_dir_path(__FILE__) . 'includes/test-run.php';
// register_activation_hook(__FILE__, function () {
//     global $wpdb;
//     $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);
// });

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 ---
    $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) {
        error_log('[SearchShifter] LightChecker cache cleared and DB ensured on activation.');
    }
});
// ---------- Ensure scanner & core tables exist (safe, idempotent) ----------
if (!function_exists('ss_ensure_core_tables')) {
    function ss_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;
            // If table missing → create via dbDelta
            if ($wpdb->get_var( $wpdb->prepare("SHOW TABLES LIKE %s", $full) ) !== $full) {
                dbDelta($sql);
                // small debug/admin notice — only when in admin and current user can manage options
                if (is_admin() && current_user_can('manage_options')) {
                    add_action('admin_notices', function() use ($full) {
                        echo '<div class="notice notice-success is-dismissible"><p>SearchShifter: Table <code>' . esc_html($full) . '</code> created (or ensured).</p></div>';
                    });
                }
            }
        }
    }
}

// Run on activation to be extra safe
register_activation_hook(__FILE__, 'ss_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();
});

// Manual create link (you already have a create hook — this is a friendly duplicate)
add_action('admin_init', function() {
    if (! current_user_can('manage_options')) return;
    if (isset($_GET['ss_force_create_tables']) && $_GET['ss_force_create_tables'] === '1') {
        ss_ensure_core_tables();
        // redirect to remove query param
        wp_safe_redirect(remove_query_arg('ss_force_create_tables'));
        exit;
    }
});

// add_action('admin_menu', function () {
//     add_submenu_page(
//         'searchshifter',               // parent slug
//         'Visibility Scanner',          // page title
//         'Visibility Scanner',          // menu title
//         'manage_options',              // capability
//         'ss-visibility-scanner',       // slug
//         function () { include __DIR__ . '/includes/admin/visibility-results.php'; } // callback
//     );
// });
// --- Add "Upgrade to Pro" button next to Deactivate ---
add_filter('plugin_action_links_' . plugin_basename(__FILE__), function ($links) {
    // Check license plan before showing upgrade link
    if (class_exists('SS_Licensing')) {
        $license = SS_Licensing::get_cached_status();
        $plan = strtolower($license['plan'] ?? 'free');

        // Only show Upgrade button if it's Free plan
        if (!in_array($plan, ['pro', 'authority', 'elite'], true)) {
            $links[] = '<a href="https://searchshifter.ai/pricing/" target="_blank" 
                style="
                    background:#0073aa;
                    color:#fff;
                    padding:3px 10px;
                    border-radius:3px;
                    font-weight:600;
                    text-decoration:none;
                ">
                Upgrade&nbsp;to&nbsp;Pro
            </a>';
        }
    } else {
        // Fallback: if license class not loaded, show upgrade link
        $links[] = '<a href="https://searchshifter.ai/pricing/" target="_blank" 
            style="
                background:#0073aa;
                color:#fff;
                padding:3px 10px;
                border-radius:3px;
                font-weight:600;
                text-decoration:none;
            ">
            Upgrade&nbsp;to&nbsp;Pro
        </a>';
    }

    return $links;
});

if (class_exists('SS\\Core\\SyncEngine')) {
    SS\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>';
    }
});

// TEMP: Manual table creation trigger
add_action('admin_init', function() {
    if (isset($_GET['create_scanner_table']) && current_user_can('manage_options')) {
        if (class_exists('SS_Scanner')) {
            SS_Scanner::install();
            echo '<div class="updated"><p>✅ Table ss_scans created successfully.</p></div>';
        } else {
            echo '<div class="error"><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)).'"; console.log("🔑 SearchShifter Plan:", "'.$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
            ]);
            error_log("✅ Cleaned extra schema from post ID {$p->ID}");
        }
    }
});
/**
 * 💣 HARD DISABLE ALL YOAST SCHEMA ON SINGLE BLOG POSTS
 */
// add_action('wp', function () {

//     if (!is_single()) return;

//     // Disable ALL Yoast schema processors
//     add_filter('wpseo_json_ld_output', '__return_empty_array', 9999);
//     add_filter('wpseo_schema_needs_to_output', '__return_false', 9999);

//     // Remove Yoast schema presenters
//     remove_all_actions('wpseo_json_ld');
//     remove_all_actions('wpseo_head');
//     add_filter('wpseo_frontend_presenters', '__return_empty_array', 9999);
// });

add_action('wp', function () {

    if (!is_single()) 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_single()) 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_single()) 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 ss_breadcrumb_html_scanner($html) {
    global $ss_breadcrumb_detected;

    // FIX: 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 $p) {
        if (preg_match($p, $plain)) {
            $ss_breadcrumb_detected = true;
            break;
        }
    }

    return $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";
    }
});

/**
 * -------------------------------------------------------------
 * MAIN SEARCHSHIFTER SCHEMA INJECTOR (FINAL CLEAN VERSION)
 * -------------------------------------------------------------
 */


// function ss_get_glossary_terms_used_anywhere($post_id) {

//     $terms = get_option('ss_glossary_terms', []); 
//     if (empty($terms)) return [];

//     $found = [];

//     // Fetch main content + title + excerpt
//     $html = '';
//     $html .= ' ' . strip_tags(get_the_title($post_id));
//     $html .= ' ' . strip_tags(get_the_excerpt($post_id));
//     $html .= ' ' . strip_tags(apply_filters('the_content', get_post_field('post_content', $post_id)));

//     // Also include theme post meta (author/date line)
//     ob_start();
//     get_template_part('template-parts/post/meta'); // if exists
//     $html .= ' ' . strip_tags(ob_get_clean());

//     foreach ($terms as $t) {
//         $term = trim($t['term']);
//         if (!$term) continue;

//         if (stripos($html, $term) !== false) {
//             $found[] = [
//                 'term'       => $t['term'],
//                 'definition' => $t['definition'],
//                 'same_as'    => $t['same_as'] ?? ''
//             ];
//         }
//     }

//     return $found;
// }
function ss_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)
    ];
}
/**
 * Build SearchShifter Schema for any post id
 */
// function ss_generate_schema($post_id) {

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

//     // ARTICLE schema
//     if (get_post_type($post_id) === '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')
//         ];
//     }

//     // FAQ (if any)
//     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"]
//             ];
//         }
//     }

//     // Glossary
//     $content = strtolower(strip_tags(get_post_field('post_content', $post_id)));
//     $glossary = get_option('ss_glossary_terms', []);
//     $terms_used = [];

//     foreach ($glossary as $g) {
//         $term = strtolower($g['term']);
//         if ($term && strpos($content, $term) !== false) {
//             $schema["@graph"][] = [
//                 "@type" => "DefinedTerm",
//                 "@id"   => site_url('/glossary/#') . sanitize_title($g['term']),
//                 "name"  => $g['term'],
//                 "description" => $g['definition'],
//                 "inDefinedTermSet" => site_url('/glossary/#definedtermset')
//             ];
//             $terms_used[] = $g['term'];
//         }
//     }

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

//     return wp_json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
// }
function ss_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) && in_array($plan, ['pro','authority','elite'])) {
            $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 && $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() {

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

    // ❌ Hide this meta box for Free & Pro
    if ($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_action('wp_head', function () {
    // STOP schema on Glossary terms
    if (is_singular('ss_glossary')) return;

    if (!is_singular()) return;

    global $post;
    echo '<script type="application/ld+json">' .
        ss_generate_schema($post->ID) .
        '</script>';
});



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

//     global $post;

//     if (!is_singular() || !$post || !isset($post->ID)) return;

//     $post_id = $post->ID;

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

//     /* ---------------------------------------------------------
//      * 1. ARTICLE — Only for blog posts
//      * --------------------------------------------------------- */
//     if (is_single()) {
//         $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(),
//                 "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'),
//             "dateModified"  => get_the_modified_date('c'),
//             "inLanguage"    => get_bloginfo('language')
//         ];
//     }

//     /* ---------------------------------------------------------
//      * 2. FAQ — Extracted from ss-qa block
//      * --------------------------------------------------------- */
//     if (function_exists('ss_get_faq_schema_for_post')) {
//         $faq = ss_get_faq_schema_for_post($post_id);

//         if ($faq && !empty($faq["mainEntity"])) {
//             $schema["@graph"][] = [
//                 "@type" => "FAQPage",
//                 "@id"   => get_permalink($post_id) . "#faq",
//                 "name"  => get_the_title($post_id) . " - FAQ",
//                 "mainEntity" => $faq["mainEntity"]
//             ];
//         }
//     }

//     /* ---------------------------------------------------------
//      * 3. GLOSSARY TERMS (DefinedTerm + DefinedTermSet)
//      * --------------------------------------------------------- */
// $terms_used = [];

// $content_raw = strtolower(strip_tags(get_post_field('post_content', $post_id)));
// $glossary    = get_option('ss_glossary_terms', []);

// foreach ($glossary as $g) {
//     $term = strtolower(trim($g['term']));
//     if (!$term) continue;

//     // Only trigger if user wrote the glossary term manually in content
//     if (strpos($content_raw, $term) !== false) {

//         // Add single term entity
//         $schema["@graph"][] = [
//             "@type" => "DefinedTerm",
//             "@id"   => site_url('/glossary/') . '#' . sanitize_title($g['term']),
//             "name"  => $g['term'],
//             "description" => $g['definition'],
//             "inDefinedTermSet" => site_url('/glossary/#definedtermset')
//         ];

//         $terms_used[] = $g['term'];
//     }
// }

// // Add the DefinedTermSet once if we have terms
// if (!empty($terms_used)) {
//     $schema["@graph"][] = [
//         "@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)
//     ];
// }



//     /* ---------------------------------------------------------
//      * 4. BreadcrumbList — Automatic only if user wrote breadcrumbs
//      * --------------------------------------------------------- */
//  if (!empty($_COOKIE['ss_breadcrumb_found']) && $_COOKIE['ss_breadcrumb_found'] == "1") {

//     $schema["@graph"][] = [
//         "@type" => "BreadcrumbList",
//         "@id"   => get_permalink($post_id) . "#breadcrumb",
//         "itemListElement" => [
//             [
//                 "@type" => "ListItem",
//                 "position" => 1,
//                 "name" => "Home",
//                 "item" => home_url("/")
//             ],
//             [
//                 "@type" => "ListItem",
//                 "position" => 2,
//                 "name" => "Blog",
//                 "item" => home_url("/blog/")
//             ],
//             [
//                 "@type" => "ListItem",
//                 "position" => 3,
//                 "name" => get_the_title($post_id),
//                 "item" => get_permalink($post_id)
//             ]
//         ]
//     ];
// }


//     /* ---------------------------------------------------------
//      * 6. Output Clean JSON-LD — One Script Only
//      * --------------------------------------------------------- */
//     echo '<script type="application/ld+json">' .
//         wp_json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) .
//         '</script>';

// }, 9999);

/**
 * -------------------------------------------------------
 * 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)',
            'ss_render_universal_schema_preview',
            $pt,
            'side',
            'high'
        );
    }
});


/**
 * Render the preview meta box
 */
function ss_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 = ss_generate_schema($post_id);

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

}, 10, 3);

add_action('init', 'ss_register_glossary_cpt');
function ss_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 ($plan === 'free') {
        add_filter('get_sample_permalink_html', '__return_empty_string', 99);
    }
}
add_action('load-post.php', 'ss_glossary_enable_slug_editor');
add_action('load-post-new.php', 'ss_glossary_enable_slug_editor');

function ss_glossary_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__, 'ss_create_glossary_page');

function ss_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', 'ss_migrate_glossary_to_cpt');
function ss_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 ss_build_schema_for_post($post_id) {

    ob_start();
    // This forces your wp_head schema block to run
    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 ss_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 ss_why_matters_box($post) {
    $plan = ss_get_current_plan();
    $value = get_post_meta($post->ID, 'ss_why_matters', true);

    if ($plan === 'free') {
?>
<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 ss_simple_example_box($post) {
    $plan = ss_get_current_plan();
    $value = get_post_meta($post->ID, 'ss_simple_example', true);

    if ($plan === 'free') {
?>
<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 ss_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 ($plan === 'free') {
?>
<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>Locked</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

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

    echo '</select>';

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



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

    if ($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 ss_where_appears_box($post) {
    $plan = ss_get_current_plan();

    if ($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', 'ss_glossary_single_template');
function ss_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'
    ];

    // Save simple text/meta fields
    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);
        }
    }

    // Save related terms (array field)
    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');
    }

    // Save plan flag ONLY for Authority plan
$plan = ss_get_current_plan();
if ($plan === 'authority' && isset($_POST['ss_plan_flag'])) {
    update_post_meta($post_id, 'ss_plan_flag', sanitize_text_field($_POST['ss_plan_flag']));
}

});


function ss_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', 'ss_glossary_meta_boxes');
function ss_glossary_meta_boxes() {
    add_meta_box('ss_definition', 'Definition', 'ss_definition_box', 'ss_glossary', 'normal', 'high');
    add_meta_box('ss_why_matters', 'Why it Matters', 'ss_why_matters_box', 'ss_glossary', 'normal', 'default');
    add_meta_box('ss_simple_example', 'Simple Example', 'ss_simple_example_box', 'ss_glossary', 'normal', 'default');
add_meta_box(
    'ss_related_terms',
    'Related Terms',
    'ss_related_terms_box',
    'ss_glossary',
    'normal',
    'default'
);

    add_meta_box('ss_video_url', 'YouTube Video', 'ss_video_url_box', 'ss_glossary', 'normal', 'default');
    add_meta_box('ss_where_appears', 'Where this term appears', 'ss_where_appears_box', 'ss_glossary', 'normal', 'default');
    add_meta_box('ss_same_as', 'External Reference (SameAs URL)', 'ss_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', 'ss_enqueue_upgrade_popup_assets');
add_action('admin_enqueue_scripts', 'ss_enqueue_upgrade_popup_assets');

function ss_enqueue_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', 'ss_print_upgrade_modal_html');
add_action('wp_footer', 'ss_print_upgrade_modal_html');

function ss_print_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;

    echo '<a href="'.admin_url('edit.php?post_type=ss_glossary&ss_import_authority=1').'" 
             class="button button-primary" 
             style="margin-left:10px;margin-right:10px;">
             Import Authority Dataset
          </a>';
});

// add_action('admin_init', function() {
//     if (!isset($_GET['ss_import_authority'])) return;
//     // if (ss_get_current_plan() !== 'authority') return;

//     $json = file_get_contents(SEARCHSHIFTER_PLUGIN_DIR . 'data/authority_glossary.json');
//     $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 = isset($t['same_as']) ? esc_url_raw($t['same_as']) : '';

//     // Check if term already exists
//     $existing = get_page_by_title($title, OBJECT, 'ss_glossary');

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

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

//         continue;
//     }

//     // Insert new glossary term
//     $post_id = wp_insert_post([
//         'post_title' => $title,
//         'post_content' => $definition,
//         'post_type' => 'ss_glossary',
//         'post_status' => 'publish',
//     ]);

//     if ($post_id && $same_as) {
//         update_post_meta($post_id, 'ss_same_as', $same_as);
//     }
// }


//     wp_safe_redirect(admin_url('edit.php?post_type=ss_glossary&imported=1'));
//     exit;
// });
add_action('admin_notices', function() {
    if (isset($_GET['imported'])) {
        echo '<div class="notice notice-success"><p>
            Authority Glossary Dataset Imported Successfully.
        </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:' . $color . ';
            margin-left:6px;
        " title="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 ($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 (is_page('glossary')) {
        ob_start();
    }
}, 0);

add_action('wp_head', function() {
    if (is_page('glossary')) {
        $buffer = ob_get_clean();
        $buffer = preg_replace('/<script type="application\/ld\+json">\s*{\s*"@context":\s*"https:\/\/schema\.org",\s*"@graph":\s*\[\]\s*}\s*<\/script>/m', '', $buffer);
        echo $buffer;
    }
}, 999);
add_filter('the_content', function($content) {
    if (ss_get_current_plan() !== 'authority') return $content;

    // Auto-link FAQs → Finds glossary terms inside FAQ pages
    $terms = get_posts(['post_type' => 'ss_glossary', 'posts_per_page' => -1]);

    foreach ($terms as $t) {
        $term = preg_quote($t->post_title, '/');
        $url  = get_permalink($t->ID);

        $content = preg_replace(
            "/\b($term)\b/i",
            '<a href="'.$url.'" class="ss-auto-link">$1</a>',
            $content,
            1
        );
    }

    return $content;
});
add_filter('the_content', function($content) {
    if (ss_get_current_plan() !== 'authority') return $content;
    if (get_post_type() !== 'post') return $content;

    $terms = get_posts(['post_type' => 'ss_glossary', 'posts_per_page' => -1]);

    foreach ($terms as $t) {
        $term = preg_quote($t->post_title, '/');
        $url  = get_permalink($t->ID);

        $content = preg_replace(
            "/\b($term)\b/i",
            '<a href="'.$url.'" class="ss-auto-link-article">$1</a>',
            $content,
            1
        );
    }

    return $content;
});
add_filter('the_content', function($content) {
    if (ss_get_current_plan() !== 'authority') return $content;

    $terms = get_posts(['post_type' => 'ss_glossary', 'posts_per_page' => -1]);

    foreach ($terms as $t) {
        $term = preg_quote($t->post_title, '/');
        $url  = get_permalink($t->ID);

        $content = preg_replace(
            "/\b($term)\b/i",
            '<a href="'.$url.'" class="ss-auto-link-qa">$1</a>',
            $content
        );
    }

    return $content;
});
add_action('wp_head', function() {
    if (ss_get_current_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 (ss_get_current_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('template_redirect', function() {
//     if (is_singular('ss_glossary')) {
//         ob_start('ss_clean_single_glossary_schema');
//     }
// });

// function ss_clean_single_glossary_schema($html) {

//     // 1. Remove Yoast Article Schema
//     $html = preg_replace(
//         '/<script type="application\/ld\+json">[^<]*?"@type"\s*:\s*"Article"[^<]*?<\/script>/s',
//         '',
//         $html
//     );

//     // 2. Remove DefinedTermSet (should only appear on glossary archive)
//     $html = preg_replace(
//         '/<script type="application\/ld\+json">[^<]*?"@type"\s*:\s*"DefinedTermSet"[^<]*?<\/script>/s',
//         '',
//         $html
//     );

//     // 3. Remove old multimodal schema
//     $html = preg_replace(
//         '/<script type="application\/ld\+json">[^<]*?"multimodal"[^<]*?<\/script>/s',
//         '',
//         $html
//     );

//     // 4. Remove duplicate DefinedTerm (if more than 1 appears)
//     $html = preg_replace(
//         '/<script type="application\/ld\+json">[^<]*?"@type"\s*:\s*"DefinedTerm"[^<]*?"termPlan"[^<]*?<\/script>/s',
//         '',
//         $html,
//         1 // keeps the first one
//     );

//     return $html;
// }

add_action('wp_footer', function () {
    if (!is_single()) 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
});
