<?php

use CleantalkSP\SpbctWP\RenameLoginPage;
use CleantalkSP\Variables\Post;
use CleantalkSP\Variables\Server;

// Prevent direct call
if ( ! defined('ABSPATH') ) {
    die('Not allowed!');
}

/**
 * Gets user by filed
 *
 * @param $field
 * @param $value
 *
 * @return bool|WP_User
 */
function spbc_get_user_by($field, $value)
{
    $userdata = WP_User::get_data_by($field, $value);

    if ( ! $userdata) {
        return false;
    }

    $user = new WP_User();
    $user->init($userdata);

    return $user;
}

/*
 * Checking if current request is a cron job
 * Support for wordpress < 4.8.0
 *
 * @return bool
 */
function spbc_wp_doing_cron()
{
    if (function_exists('wp_doing_cron')) {
        return wp_doing_cron();
    } else {
        return defined('DOING_CRON');
    }
}

/**
 * Checks if the plugin is active
 *
 * @param string $plugin relative path from plugin folder like security-malware-firewall/security-malware-firewall.php
 *
 * @return bool
 */
function spbc_is_plugin_active($plugin)
{
    return in_array($plugin, (array) get_option('active_plugins', array())) || spbc_is_plugin_active_for_network($plugin);
}

/**
 * Checks if the plugin is active for network
 *
 * @param string $plugin relative path from plugin folder like security-malware-firewall/security-malware-firewall.php
 *
 * @return bool
 */
function spbc_is_plugin_active_for_network($plugin)
{
    if ( ! SPBC_WPMS) {
        return false;
    }

    $plugins = get_site_option('active_sitewide_plugins');

    return isset($plugins[ $plugin ])
        ? true
        : false;
}

function spbc_mailpoet_doing_cron()
{
    return (
        // MailPoet cron requests skip
        spbc_is_plugin_active('mailpoet/mailpoet.php') &&
        Server::getString('HTTP_USER_AGENT') === 'MailPoet Cron' &&
        strpos(Server::get('REQUEST_URI', null, 'url'), 'mailpoet_router') !== false
    );
}

/**
 * Checks if the request is the command line access
 *
 * @return boolean
 */
function spbc_is_cli()
{
    return PHP_SAPI === "cli";
}

/**
 * Whether current request is a login page where BFP should enforce blocks.
 * Covers wp-login.php (incl. renamed login URL) and WooCommerce My Account.
 *
 * @return bool
 */
function spbc_is_login_page_request()
{
    global $spbc;

    $login_url = wp_login_url();
    if ( ! empty($spbc->settings['login_page_rename__enabled']) ) {
        if ( empty($GLOBALS['wp_rewrite']) || ! ($GLOBALS['wp_rewrite'] instanceof WP_Rewrite) ) {
            $GLOBALS['wp_rewrite'] = new WP_Rewrite();
        }
        $login_url = RenameLoginPage::getURL($spbc->settings['login_page_rename__name']);
    }

    if ( spbc_request_uri_matches_url($login_url) ) {
        return true;
    }

    return spbc_is_woocommerce_login_request();
}

/**
 * Detect WooCommerce My Account page / login form for BFP.
 *
 * @return bool
 */
function spbc_is_woocommerce_login_request()
{
    if ( ! spbc_is_plugin_active('woocommerce/woocommerce.php') ) {
        return false;
    }

    // Login form POST from WooCommerce My Account
    if ( Post::getString('woocommerce-login-nonce') !== '' ) {
        return true;
    }

    // Visiting My Account so already-banned IPs are blocked before form submit
    $myaccount_page_id = (int) get_option('woocommerce_myaccount_page_id');
    if ( ! $myaccount_page_id ) {
        return false;
    }

    $myaccount_url = get_permalink($myaccount_page_id);
    if ( ! $myaccount_url ) {
        return false;
    }

    return spbc_request_uri_matches_url($myaccount_url);
}

/**
 * Whether the current REQUEST_URI matches the given absolute URL.
 * Compares path and, when present, required query args — so plain-permalink
 * URLs like /?my-login or /?page_id=37 do not match the whole site.
 *
 * @param string $url Absolute URL (e.g. from wp_login_url() / get_permalink()).
 *
 * @return bool
 */
function spbc_request_uri_matches_url($url)
{
    $url_parts = parse_url((string) $url);
    if ( ! is_array($url_parts) ) {
        return false;
    }

    $target_path  = isset($url_parts['path']) ? $url_parts['path'] : '/';
    $target_query = isset($url_parts['query']) ? $url_parts['query'] : '';

    // Path: canonical (percent-decoded). Query: raw QUERY_STRING — do not take it from
    // rawurldecoded REQUEST_URI (%3F in path / %2B semantics would break parsing).
    $current_path  = Server::getCanonicalPath();
    $current_query = (string) Server::get('QUERY_STRING', null, 'url');

    if ( $current_path === '' ) {
        $current_path = '/';
    }

    $target_path_norm  = spbc_normalize_request_path($target_path);
    $current_path_norm = spbc_normalize_request_path($current_path);

    // Query-based URLs (plain permalinks / renamed login): require path + query keys.
    if ( $target_query !== '' ) {
        if ( $target_path_norm !== $current_path_norm ) {
            return false;
        }

        parse_str($target_query, $target_params);
        parse_str($current_query, $current_params);

        if ( empty($target_params) ) {
            return false;
        }

        foreach ( $target_params as $key => $value ) {
            if ( ! array_key_exists($key, $current_params) ) {
                return false;
            }
            if ( $value !== '' && (string) $current_params[$key] !== (string) $value ) {
                return false;
            }
        }

        return true;
    }

    // Path-only URL: never treat bare "/" as a match (would mark every request).
    if ( $target_path_norm === '/' ) {
        return false;
    }

    $target_trim  = trim($target_path_norm, '/');
    $current_trim = trim($current_path_norm, '/');

    return $current_trim === $target_trim || strpos($current_trim, $target_trim . '/') === 0;
}

/**
 * @param string $path
 *
 * @return string
 */
function spbc_normalize_request_path($path)
{
    $path = (string) $path;
    if ( $path === '' || $path === '/' ) {
        return '/';
    }

    return '/' . trim($path, '/');
}
