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

/**
 * FormShield IP Whitelist Class
 * 
 * Handles all IP whitelist functionality including:
 * - Saving whitelist settings
 * - Validating IP addresses
 * - Checking if IP is whitelisted
 * - Managing whitelist entries
 * 
 * @since 1.0.3-beta
 */
class FormShieldIPWhitelist {
    
    private static $instance = null;
    private $whitelist_option = 'formshield_ip_whitelist';
    private $enabled_option = 'formshield_whitelist_enabled';
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        add_action('wp_ajax_formshield_save_whitelist', array($this, 'save_whitelist'));
        add_action('wp_ajax_formshield_add_ip_to_whitelist', array($this, 'add_ip_to_whitelist'));
        add_action('wp_ajax_formshield_remove_ip_from_whitelist', array($this, 'remove_ip_from_whitelist'));
        add_action('wp_ajax_formsh_test_ip', array($this, 'test_ip'));
    }
    
    /**
     * Save whitelist settings via AJAX
     */
    public function save_whitelist() {
        // Check nonce
        if (!check_ajax_referer('formshield_whitelist', 'nonce', false)) {
            wp_send_json_error('Security check failed');
            return;
        }
        
        // Check permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Insufficient permissions');
            return;
        }
        
        // Get and validate data
        $whitelist_ips = formshield_get_post_string('whitelist_ips');
        $whitelist_ips = sanitize_textarea_field($whitelist_ips);
        $whitelist_enabled = formshield_get_post_bool('whitelist_enabled');
        
        // Parse and validate IP addresses
        $ip_list = $this->parse_ip_list($whitelist_ips);
        $valid_ips = array();
        $invalid_ips = array();
        
        foreach ($ip_list as $ip) {
            if ($this->is_valid_ip($ip)) {
                $valid_ips[] = $ip;
            } else {
                $invalid_ips[] = $ip;
            }
        }
        
        // Save valid IPs
        update_option($this->whitelist_option, $valid_ips);
        update_option($this->enabled_option, $whitelist_enabled);
        
        // Prepare response
        // translators: %1$d is number of valid IPs, %2$s is list of valid IPs
        $valid_message = sprintf(__('Valid IPs (%1$d):\n%2$s\n\n', 'formshield'), 
            count($valid_ips), 
            implode("\n", $valid_ips)
        );
        
        // translators: %1$d is number of invalid IPs, %2$s is list of invalid IPs
        $invalid_message = sprintf(__('Invalid IPs (%1$d):\n%2$s\n\n', 'formshield'),
            count($invalid_ips),
            implode("\n", $invalid_ips)
        );
        
        $response = array(
            'message' => __('Whitelist saved successfully', 'formshield'),
            'valid_ips' => $valid_ips,
            'invalid_ips' => $invalid_ips,
            'total_valid' => count($valid_ips),
            'total_invalid' => count($invalid_ips),
            'valid_message' => $valid_message,
            'invalid_message' => $invalid_message
        );
        
        if (!empty($invalid_ips)) {
            $response['message'] .= ' (some invalid IPs were ignored)';
        }
        
        wp_send_json_success($response);
    }
    
    /**
     * Add IP to whitelist
     */
    public function add_ip_to_whitelist() {
        // Check nonce
        if (!check_ajax_referer('formshield_whitelist', 'nonce', false)) {
            wp_send_json_error('Security check failed');
            return;
        }
        
        // Check permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Insufficient permissions');
            return;
        }
        
        $ip = formshield_get_post_string('ip');
        
        if (!$this->is_valid_ip($ip)) {
            wp_send_json_error('Invalid IP address');
            return;
        }
        
        $whitelist = $this->get_whitelist();
        
        if (in_array($ip, $whitelist)) {
            wp_send_json_error('IP address already in whitelist');
            return;
        }
        
        $whitelist[] = $ip;
        update_option($this->whitelist_option, $whitelist);
        
        wp_send_json_success(array(
            'message' => 'IP added to whitelist',
            'ip' => $ip,
            'total_ips' => count($whitelist)
        ));
    }
    
    /**
     * Remove IP from whitelist
     */
    public function remove_ip_from_whitelist() {
        // Check nonce
        if (!check_ajax_referer('formshield_whitelist', 'nonce', false)) {
            wp_send_json_error('Security check failed');
            return;
        }
        
        // Check permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Insufficient permissions');
            return;
        }
        
        $ip = formshield_get_post_string('ip');
        $whitelist = $this->get_whitelist();
        
        if (!in_array($ip, $whitelist)) {
            wp_send_json_error('IP address not found in whitelist');
            return;
        }
        
        $whitelist = array_diff($whitelist, array($ip));
        update_option($this->whitelist_option, $whitelist);
        
        wp_send_json_success(array(
            'message' => 'IP removed from whitelist',
            'ip' => $ip,
            'total_ips' => count($whitelist)
        ));
    }
    
    /**
     * Test if IP is valid
     */
    public function test_ip() {
        // Check nonce
        if (!check_ajax_referer('formshield_whitelist', 'nonce', false)) {
            wp_send_json_error('Security check failed');
            return;
        }
        
        // Check permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Insufficient permissions');
            return;
        }
        
        $ip = formshield_get_post_string('ip');
        
        if ($this->is_valid_ip($ip)) {
            wp_send_json_success(array(
                'message' => 'Valid IP address',
                'ip' => $ip,
                'is_valid' => true
            ));
        } else {
            wp_send_json_error(array(
                'message' => 'Invalid IP address',
                'ip' => $ip,
                'is_valid' => false
            ));
        }
    }
    
    /**
     * Check if IP is whitelisted
     */
    public function is_ip_whitelisted($ip) {
        // Check if whitelist is enabled
        if (!$this->is_enabled()) {
            return false;
        }
        
        $whitelist = $this->get_whitelist();
        return in_array($ip, $whitelist);
    }
    
    /**
     * Get current whitelist
     */
    public function get_whitelist() {
        return get_option($this->whitelist_option, array());
    }
    
    /**
     * Check if whitelist is enabled
     */
    public function is_enabled() {
        return get_option($this->enabled_option, false);
    }
    
    /**
     * Parse IP list from textarea
     */
    private function parse_ip_list($ip_text) {
        $lines = explode("\n", $ip_text);
        $ips = array();
        
        foreach ($lines as $line) {
            $ip = trim($line);
            if (!empty($ip)) {
                $ips[] = $ip;
            }
        }
        
        return array_unique($ips);
    }
    
    /**
     * Validate IP address
     */
    private function is_valid_ip($ip) {
        // Remove whitespace
        $ip = trim($ip);
        
        // Check for empty IP
        if (empty($ip)) {
            return false;
        }
        
        // Check for IPv4
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            return true;
        }
        
        // Check for IPv6
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return true;
        }
        
        // Check for CIDR notation (e.g., 192.168.1.0/24)
        if (strpos($ip, '/') !== false) {
            $parts = explode('/', $ip);
            if (count($parts) === 2) {
                $base_ip = $parts[0];
                $subnet = $parts[1];
                
                if (filter_var($base_ip, FILTER_VALIDATE_IP) && 
                    is_numeric($subnet) && 
                    $subnet >= 0 && 
                    $subnet <= 32) {
                    return true;
                }
            }
        }
        
        // Check for wildcard notation (e.g., 192.168.*.*)
        if (strpos($ip, '*') !== false) {
            $pattern = '/^(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)$/';
            if (preg_match($pattern, $ip)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Get whitelist statistics
     */
    public function get_statistics() {
        $whitelist = $this->get_whitelist();
        $enabled = $this->is_enabled();
        
        return array(
            'enabled' => $enabled,
            'total_ips' => count($whitelist),
            'ip_list' => $whitelist,
            'last_updated' => get_option($this->whitelist_option . '_updated', 'Never')
        );
    }
}

// Initialize the class
FormShieldIPWhitelist::get_instance();
