<?php
/**
 * Pro spam protection helpers.
 *
 * @package AlgoForms
 */

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

/**
 * Client IP for rate limiting (hashed storage preferred).
 *
 * @return string
 */
function algo_forms_client_ip()
{
    $ip = '';
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && is_string($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $parts = explode(',', wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR']));
        $ip = trim((string) $parts[0]);
    } elseif (!empty($_SERVER['REMOTE_ADDR']) && is_string($_SERVER['REMOTE_ADDR'])) {
        $ip = wp_unslash($_SERVER['REMOTE_ADDR']);
    }
    $ip = is_string($ip) ? $ip : '';
    if ($ip !== '' && filter_var($ip, FILTER_VALIDATE_IP)) {
        return $ip;
    }
    return '';
}

/**
 * @return string
 */
function algo_forms_client_ip_hash()
{
    $ip = algo_forms_client_ip();
    if ($ip === '') {
        return '';
    }
    return hash_hmac('sha256', $ip, wp_salt('auth'));
}

/**
 * Front-end anti-spam fields (only when Pro spam is on).
 *
 * @return void
 */
function algo_forms_render_spam_fields()
{
    if (!algo_forms_pro_feature('spam')) {
        return;
    }
    $opts = algo_forms_get_options();
    if (!isset($opts['spam_honeypot']) || !empty($opts['spam_honeypot'])) {
        ?>
    <div class="algo-form__hp" aria-hidden="true">
        <label for="af_hp_website"><?php esc_html_e('Website', 'algo-forms'); ?></label>
        <input type="text" name="af_hp_website" id="af_hp_website" value="" tabindex="-1" autocomplete="off">
    </div>
        <?php
    }
    $min = isset($opts['spam_min_seconds']) ? (int) $opts['spam_min_seconds'] : 2;
    if ($min > 0) {
        ?>
    <input type="hidden" name="af_started" value="<?php echo esc_attr((string) time()); ?>">
        <?php
    }
}

/**
 * Validate Pro spam rules. Returns error string or empty string when OK / Free.
 *
 * @param int $form_id Form ID.
 * @return string
 */
function algo_forms_check_spam($form_id)
{
    if (!algo_forms_pro_feature('spam')) {
        return '';
    }

    $opts = algo_forms_get_options();

    // Honeypot — bots fill hidden fields.
    if (!isset($opts['spam_honeypot']) || !empty($opts['spam_honeypot'])) {
        $hp = isset($_POST['af_hp_website']) ? trim((string) wp_unslash($_POST['af_hp_website'])) : '';
        if ($hp !== '') {
            return __('Submission blocked.', 'algo-forms');
        }
    }

    // Minimum fill time.
    $min_seconds = isset($opts['spam_min_seconds']) ? max(0, (int) $opts['spam_min_seconds']) : 2;
    $started = isset($_POST['af_started']) ? (int) wp_unslash($_POST['af_started']) : 0;
    if ($min_seconds > 0 && $started > 0) {
        $elapsed = time() - $started;
        if ($elapsed >= 0 && $elapsed < $min_seconds) {
            return __('Please wait a moment and try again.', 'algo-forms');
        }
    }

    // Rate limit by IP hash (count is incremented after a successful save).
    $limit = isset($opts['spam_rate_limit']) ? max(0, (int) $opts['spam_rate_limit']) : 8;
    if ($limit > 0) {
        $hash = algo_forms_client_ip_hash();
        if ($hash !== '') {
            $key = 'algo_forms_rl_' . substr($hash, 0, 32);
            $count = (int) get_transient($key);
            if ($count >= $limit) {
                return __('Too many submissions. Please try again later.', 'algo-forms');
            }
        }
    }

    /**
     * Extra spam checks.
     *
     * @param string $error   Empty = pass.
     * @param int    $form_id Form ID.
     */
    return (string) apply_filters('algo_forms_check_spam', '', $form_id);
}

/**
 * Record a successful submission against the Pro IP rate limit.
 *
 * @return void
 */
function algo_forms_spam_rate_limit_hit()
{
    if (!algo_forms_pro_feature('spam')) {
        return;
    }
    $opts = algo_forms_get_options();
    $limit = isset($opts['spam_rate_limit']) ? max(0, (int) $opts['spam_rate_limit']) : 8;
    $window = isset($opts['spam_rate_window']) ? max(60, (int) $opts['spam_rate_window']) : HOUR_IN_SECONDS;
    if ($limit <= 0) {
        return;
    }
    $hash = algo_forms_client_ip_hash();
    if ($hash === '') {
        return;
    }
    $key = 'algo_forms_rl_' . substr($hash, 0, 32);
    set_transient($key, (int) get_transient($key) + 1, $window);
}
