<?php
/**
 * Plugin Name:       WP SEO Next
 * Description:       Modular SEO suite: meta tags, Schema.org, sitemaps, audits, bulk tools, internal linking, and optional integrations (GSC/OpenAI).
 * Version: 0.75.31
 * Requires at least: 6.4
 * Requires PHP:      7.4
 * Author:            WP SEO Next
 * License:           GPL-2.0-or-later
 * Text Domain:       wp-seo-next
 */

defined('ABSPATH') || exit;

define('WPSN_VERSION', '0.75.31');

define('WPSN_PLUGIN_FILE', __FILE__);
define('WPSN_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WPSN_PLUGIN_URL', plugin_dir_url(__FILE__));

// Build flag (used for Free/Pro/Agency packaging).
//
// Packaging systems may inject build/constants.php into the release ZIP.
// That file can define WPSN_BUILD and related metadata without requiring the
// repository source to be edited per-build.
$wpsnBuildConstants = WPSN_PLUGIN_DIR . 'build/constants.php';
if (is_readable($wpsnBuildConstants)) {
    require_once $wpsnBuildConstants;
}

if (!defined('WPSN_BUILD')) {
    define('WPSN_BUILD', 'free');
}

// Polyfills for PHP < 8.
require_once WPSN_PLUGIN_DIR . 'src/Core/Compat.php';

require_once WPSN_PLUGIN_DIR . 'src/Core/Autoloader.php';
\WPSN\Core\Autoloader::register();


// Global AJAX gate (optional).
//
// If Performance → AJAX live mode is disabled, we proactively reject any
// wp-admin/admin-ajax.php requests that target WP SEO Next actions (wpsn_*).
// This protects shared hosting from accidental retry storms / 503 loops.
add_action('init', static function (): void {
    if (!defined('DOING_AJAX') || !DOING_AJAX) {
        return;
    }

    $action = isset($_REQUEST['action']) ? sanitize_key((string) wp_unslash($_REQUEST['action'])) : '';
    if ($action === '' || !\WPSN\Core\AjaxMode::isWpsnAjaxAction($action)) {
        return;
    }

    // If enabled, allow normal handlers.
    if (\WPSN\Core\AjaxMode::isEnabled(null)) {
        return;
    }

    if (function_exists('nocache_headers')) {
        nocache_headers();
    }

    wp_send_json_error([
        'message' => __('WP SEO Next AJAX is disabled in Performance modes. Use queue/direct mode instead.', 'wp-seo-next'),
        'action' => $action,
    ], 403);
    exit;
}, 0);

// Best-effort: keep the optional MU recovery helper up-to-date.
// This runs before the heavy plugin boot (plugins_loaded), so it still works
// even if a later module is broken.
try {
    if (class_exists('\\WPSN\\Core\\RecoveryHelper') && \WPSN\Core\RecoveryHelper::isInstalled()) {
        \WPSN\Core\RecoveryHelper::maybeUpdateMuPlugin();
    }
} catch (\Throwable $e) {
    // Never break site load because of recovery helper.
}

register_activation_hook(__FILE__, ['\\WPSN\\Core\\Lifecycle', 'activate']);
register_deactivation_hook(__FILE__, ['\\WPSN\\Core\\Lifecycle', 'deactivate']);

add_action('plugins_loaded', static function (): void {
    // Performance hardening: admin-ajax.php can be a hotspot on shared hosting.
    // If this is an unrelated admin-ajax request (heartbeat, etc.), avoid booting
    // the full plugin to reduce load and 503 errors.
    if (defined('DOING_AJAX') && DOING_AJAX) {
        $action = isset($_REQUEST['action']) ? sanitize_key((string) $_REQUEST['action']) : '';
        $isWpsn = \WPSN\Core\AjaxMode::isWpsnAjaxAction($action);

        // If AJAX live mode is OFF, reject WP SEO Next AJAX actions as early as possible.
        if ($isWpsn && !\WPSN\Core\AjaxMode::isEnabled(null)) {
            wp_send_json_error([
                'code' => 'wpsn_ajax_disabled',
                'message' => 'WP SEO Next: AJAX live mode is disabled. Use queue/direct mode instead.',
            ], 403);
            exit;
        }

        // Lite boot: skip full plugin init on unrelated admin-ajax requests.
        if (!$isWpsn && \WPSN\Core\AjaxMode::isLiteBootEnabled(null)) {
            return;
        }
    }

    // Boot plugin after WP is loaded.
    $plugin = new \WPSN\Core\Plugin();
    $plugin->register();
});
