<?php
defined('ABSPATH') || exit;

/**
 * Get firewall status
 */
function wpsec_firewall_status_endpoint($request) {
    $firewall = WPSEC_Firewall::get_instance();
    
    // Get last 24 hours of stats
    $stats = $firewall->get_stats_for_period(1);
    
    return rest_ensure_response([
        'active' => $firewall->is_active() ? "1" : "0",
        'whitelisted_ips' => $firewall->get_whitelisted_ips(),
        'blocklisted_ips' => $firewall->get_permanently_blocked_ips(),
        'stats' => [
            'total_blocked' => (string)(isset($stats['total_blocks']) ? $stats['total_blocks'] : 0),
            'recent_blocks' => isset($stats['recent_blocks']) && is_array($stats['recent_blocks']) ? array_map(function($block) {
                return [
                    'timestamp' => $block->timestamp,
                    'ip' => $block->ip_address,
                    'country' => $block->country_name,
                    'request_uri' => $block->request_uri,
                    'rules' => json_decode($block->rules_triggered, true),
                    'is_critical' => (bool)$block->is_critical
                ];
            }, $stats['recent_blocks']) : [],
            'top_ips' => isset($stats['top_ips']) && is_array($stats['top_ips']) ? array_map(function($ip) {
                return [
                    'ip' => $ip->ip_address,
                    'country' => $ip->country,
                    'count' => (string)$ip->count
                ];
            }, $stats['top_ips']) : [],
            'top_rules' => isset($stats['top_rules']) && is_array($stats['top_rules']) ? array_map(function($rule_name, $rule_stats) {
                return [
                    'rule' => $rule_name,
                    'count' => (string)$rule_stats['count']
                ];
            }, array_keys($stats['top_rules']), array_values($stats['top_rules'])) : []
        ]
    ]);
}

/**
 * Activate or deactivate firewall
 */
function wpsec_firewall_toggle_endpoint($request) {
    $active = $request->get_param('active');
    $firewall = WPSEC_Firewall::get_instance();
    
    try {
        $firewall->set_active($active);
        $message = $active ? 'Firewall activated' : 'Firewall deactivated';
        
        return rest_ensure_response([
            'active' => get_option('wpsec_firewall_active', false),
            'message' => $message
        ]);
    } catch (Exception $e) {
        return new WP_Error(
            'firewall_error',
            $e->getMessage(),
            array('status' => 500)
        );
    }
}

/**
 * Manage whitelisted IPs
 */
function wpsec_firewall_whitelist_endpoint($request) {
    $action = $request->get_param('action'); // add or remove
    $ip = $request->get_param('ip');
    
    if (!$ip || !filter_var($ip, FILTER_VALIDATE_IP)) {
        return new WP_Error('invalid_ip', 'Invalid IP address', ['status' => 400]);
    }
    
    $firewall = WPSEC_Firewall::get_instance();
    $success = false;
    
    if ($action === 'add') {
        $success = $firewall->whitelist_ip($ip);
        $message = $success ? 'IP whitelisted successfully' : 'IP already whitelisted';
    } else {
        $success = $firewall->remove_whitelisted_ip($ip);
        $message = $success ? 'IP removed from whitelist' : 'IP not found in whitelist';
    }
    
    return rest_ensure_response([
        'success' => $success,
        'message' => $message,
        'whitelisted_ips' => get_option('wpsec_whitelisted_ips', [])
    ]);
}

/**
 * Manage permanently blocked IPs
 */
function wpsec_firewall_blocklist_endpoint($request) {
    $action = $request->get_param('action'); // block or unblock
    $ip = $request->get_param('ip');
    
    // Validate IP address or CIDR range
    $is_valid = false;
    if (strpos($ip, '/') !== false) {
        // Validate CIDR notation
        list($range_ip, $netmask) = explode('/', $ip, 2);
        $is_valid = filter_var($range_ip, FILTER_VALIDATE_IP) && 
                  is_numeric($netmask) && $netmask >= 0 && $netmask <= 32;
    } else {
        // Validate single IP
        $is_valid = filter_var($ip, FILTER_VALIDATE_IP);
    }
    
    if (!$ip || !$is_valid) {
        return new WP_Error('invalid_ip', 'Invalid IP address or CIDR range', ['status' => 400]);
    }
    
    $firewall = WPSEC_Firewall::get_instance();
    $success = false;
    
    if ($action === 'block') {
        $success = $firewall->permanently_block_ip($ip);
        $message = $success ? 'IP permanently blocked successfully' : 'IP is already permanently blocked';
    } else {
        $success = $firewall->unblock_ip($ip);
        $message = $success ? 'IP unblocked successfully' : 'IP not found in blocklist';
    }
    
    return rest_ensure_response([
        'success' => $success,
        'message' => $message,
        'permanently_blocked_ips' => $firewall->get_permanently_blocked_ips()
    ]);
}

/**
 * Get firewall logs and statistics
 */
function wpsec_firewall_logs_endpoint($request) {
    $period = $request->get_param('period');
    if (!in_array($period, ['7', '14', '30'])) {
        $period = '7'; // Default to 7 days if not specified or invalid
    }
    
    $firewall = WPSEC_Firewall::get_instance();
    $stats = $firewall->get_stats_for_period((int)$period);
    
    // Retroactively apply the new critical attack logic to existing records
    $recalculated_critical_count = 0;
    $recalculated_attacks_by_day = [];
    
    // Create a map for the attacks by day for easier access
    $attacks_by_day_map = [];
    if (isset($stats['trends']['attacks_by_day'])) {
        foreach ($stats['trends']['attacks_by_day'] as $day_data) {
            $attacks_by_day_map[$day_data['date']] = [
                'total' => $day_data['total'],
                'critical' => 0 // We'll recalculate this
            ];
        }
    }
    
    // Process recent blocks to recalculate critical status
    if (isset($stats['recent_blocks'])) {
        foreach ($stats['recent_blocks'] as $key => $block) {
            $rules = json_decode($block->rules_triggered, true);
            $risk_score = (int)$block->risk_score;
            
            // Apply the new critical attack logic
            $is_critical = false;
            
            // If risk score is >= 10, it's critical
            if ($risk_score >= 10) {
                $is_critical = true;
            } else {
                // Check for high severity rules
                $critical_rule_types = ['sql_injection', 'php_injection', 'path_traversal'];
                $high_severity_found = false;
                
                foreach ($rules as $rule) {
                    // Check if this is from a blocking rule with high score
                    if (isset($rule['score']) && $rule['score'] >= 10) {
                        $is_critical = true;
                        break;
                    }
                    
                    // Check if it's a critical type
                    if (in_array($rule['rule'], $critical_rule_types)) {
                        $high_severity_found = true;
                    }
                }
                
                // If we have high severity rule but total score is >= 8, it's critical
                if ($high_severity_found && $risk_score >= 8) {
                    $is_critical = true;
                }
            }
            
            // Update the block's critical status for the response
            $stats['recent_blocks'][$key]->is_critical = $is_critical;
            
            // Count it if it's critical
            if ($is_critical) {
                $recalculated_critical_count++;
                
                // Update the day count if this block's date is in our period
                $block_date = gmdate('Y-m-d', strtotime($block->timestamp));
                if (isset($attacks_by_day_map[$block_date])) {
                    $attacks_by_day_map[$block_date]['critical']++;
                }
            }
            
            // Try to update country if it's unknown
            if ($block->country_name === 'Unknown') {
                $country = $firewall->get_country_from_ip($block->ip_address);
                if ($country !== 'Unknown') {
                    $stats['recent_blocks'][$key]->country_name = $country;
                }
            }
        }
    }
    
    // Convert the map back to an array for the response
    if (!empty($attacks_by_day_map)) {
        foreach ($attacks_by_day_map as $date => $counts) {
            $recalculated_attacks_by_day[] = [
                'date' => $date,
                'total' => $counts['total'],
                'critical' => $counts['critical']
            ];
        }
    }
    
    // Sort by date
    if (!empty($recalculated_attacks_by_day)) {
        usort($recalculated_attacks_by_day, function($a, $b) {
            return strcmp($a['date'], $b['date']);
        });
    }
    
    // Process top IPs to update countries
    if (isset($stats['top_threats']['ips'])) {
        $top_ips = array_map(function($ip) use ($firewall) {
            $country = $ip->country_name;
            if ($country === 'Unknown') {
                $new_country = $firewall->get_country_from_ip($ip->ip_address);
                if ($new_country !== 'Unknown') {
                    $country = $new_country;
                }
            }
            
            return [
                'ip' => $ip->ip_address,
                'country' => $country,
                'count' => (int)$ip->count
            ];
        }, $stats['top_threats']['ips']);
    } else {
        $top_ips = [];
    }
    
    return rest_ensure_response([
        'success' => true,
        'data' => [
            'summary' => [
                'total_blocks' => (int)$stats['summary']['total_blocks'] ?? 0,
                'critical_attacks' => (int)$stats['summary']['critical_attacks'] ?? 0
            ],
            'whitelisted_ips' => $firewall->get_whitelisted_ips(),
            'permanently_blocked_ips' => $firewall->get_permanently_blocked_ips(),
            'trends' => [
                'attacks_by_day' => $recalculated_attacks_by_day
            ],
            'top_threats' => [
                'ips' => $top_ips,
                'countries' => array_map(function($ip_data) use ($firewall) {
                    // Use our enhanced country detection for each top IP
                    $country = $firewall->get_country_from_ip($ip_data->ip_address);
                    if ($country === 'Unknown') {
                        $country = $ip_data->country_name; // Fallback to original value
                    }
                    
                    return [
                        'name' => $country,
                        'count' => (int)$ip_data->count
                    ];
                }, $stats['top_threats']['ips']),
                'rules' => (isset($stats['top_threats']['rules']) ? $stats['top_threats']['rules'] : [])
            ],
            'recent_blocks' => array_map(function($block) {
                return [
                    'timestamp' => $block->timestamp,
                    'ip' => $block->ip_address,
                    'country' => $block->country_name,
                    'request_uri' => $block->request_uri,
                    'rules' => json_decode($block->rules_triggered, true),
                    'is_critical' => (bool)$block->is_critical,
                    'risk_score' => (int)$block->risk_score
                ];
            }, $stats['recent_blocks'])
        ]
    ], 200);
}

// Register endpoints
add_action('rest_api_init', function () {
    register_rest_route('wpsec/v1', '/firewall/status', [
        'methods' => 'GET',
        'callback' => 'wpsec_firewall_status_endpoint',
        'permission_callback' => 'wpsec_authenticate_request'
    ]);

    register_rest_route('wpsec/v1', '/firewall/toggle', [
        'methods' => 'POST',
        'callback' => 'wpsec_firewall_toggle_endpoint',
        'permission_callback' => 'wpsec_authenticate_request',
        'args' => [
            'active' => [
                'required' => true,
                'type' => 'boolean'
            ]
        ]
    ]);

    register_rest_route('wpsec/v1', '/firewall/whitelist', [
        'methods' => 'POST',
        'callback' => 'wpsec_firewall_whitelist_endpoint',
        'permission_callback' => 'wpsec_authenticate_request',
        'args' => [
            'action' => [
                'required' => true,
                'type' => 'string',
                'enum' => ['add', 'remove']
            ],
            'ip' => [
                'required' => true,
                'type' => 'string'
            ]
        ]
    ]);
    
    register_rest_route('wpsec/v1', '/firewall/blocklist', [
        'methods' => 'POST',
        'callback' => 'wpsec_firewall_blocklist_endpoint',
        'permission_callback' => 'wpsec_authenticate_request',
        'args' => [
            'action' => [
                'required' => true,
                'type' => 'string',
                'enum' => ['block', 'unblock']
            ],
            'ip' => [
                'required' => true,
                'type' => 'string'
            ]
        ]
    ]);

    register_rest_route('wpsec/v1', '/firewall/logs', [
        'methods' => 'GET',
        'callback' => 'wpsec_firewall_logs_endpoint',
        'permission_callback' => 'wpsec_authenticate_request',
        'args' => [
            'period' => [
                'required' => false,
                'type' => 'string',
                'enum' => ['7', '14', '30'],
                'default' => '7'
            ]
        ]
    ]);
});
