<?php

/**
 * Fired when BitFire is uninstalled.
 *
 * @link       http://bitfire.co
 * @since      1.0.0
 *
 * @package    bitfire
 */

use function ThreadFin\contains;
use function ThreadFin\get_hidden_file;
use function ThreadFin\HTTP\http2;

use const BitFire\FILE_EX;
use const BitFire\INFO;

// If uninstall not called from WordPress, then exit.
if (! defined('WP_UNINSTALL_PLUGIN')) {
	exit;
}

// just in case...
if (isset($_REQUEST['slug'])) {
	$slug = trim($_REQUEST['slug']);
	if ($slug !== 'bitfire') {
		return;
	}
}


// make sure the user has at least admin credentials
if (function_exists("current_user_can") && !current_user_can("manage_options")) {
	die("Uninstalling requires administrative privileges.");
}
else if (!function_exists("current_user_can")) {
	die("WordPress error. Unable to determine user capabilities.");
}

if (!defined('BitFire\WAF_ROOT')) {
	define("BitFire\WAF_ROOT", __DIR__ . "/");
	define("BitFire\WAF_SRC", __DIR__ . "/src/");

	include_once \BitFire\WAF_SRC . 'const.php';
	include_once \BitFire\WAF_SRC . 'util.php';
	include_once \BitFire\WAF_SRC . 'bitfire.php';
	include_once \BitFire\WAF_SRC . 'server.php';
}

// uninstall any .htaccess file changes or user.ini changes we might have made, 
// remove wordfence-waf.php if in emulation mode
if (defined("\BitFire\WAF_ROOT") && defined("\BitFire\WAF_SRC")) {

	// make sure we don't delete if the auto prepend is still active!
	$file = ini_get("auto_prepend_file");
	if (!empty($file) && contains($file, "bitfire")) {
        $dr = $_SERVER['DOCUMENT_ROOT']??'';
		$removed = removeBitFireBlock($dr . '/.user.ini');
		$seconds = -1; // some servers dont let us read this ini setting, so just display the default
		if ($seconds < 0 || $seconds > 10000) { $seconds = 300; }
		$minutes = floor($seconds / 60);
	}

	// make sure all files are deletable...
	\ThreadFin\file_recurse(plugin_dir_path(__FILE__), \ThreadFin\partial_right('chmod', FILE_EX));
	
	include_once \BitFire\WAF_SRC . 'server.php';
	// looks good, go ahead and delete
	\BitFireSvr\uninstall()->run();

	if (defined("BitFire\INFO")) {
		$server_id = \BitFire\Config::str('server_id', $_SERVER['HTTP_HOST'] ?? 'unknown');
		http2("POST", INFO . "zxf.php", "{\"action\":\"bitfire_uninstall\", \"server_id\":\"$server_id\"}", []);
	}

	$dir = get_hidden_file("");

	// only delete the bitfire configuration data if we have a path to the correct place!!
	if (contains($dir, "bitfire_") && contains($dir, "uploads")) {
		remove_all_contents($dir);
	}
}


/**
 * manually remove the bitfire startup script.
 * @param string $filepath 
 * @return bool 
 */
function removeBitFireBlock(string $filepath): bool {
    if (!file_exists($filepath) || !is_readable($filepath) || !is_writable($filepath)) {
        return false;
    }

    $content = file_get_contents($filepath);
    if ($content === false) {
        return false;
    }

    // Remove everything between #BEGIN BitFire and #END BitFire (including those lines)
    $pattern = '/^#BEGIN BitFire.*?#END BitFire\s*/ms';
    $modified = preg_replace($pattern, '', $content);

    if ($modified === null) {
        return false; // preg_replace failed
    }

    return file_put_contents($filepath, $modified) !== false;
}


/**
 * remove all contents of a directory recursively.
 * @param string $path 
 * @return bool 
 */
function remove_all_contents(string $path): bool {
    if (!is_dir($path)) {
        return false; // Not a directory
    }

    $items = scandir($path);
    if ($items === false) return false;

    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }

        $fullPath = $path . DIRECTORY_SEPARATOR . $item;
		if (is_link($fullPath)) {
			continue;
		}

        if (is_dir($fullPath)) {
            // Recurse into subdirectory
            if (!remove_all_contents($fullPath)) {
                return false;
            }
            if (!rmdir($fullPath)) {
                return false;
            }
        } else {
            // Remove file or symlink
            if (!unlink($fullPath)) {
                return false;
            }
        }
    }

    return true;
}
