<?php
if (!defined('ABSPATH')) {
    die('You are not allowed to call this page directly.');
}

class FormShieldSpamProtection {
    private static $instance = null;
    private $ip_cache = array();
    private $spam_patterns = array();
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        // Инициализираме спам шаблоните
        $this->init_spam_patterns();
        
        // Добавяме филтри за коментари
        add_filter('preprocess_comment', array($this, 'check_comment_spam'), 1);
        
        // Добавяме проверки за форми
        add_action('wp_ajax_formshield_check_spam', array($this, 'check_submission_spam'));
        add_action('wp_ajax_nopriv_formshield_check_spam', array($this, 'check_submission_spam'));
    }
    
    private function init_spam_patterns() {
        $this->spam_patterns = array(
            // URL спам шаблони
            'urls' => array(
                '/\[url=.*?\].*?\[\/url\]/i',     // BBCode URLs
                '/(http|https|ftp):\/\/[^\s]*/i',  // Raw URLs
                '/href\s*=\s*["\'][^"\']*["\']/',  // HTML URLs
                '/www\.[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/i', // www URLs
                '/[a-zA-Z0-9.-]+\.(com|net|org|info|biz|co\.uk)/i', // Domain names
            ),
            
            // Спам думи и фрази
            'keywords' => array(
                '/\b(viagra|cialis|levitra|casino|porn|sex|xxx|adult)\b/i',
                '/\b(buy|cheap|discount|offer|sale|free|deal)\b.*\b(now|online|here|today)\b/i',
                '/\b(make|earn|get).*\b(money|cash|profit|income)\b.*\b(fast|online|easy|quick)\b/i',
                '/\b(click|visit|check|see)\b.*\b(here|link|url|website)\b/i',
                '/\b(guaranteed|promise|guarantee|sure|100%)\b/i',
                '/\b(limited|exclusive|special|unique|amazing)\b.*\b(offer|deal|price)\b/i'
            ),
            
            // Специални символи
            'symbols' => array(
                '/\$[0-9,]+(\.\d{2})?/',  // Цени с десетични
                '/\d{1,3}%/',   // Проценти
                '/[!?]{2,}/',    // Множество препинателни знаци
                '/[\$€£¥]{2,}/', // Множество валутни символи
                '/[\*\+\-]{3,}/', // Множество специални символи
                '/\d{4,}/' // Дълги числови последователности
            ),
            
            // Езикови аномалии
            'language' => array(
                '/[а-яА-Я]{3,}.*[a-zA-Z]{3,}/u',  // Смесица от кирилица и латиница
                '/(.)\1{3,}/',                     // Повтарящи се символи
                '/\b[A-Z]{3,}\b/',                  // CAPS LOCK думи
                '/[a-z]{1,2}[A-Z][a-z]{1,2}[A-Z]/u', // CamelCase в спам
                '/[\x00-\x1F\x7F-\xFF]/u' // Контролни символи
            ),
            
            // Подозрителни фрази
            'phrases' => array(
                '/\b(no\s+spam|not\s+spam|legitimate|genuine)\b/i',
                '/\b(remove|unsubscribe|opt\s+out)\b/i',
                '/\b(winner|congratulations|you\s+won|prize)\b/i',
                '/\b(urgent|asap|immediately|right\s+now)\b/i',
                '/\b(click\s+here|visit\s+now|act\s+now)\b/i'
            )
        );
    }
    
    public function check_submission_spam() {
        // Проверяваме nonce
        check_ajax_referer('formshield_spam_check', 'nonce');
        
        $content = isset($_POST['content']) ? sanitize_textarea_field(wp_unslash($_POST['content'])) : '';
        $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : '';
        $ip = formshield_get_validated_ip('Unknown');
        
        // Без директен достъп до $_POST — минаваме през helper-и
        $typing_patterns_json = formshield_get_post_string('typing_patterns', '');
        $typing_patterns = $typing_patterns_json ? json_decode($typing_patterns_json, true) : null;
        if (json_last_error() !== JSON_ERROR_NONE) {
            $typing_patterns = null; // невалиден JSON -> игнорирай
        }

        $paste_count = formshield_get_post_int('paste_count', 0);
        
        $spam_score = $this->calculate_spam_score($content, $email, $ip, $typing_patterns, $paste_count);
        
        if ($spam_score >= 70) {
            wp_send_json_error(array(
                'message' => 'Suspected spam content',
                'score' => $spam_score
            ));
        } else {
            wp_send_json_success(array(
                'score' => $spam_score
            ));
        }
    }
    
    public function check_comment_spam($commentdata) {
        $content = $commentdata['comment_content'];
        $email = $commentdata['comment_author_email'];
        $ip = formshield_get_validated_ip('Unknown');
        
        $spam_score = $this->calculate_spam_score($content, $email, $ip);
        
        if ($spam_score >= 70) {
            wp_die('Comment blocked as potential spam. Please try again with different content.');
        }
        
        return $commentdata;
    }
    
    private function calculate_spam_score($content, $email, $ip, $typing_patterns = null, $paste_count = 0) {
        $score = 0;
        
        // IP-базирани проверки
        if ($this->check_ip_spam_score($ip) > 50) {
            $score += 30;
        }
        
        // Проверка за спам шаблони
        foreach ($this->spam_patterns as $type => $patterns) {
            foreach ($patterns as $pattern) {
                if (preg_match_all($pattern, $content, $matches)) {
                    $score += (count($matches[0]) * 10);
                }
            }
        }
        
        // Проверка на имейл
        if ($this->is_disposable_email($email)) {
            $score += 20;
        }
        
        // Проверка за скорост на изпращане
        if ($this->is_rapid_submission($ip)) {
            $score += 25;
        }
        
        // Проверка за дължина на съдържанието
        $content_length = strlen($content);
        if ($content_length < 10) {
            $score += 10;
        } elseif ($content_length > 1000) {
            $score += 15;
        }
        
        // Проверка на поведенчески данни от JavaScript
        if ($typing_patterns && isset($typing_patterns['suspicious']) && $typing_patterns['suspicious']) {
            $score += 20; // Подозрителни typing patterns
        }
        
        // Проверка за твърде много paste операции
        if ($paste_count > 3) {
            $score += 15; // Вероятно копиране на голям текст
        }
        
        // Логваме високите резултати
        if ($score >= 50) {
            $this->log_spam_attempt($content, $email, $ip, $score);
        }
        
        return $score;
    }
    
    private function check_ip_spam_score($ip) {
        global $wpdb;
        
        // Проверяваме кеша първо
        if (isset($this->ip_cache[$ip])) {
            return $this->ip_cache[$ip];
        }
        
        // Проверяваме историята на IP адреса
        $table_name = $wpdb->prefix . 'formshield_activity_log';
        $last_24h = gmdate('Y-m-d H:i:s', strtotime('-24 hours'));
        
        // Get stats with caching
        $cache_key = 'formshield_spam_stats_' . md5($ip . $last_24h);
        $stats = wp_cache_get($cache_key, 'formshield');
        if (false === $stats) {
            $table_name = $wpdb->prefix . 'formshield_activity_log';

            $stats = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- read-only към вътрешна таблица
                $wpdb->prepare(
                    "SELECT COUNT(*) AS total_attempts, SUM(is_suspicious) AS suspicious_attempts FROM {$table_name} WHERE ip_address = %s AND `timestamp` > %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table_name е вътрешна таблица от $wpdb->prefix
                    $ip,
                    $last_24h
                )
            );
            wp_cache_set($cache_key, $stats, 'formshield', 300); // 5 минути
        }
        
        $score = 0;
        
        if ($stats) {
            // Повече от 10 опита за 24 часа
            if ($stats->total_attempts > 10) {
                $score += 20;
            }
            
            // Повече от 50% подозрителни опити
            if ($stats->total_attempts > 0) {
                $suspicious_ratio = $stats->suspicious_attempts / $stats->total_attempts;
                if ($suspicious_ratio > 0.5) {
                    $score += 30;
                }
            }
        }
        
        // Кешираме резултата
        $this->ip_cache[$ip] = $score;
        
        return $score;
    }
    
    private function is_disposable_email($email) {
        $disposable_domains = array(
            'tempmail.com', 'throwawaymail.com', 'mailinator.com',
            'guerrillamail.com', 'yopmail.com', 'trashmail.com'
            // Добави още домейни тук
        );
        
        $domain = substr(strrchr($email, "@"), 1);
        return in_array(strtolower($domain), $disposable_domains);
    }
    
    private function is_rapid_submission($ip) {
        $cache_key = 'formshield_last_submission_' . $ip;
        $last_submission = get_transient($cache_key);
        
        if ($last_submission) {
            $time_diff = time() - $last_submission;
            if ($time_diff < 30) { // По-малко от 30 секунди
                return true;
            }
        }
        
        set_transient($cache_key, time(), HOUR_IN_SECONDS);
        return false;
    }
    
    private function log_spam_attempt($content, $email, $ip, $score) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'formshield_activity_log';
        
        $data = array(
            'ip_address' => $ip,
            'timestamp' => current_time('mysql'),
            'is_suspicious' => 1,
            'validation_data' => wp_json_encode(array(
                'content_sample' => substr($content, 0, 255),
                'email' => $email,
                'spam_score' => $score
            ))
        );
        
        // Use WordPress cache to avoid direct database queries
        $cache_key = 'formshield_activity_' . md5($ip . '|' . $data['timestamp']);
        wp_cache_delete($cache_key, 'formshield');
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->insert(
            $table_name,
            $data,
            array('%s', '%s', '%d', '%s') // ip_address, timestamp, is_suspicious, validation_data
        );
        
        // Record attack in FormShield statistics for Analytics Overview
        // Try to find the form ID from the current context
        $form_id = $this->get_current_form_id();
        if ($form_id) {
            FormShieldForms::record_spam_attack($form_id, $email, $content);
        }
        
        // Ако имаме много спам от това IP, добавяме го в черния списък
        if ($score > 90) {
            $this->add_to_blacklist($ip);
        }
    }
    
    /**
     * Try to determine the current form ID from context
     * This is a fallback method when we can't get the form ID directly
     */
    private function get_current_form_id() {
        // Check if we're in a form submission context
        $form_id = formshield_get_post_string('form_id');
        if ($form_id) {
            return sanitize_text_field($form_id);
        }
        
        // Check for common form fields
        $cf7_id = formshield_get_post_string('contact-form-7-id');
        if ($cf7_id) {
            return 'cf7_' . sanitize_text_field($cf7_id);
        }
        
        // front-end WPForms submit; няма как да изискваме наш nonce тук
        // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $wpforms_post = isset($_POST['wpforms']) ? wp_unslash($_POST['wpforms']) : array();

        $wpforms_raw = is_array($wpforms_post)
            ? array_map('sanitize_text_field', $wpforms_post)
            : array();
        
        $form_id = 0;
        if (is_array($wpforms_raw) && isset($wpforms_raw['id'])) {
            $form_id = absint($wpforms_raw['id']);
        }
        
        if ($form_id) {
            return 'wpforms_' . $form_id;
        }
        
        // Default fallback
        return 'unknown_form';
    }
    
    private function add_to_blacklist($ip) {
        $blacklist = get_option('formshield_ip_blacklist', array());
        if (!in_array($ip, $blacklist)) {
            $blacklist[] = $ip;
            update_option('formshield_ip_blacklist', $blacklist);
        }
    }
}

// Инициализираме класа
FormShieldSpamProtection::get_instance();
