<?php
namespace BitFire;

use BitFire\Config as CFG;
use function ThreadFin\check_pro_ver;
use function ThreadFin\debug;
use function ThreadFin\ends_with;
use function ThreadFin\parse_ini;
use function ThreadFin\starts_with;

/* ---------- One-time include guard + platform guards ---------- */
if (defined('BitFire\\WAF_ROOT')) {
    user_error('BitFire startup.php already included');
    return;
}
if (PHP_VERSION_ID < 70400) {
    user_error('BitFire requires PHP >= 7.4 '.PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION.' found');
    return;
}
if (stripos(PHP_OS, 'win') === 0) {
    user_error('windows not supported');
    return;
}


const ASSERT = false;
const DS = DIRECTORY_SEPARATOR;
$GLOBALS['bf_s1'] = hrtime(true);

/* ---------- Define paths ---------- */

if (!defined('BitFire\WAF_ROOT')) {
    define('BitFire\WAF_ROOT', realpath(__DIR__) . DS);
    define('BitFire\BLOCK_DIR', \BitFire\WAF_ROOT . 'blocks');
    define('BitFire\WAF_SRC',  \BitFire\WAF_ROOT . 'src' . DS);
    define('BitFire\TYPE',     'WORDPRESS');
    define('ThreadFin\view\VIEW_ROOT', \BitFire\WAF_ROOT . 'views');
}




/* ---------- Small helpers (unit-testable) ---------- */

// PHP 7.4 polyfill matching PHP 8 behavior (empty needle => true)
if (!function_exists('str_ends_with')) {
    function str_ends_with($haystack, $needle): bool {
        $needle = (string)$needle;
        if ($needle === '') return true;
        if (!is_string($haystack)) $haystack = (string)$haystack;
        $n = strlen($needle);
        return $n <= strlen($haystack) && substr_compare($haystack, $needle, -$n) === 0;
    }
}
function str_starts_with_ci(string $s, string $prefix): bool {
    $lp = strlen($prefix); if ($lp === 0) return true;
    return strncasecmp($s, $prefix, $lp) === 0;
}
function has_wordpress_cookies(array $cookies): bool {
    foreach ($cookies as $name => $_) {
        if (strpos($name, 'wordpress_') === 0) return true; // fast + good enough
    }
    return false;
}
function request_path(): string {
    $raw = $_SERVER['REQUEST_URI'] ?? '/';
    $p = parse_url($raw, PHP_URL_PATH);
    return ($p === null || $p === '') ? '/' : $p;
}
function should_delay_load(string $path): bool {
    // exact pages
    foreach (DELAY_LOAD_SCRIPTS as $p) {
        if (str_ends_with($path, $p)) return true;
    }
    // prefixes
    foreach (DELAY_LOAD_PREFIX as $p) {
        if (str_starts_with_ci($path, $p)) return true;
    }
    return false;
}

/* ---------- Delay-load rules ---------- */

const DELAY_LOAD_SCRIPTS = ['/wp-login.php', '/xmlrpc.php', '/wp-signup.php'];
// FIXED: missing comma; must be two elements
const DELAY_LOAD_PREFIX  = ['/wp-json/', '/wp-admin/'];



/* ---------- Assertions on/off ---------- */

if (ASSERT) {
    if (PHP_VERSION_ID < 80300) { $prevAssert = @assert_options(ASSERT_ACTIVE, true); }
} else if (PHP_VERSION_ID < 80300) {
    $prevAssert = @assert_options(ASSERT_ACTIVE, 0);
}


/* ---------- Early blocking + bootstrap ---------- */

require_once __DIR__ . DS . 'ip_blocking.php';
require_once \BitFire\WAF_ROOT . 'error_handler.php';
require_once \BitFire\WAF_SRC  . 'const.php';
require_once \BitFire\WAF_SRC  . 'bitfire.php';

try {
    // serve bot placeholder image without hitting WP/app
    $uri = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?? '/';
    if (strpos($uri, '/bitfire') !== false && substr($uri, -5) === '.webp') {
        header('Content-Type: image/webp');
        header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + 3600));
        die(file_get_contents(\BitFire\WAF_ROOT . 'public/browsers/unknown_bot.webp'));
    }

    // load config + optional debug line
    $config = parse_ini();
    CFG::set($config);
    if (CFG::enabled('debug_file', false) || CFG::enabled('debug_header', false)) {
        debug('  --> bitfire %s [%s:%s] @%s',
            \BitFire\BITFIRE_SYM_VER,
            $_SERVER['REQUEST_METHOD'] ?? 'GET',
            substr($uri, 0, 80),
            date('D M j G:i:s')
        );
    }

    bitfire_init();

    // detect strong WP auth signal (2+ auth cookies with plausible length)
    $auth_cookies = array_filter($_COOKIE ?? [], static function ($val, $key) {
        return (strpos($key, 'wordpress_') === 0) && is_string($val) && strlen($val) > 64;
    }, ARRAY_FILTER_USE_BOTH);

    // Run early if not in WP or not clearly logged-in. This catches non php scripts
    // we will wait to run from the plugin if they are logged in or accessing admin code
    if (count($auth_cookies) < 2 && !starts_with($uri, '/wp-admin/')) {
        $bitfire = \BitFire\BitFire::get_instance();
        $bitfire->inspect(); // inspect() should be idempotent internally
    }

    // Optionally fetch/update pro build
    check_pro_ver(CFG::str('pro_key') ?? '');

} catch (\Throwable $e) {
    \BitFire\on_err($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
}

/* ---------- Timing + teardown ---------- */

// FIXED: parenthesize to actually accumulate
$GLOBALS['bf_t1'] = ($GLOBALS['bf_t1'] ?? 0) + ((hrtime(true) - $GLOBALS['bf_s1']) / 1e6);

// restore assert setting
if (ASSERT) {
    if (PHP_VERSION_ID < 80300) { @assert_options(ASSERT_ACTIVE, $prevAssert); }
}

// startup chaining
$autoload = CFG::str('auto_prepend_file');
if (!empty($autoload) && is_file($autoload)) {
    include $autoload;
}
