<?php
/**
 * security_management_actions.php — the Security Management POST actions,
 * extracted so they can be driven both by the page (non-JS full-reload
 * fallback) and by api/security-management-ajax.php (async JSON via
 * whp_ajax_endpoint). Logic is unchanged from the original page handler; it
 * reads $_POST and returns ['message' => string, 'type' => string] where
 * 'type' is one of 'success'|'danger'|'warning'|'info' (the wrapper maps
 * 'success' => success:true, everything else => success:false).
 *
 * NOTE: CSRF validation is intentionally NOT done here. The page handler and
 * the async wrapper (whp_ajax_endpoint) each validate CSRF before calling this
 * function, mirroring libs/announcement_actions.php.
 *
 * Pattern mirror of libs/announcement_actions.php.
 *
 * @param security_manager     $SecManager
 * @param log_monitor_manager  $LogMonitor
 */
function whp_security_management_handle_action(security_manager $SecManager, log_monitor_manager $LogMonitor): array {
    $message = '';
    $message_type = '';

    if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST' || !isset($_POST['action'])) {
        return ['message' => $message, 'type' => $message_type];
    }

    switch ($_POST['action']) {
        case 'unblock_ip':
            $ip_input = trim($_POST['ip_address'] ?? '');

            // Validate IP or CIDR notation
            $is_valid = false;
            if (filter_var($ip_input, FILTER_VALIDATE_IP)) {
                $is_valid = true;
            } elseif (strpos($ip_input, '/') !== false) {
                list($ip, $mask) = explode('/', $ip_input, 2);
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
                    is_numeric($mask) && $mask >= 0 && $mask <= 32) {
                    $is_valid = true;
                }
            }

            if ($is_valid && !empty($ip_input)) {
                $errors = [];
                $success_count = 0;

                // Try to unblock from all services and handle errors gracefully
                // Note: SSH/FTP services only support single IP unblocking, not CIDR
                $is_cidr = strpos($ip_input, '/') !== false;

                if (!$is_cidr) {
                    try {
                        $result1 = $LogMonitor->unblock_ip_from_all_services($ip_input);
                        if ($result1) {
                            $success_count++;
                        }
                    } catch (Exception $e) {
                        $errors[] = 'Service unblock: Operation failed';
                        error_log('Service unblock error for IP ' . $ip_input . ': ' . $e->getMessage());
                    }
                }

                try {
                    $result2 = $SecManager->unblock_ip($ip_input);
                    if ($result2) {
                        $success_count++;
                    }
                } catch (Exception $e) {
                    $errors[] = 'Security manager unblock: Operation failed';
                    error_log('Security manager unblock error for IP ' . $ip_input . ': ' . $e->getMessage());
                }

                try {
                    if (class_exists('haproxy_manager')) {
                        $HaproxyManager = new haproxy_manager();
                        $result3 = $HaproxyManager->unblock_ip($ip_input);
                        if ($result3) {
                            $success_count++;
                        }
                    } else {
                        $errors[] = 'HAProxy unblock: Service not available';
                    }
                } catch (Exception $e) {
                    $errors[] = 'HAProxy unblock: Operation failed';
                    error_log('HAProxy unblock error for IP ' . $ip_input . ': ' . $e->getMessage());
                }

                if ($success_count > 0) {
                    $entry_type = $is_cidr ? 'CIDR range' : 'IP address';
                    if (empty($errors)) {
                        $message = $entry_type . ' unblocked successfully from all services: ' . htmlspecialchars($ip_input);
                        $message_type = 'success';
                    } else {
                        $message = $entry_type . ' partially unblocked from ' . $success_count . ' service(s): ' . htmlspecialchars($ip_input) . '. Warnings: ' . implode('; ', $errors);
                        $message_type = 'warning';
                    }
                } else {
                    $entry_type = $is_cidr ? 'CIDR range' : 'IP address';
                    $message = 'Failed to unblock ' . $entry_type . ' from any service: ' . htmlspecialchars($ip_input) . '. Errors: ' . implode('; ', $errors);
                    $message_type = 'danger';
                }
            } else {
                $message = 'Invalid IP address or CIDR format';
                $message_type = 'danger';
            }
            break;
        case 'block_ip':
            $ip_input = trim($_POST['ip_address'] ?? '');

            // Validate IP or CIDR notation
            $is_valid = false;
            if (filter_var($ip_input, FILTER_VALIDATE_IP)) {
                $is_valid = true;
            } elseif (strpos($ip_input, '/') !== false) {
                // Validate CIDR notation
                list($ip, $mask) = explode('/', $ip_input, 2);
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
                    is_numeric($mask) && $mask >= 0 && $mask <= 32) {
                    $is_valid = true;
                }
            }

            if ($is_valid && !empty($ip_input)) {
                $reason = !empty($_POST['reason']) ? substr(trim($_POST['reason']), 0, 255) : 'Manual block';
                $permanent = isset($_POST['permanent']) && $_POST['permanent'] == '1';
                $result = $SecManager->block_ip($ip_input, $reason, 0, $permanent, false);
                if ($result) {
                    $block_type = $permanent ? 'permanently' : 'temporarily';
                    $entry_type = strpos($ip_input, '/') !== false ? 'CIDR range' : 'IP address';
                    $message = $entry_type . ' blocked ' . $block_type . ': ' . htmlspecialchars($ip_input);
                    $message_type = 'success';
                } else {
                    $message = 'Error blocking IP/CIDR (may be exempted or invalid)';
                    $message_type = 'danger';
                }
            } else {
                $message = 'Invalid IP address or CIDR notation format';
                $message_type = 'danger';
            }
            break;
        case 'add_exemption':
            $ip_input = trim($_POST['ip_address'] ?? '');

            // Validate IP or CIDR notation
            $is_valid = false;
            if (filter_var($ip_input, FILTER_VALIDATE_IP)) {
                $is_valid = true;
            } elseif (strpos($ip_input, '/') !== false) {
                // Validate CIDR notation
                list($ip, $mask) = explode('/', $ip_input, 2);
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
                    is_numeric($mask) && $mask >= 0 && $mask <= 32) {
                    $is_valid = true;
                }
            }

            if ($is_valid && !empty($ip_input)) {
                $description = !empty($_POST['description']) ? substr(trim($_POST['description']), 0, 255) : '';
                $result = $SecManager->add_exemption_ip($ip_input, $description);
                if ($result) {
                    $entry_type = strpos($ip_input, '/') !== false ? 'CIDR range' : 'IP address';
                    $message = $entry_type . ' added to exemption list: ' . htmlspecialchars($ip_input);
                    $message_type = 'success';
                } else {
                    $message = 'Error adding IP/CIDR to exemption list';
                    $message_type = 'danger';
                }
            } else {
                $message = 'Invalid IP address or CIDR notation format';
                $message_type = 'danger';
            }
            break;
        case 'remove_exemption':
            $ip_input = trim($_POST['ip_address'] ?? '');

            // Validate IP or CIDR notation (same as add_exemption)
            $is_valid = false;
            if (filter_var($ip_input, FILTER_VALIDATE_IP)) {
                $is_valid = true;
            } elseif (strpos($ip_input, '/') !== false) {
                // Validate CIDR notation
                list($ip, $mask) = explode('/', $ip_input, 2);
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
                    is_numeric($mask) && $mask >= 0 && $mask <= 32) {
                    $is_valid = true;
                }
            }

            if ($is_valid && !empty($ip_input)) {
                $result = $SecManager->remove_exemption_ip($ip_input);
                if ($result) {
                    $entry_type = strpos($ip_input, '/') !== false ? 'CIDR range' : 'IP address';
                    $message = $entry_type . ' removed from exemption list: ' . htmlspecialchars($ip_input);
                    $message_type = 'success';
                } else {
                    $message = 'Error removing IP/CIDR from exemption list';
                    $message_type = 'danger';
                }
            } else {
                $message = 'Invalid IP address or CIDR notation format';
                $message_type = 'danger';
            }
            break;
        case 'update_log_monitoring':
            // Define allowed configuration keys for security
            $allowed_config_keys = [
                'ssh_monitoring_enabled', 'ftp_monitoring_enabled',
                'max_ssh_attempts', 'max_ftp_attempts',
                'ssh_block_duration', 'ftp_block_duration',
                'ssh_log_file', 'ftp_log_file',
                'log_check_interval', 'blocking_method',
                'docker_network_preserve'
            ];

            $config_updates = array();

            foreach ($_POST as $key => $value) {
                if (strpos($key, 'config_') === 0) {
                    $setting_name = substr($key, 7); // Remove 'config_' prefix
                    if (in_array($setting_name, $allowed_config_keys)) {
                        $config_updates[$setting_name] = $value;
                    }
                }
            }

            $success_count = 0;
            foreach ($config_updates as $setting => $value) {
                if ($LogMonitor->set_config($setting, $value)) {
                    $success_count++;
                }
            }

            if ($success_count > 0) {
                $message = "Updated $success_count log monitoring settings successfully";
                $message_type = 'success';
            } else {
                $message = 'No settings were updated';
                $message_type = 'warning';
            }
            break;
        case 'unblock_service_ip':
            if (!empty($_POST['ip_address']) && filter_var($_POST['ip_address'], FILTER_VALIDATE_IP)) {
                // Unblock from all services and security manager
                $result1 = $LogMonitor->unblock_ip_from_all_services($_POST['ip_address']);
                $result2 = $SecManager->unblock_ip($_POST['ip_address']);

                if ($result1 || $result2) {
                    $message = 'IP address unblocked from all services: ' . htmlspecialchars($_POST['ip_address']);
                    $message_type = 'success';
                } else {
                    $message = 'Error unblocking IP address - IP may not have been blocked';
                    $message_type = 'danger';
                }
            } else {
                $message = 'Invalid IP address format';
                $message_type = 'danger';
            }
            break;
        case 'sync_blocked_ips':
            try {
                $sync_results = $LogMonitor->sync_blocked_ips();

                if ($sync_results['success']) {
                    if ($sync_results['synced_count'] > 0) {
                        $message = 'Successfully synced ' . $sync_results['synced_count'] . ' IP(s) across all services.';
                        if (!empty($sync_results['errors'])) {
                            $message .= ' Some warnings occurred: ' . implode(', ', array_slice($sync_results['errors'], 0, 3));
                            if (count($sync_results['errors']) > 3) {
                                $message .= ' (and ' . (count($sync_results['errors']) - 3) . ' more)';
                            }
                            $message_type = 'warning';
                        } else {
                            $message_type = 'success';
                        }
                    } else {
                        $message = 'Sync completed - all services are already in sync.';
                        if (!empty($sync_results['errors'])) {
                            $message .= ' Some issues detected: ' . implode(', ', array_slice($sync_results['errors'], 0, 2));
                            $message_type = 'warning';
                        } else {
                            $message_type = 'info';
                        }
                    }
                } else {
                    $message = 'Sync operation failed: ' . implode(', ', $sync_results['errors']);
                    $message_type = 'danger';
                }
            } catch (Exception $e) {
                $message = 'Sync operation failed: Operation error';
                $message_type = 'danger';
                error_log('IP sync operation exception: ' . $e->getMessage());
            }
            break;
    }

    return ['message' => $message, 'type' => $message_type];
}
