<?php
/**
 * Input Sanitization Functions
 * Sanitize user inputs to prevent XSS and SQL injection
 */

// ============================================
// BASIC SANITIZATION
// ============================================

/**
 * Sanitize string for HTML output (XSS protection)
 * @param string $input
 * @return string
 */
function sanitizeHtml($input) {
    return htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}

/**
 * Sanitize string for database input
 * @param string $input
 * @return string
 */
function sanitizeDb($input) {
    // Remove any potential SQL injection patterns
    $input = strip_tags($input);
    $input = trim($input);
    return $input;
}

/**
 * Sanitize integer value
 * @param mixed $input
 * @param int $default
 * @return int
 */
function sanitizeInt($input, $default = 0) {
    if (is_numeric($input)) {
        return (int)$input;
    }
    return $default;
}

/**
 * Sanitize float value
 * @param mixed $input
 * @param float $default
 * @return float
 */
function sanitizeFloat($input, $default = 0.0) {
    if (is_numeric($input)) {
        return (float)$input;
    }
    return $default;
}

/**
 * Sanitize email address
 * @param string $email
 * @return string|false
 */
function sanitizeEmail($email) {
    $email = trim($email);
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);
    return filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : false;
}

/**
 * Sanitize URL
 * @param string $url
 * @return string|false
 */
function sanitizeUrl($url) {
    $url = trim($url);
    $url = filter_var($url, FILTER_SANITIZE_URL);
    return filter_var($url, FILTER_VALIDATE_URL) ? $url : false;
}

/**
 * Sanitize mobile number
 * @param string $mobile
 * @return string
 */
function sanitizeMobile($mobile) {
    // Remove all non-numeric characters
    $mobile = preg_replace('/[^0-9]/', '', $mobile);
    
    // Remove leading zero if present
    $mobile = ltrim($mobile, '0');
    
    // Ensure 10 digits
    if (strlen($mobile) > 10) {
        $mobile = substr($mobile, -10);
    }
    
    return $mobile;
}

/**
 * Sanitize name (alphabets, spaces, hyphens, apostrophes)
 * @param string $name
 * @return string
 */
function sanitizeName($name) {
    // Remove any characters that are not letters, spaces, hyphens, or apostrophes
    $name = preg_replace('/[^a-zA-Z\s\-\']/', '', $name);
    $name = trim($name);
    // Capitalize first letter of each word
    $name = ucwords(strtolower($name));
    return $name;
}

/**
 * Sanitize username
 * @param string $username
 * @return string
 */
function sanitizeUsername($username) {
    // Allow only alphanumeric, underscore, and dot
    $username = preg_replace('/[^a-zA-Z0-9_\.]/', '', $username);
    $username = strtolower(trim($username));
    return $username;
}

/**
 * Sanitize text area (preserve line breaks but remove XSS)
 * @param string $text
 * @param bool $preserveLineBreaks
 * @return string
 */
function sanitizeTextarea($text, $preserveLineBreaks = true) {
    $text = trim($text);
    $text = strip_tags($text);
    if ($preserveLineBreaks) {
        $text = nl2br($text);
    }
    return $text;
}

// ============================================
// ADVANCED SANITIZATION
// ============================================

/**
 * Sanitize array recursively
 * @param array $array
 * @return array
 */
function sanitizeArray($array) {
    $result = [];
    foreach ($array as $key => $value) {
        $key = sanitizeHtml($key);
        if (is_array($value)) {
            $result[$key] = sanitizeArray($value);
        } else {
            $result[$key] = sanitizeHtml($value);
        }
    }
    return $result;
}

/**
 * Sanitize input with multiple rules
 * @param mixed $input
 * @param array $rules
 * @return mixed
 */
function sanitizeWithRules($input, $rules = []) {
    foreach ($rules as $rule) {
        switch ($rule) {
            case 'html':
                $input = sanitizeHtml($input);
                break;
            case 'int':
                $input = sanitizeInt($input);
                break;
            case 'float':
                $input = sanitizeFloat($input);
                break;
            case 'email':
                $input = sanitizeEmail($input);
                break;
            case 'url':
                $input = sanitizeUrl($input);
                break;
            case 'mobile':
                $input = sanitizeMobile($input);
                break;
            case 'name':
                $input = sanitizeName($input);
                break;
            case 'username':
                $input = sanitizeUsername($input);
                break;
            case 'trim':
                $input = trim($input);
                break;
            case 'strip_tags':
                $input = strip_tags($input);
                break;
            case 'lowercase':
                $input = strtolower($input);
                break;
            case 'uppercase':
                $input = strtoupper($input);
                break;
            case 'no_spaces':
                $input = preg_replace('/\s+/', '', $input);
                break;
            case 'alphanumeric':
                $input = preg_replace('/[^a-zA-Z0-9]/', '', $input);
                break;
        }
    }
    return $input;
}

// ============================================
// SQL INJECTION PREVENTION
// ============================================

/**
 * Escape string for SQL (when not using prepared statements)
 * @param string $string
 * @return string
 */
function escapeSql($string) {
    global $pdo;
    if (isset($pdo)) {
        return $pdo->quote($string);
    }
    return addslashes($string);
}

/**
 * Prepare LIKE query parameter
 * @param string $term
 * @return string
 */
function prepareLikeTerm($term) {
    $term = trim($term);
    $term = addcslashes($term, '%_');
    return "%$term%";
}

// ============================================
// FILE SANITIZATION
// ============================================

/**
 * Sanitize filename
 * @param string $filename
 * @return string
 */
function sanitizeFilename($filename) {
    // Remove path information
    $filename = basename($filename);
    
    // Replace spaces with underscores
    $filename = str_replace(' ', '_', $filename);
    
    // Remove special characters
    $filename = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', $filename);
    
    // Convert to lowercase
    $filename = strtolower($filename);
    
    return $filename;
}

/**
 * Sanitize file extension
 * @param string $filename
 * @param array $allowedExtensions
 * @return string|false
 */
function sanitizeFileExtension($filename, $allowedExtensions = []) {
    $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    
    if (!empty($allowedExtensions) && !in_array($extension, $allowedExtensions)) {
        return false;
    }
    
    return $extension;
}

// ============================================
// OUTPUT SANITIZATION
// ============================================

/**
 * Sanitize output for JSON
 * @param mixed $data
 * @return string
 */
function sanitizeJson($data) {
    return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
}

/**
 * Sanitize output for CSV
 * @param string $string
 * @return string
 */
function sanitizeCsv($string) {
    // Escape for CSV
    if (strpos($string, '"') !== false || strpos($string, ',') !== false || strpos($string, "\n") !== false) {
        $string = '"' . str_replace('"', '""', $string) . '"';
    }
    return $string;
}

/**
 * Sanitize output for XML
 * @param string $string
 * @return string
 */
function sanitizeXml($string) {
    $string = htmlspecialchars($string, ENT_XML1, 'UTF-8');
    return $string;
}

// ============================================
// SESSION & COOKIE SANITIZATION
// ============================================

/**
 * Sanitize session variable
 * @param string $key
 * @param mixed $default
 * @return mixed
 */
function sanitizeSession($key, $default = null) {
    if (isset($_SESSION[$key])) {
        return sanitizeHtml($_SESSION[$key]);
    }
    return $default;
}

/**
 * Sanitize cookie value
 * @param string $key
 * @param mixed $default
 * @return mixed
 */
function sanitizeCookie($key, $default = null) {
    if (isset($_COOKIE[$key])) {
        return sanitizeHtml($_COOKIE[$key]);
    }
    return $default;
}

// ============================================
// REQUEST SANITIZATION
// ============================================

/**
 * Sanitize GET parameter
 * @param string $key
 * @param mixed $default
 * @param array $rules
 * @return mixed
 */
function sanitizeGet($key, $default = null, $rules = []) {
    if (isset($_GET[$key])) {
        $value = $_GET[$key];
        if (!empty($rules)) {
            $value = sanitizeWithRules($value, $rules);
        } else {
            $value = sanitizeHtml($value);
        }
        return $value;
    }
    return $default;
}

/**
 * Sanitize POST parameter
 * @param string $key
 * @param mixed $default
 * @param array $rules
 * @return mixed
 */
function sanitizePost($key, $default = null, $rules = []) {
    if (isset($_POST[$key])) {
        $value = $_POST[$key];
        if (!empty($rules)) {
            $value = sanitizeWithRules($value, $rules);
        } else {
            $value = sanitizeHtml($value);
        }
        return $value;
    }
    return $default;
}

/**
 * Sanitize REQUEST parameter
 * @param string $key
 * @param mixed $default
 * @param array $rules
 * @return mixed
 */
function sanitizeRequest($key, $default = null, $rules = []) {
    if (isset($_REQUEST[$key])) {
        $value = $_REQUEST[$key];
        if (!empty($rules)) {
            $value = sanitizeWithRules($value, $rules);
        } else {
            $value = sanitizeHtml($value);
        }
        return $value;
    }
    return $default;
}

/**
 * Get sanitized POST array
 * @param array $keys
 * @return array
 */
function sanitizePostArray($keys = []) {
    $result = [];
    foreach ($_POST as $key => $value) {
        if (empty($keys) || in_array($key, $keys)) {
            if (is_array($value)) {
                $result[$key] = sanitizeArray($value);
            } else {
                $result[$key] = sanitizeHtml($value);
            }
        }
    }
    return $result;
}

// ============================================
// SERVER VARIABLE SANITIZATION
// ============================================

/**
 * Sanitize server variable
 * @param string $key
 * @param string $default
 * @return string
 */
function sanitizeServer($key, $default = '') {
    if (isset($_SERVER[$key])) {
        return sanitizeHtml($_SERVER[$key]);
    }
    return $default;
}

/**
 * Get client IP address (sanitized)
 * @return string
 */
function getClientIp() {
    $ip = '';
    if (isset($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    
    // Validate IP address
    if (!filter_var($ip, FILTER_VALIDATE_IP)) {
        $ip = '0.0.0.0';
    }
    
    return $ip;
}

/**
 * Get user agent (sanitized)
 * @return string
 */
function getUserAgent() {
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    return sanitizeHtml($userAgent);
}

// ============================================
// BULK SANITIZATION
// ============================================

/**
 * Sanitize entire input array
 * @param array $data
 * @param array $rules
 * @return array
 */
function sanitizeInput($data, $rules = []) {
    $sanitized = [];
    foreach ($data as $key => $value) {
        if (isset($rules[$key])) {
            $sanitized[$key] = sanitizeWithRules($value, $rules[$key]);
        } else {
            $sanitized[$key] = sanitizeHtml($value);
        }
    }
    return $sanitized;
}

/**
 * Common input validation rules for forms
 */
return [
    'login' => [
        'username' => ['trim', 'html'],
        'password' => ['trim']
    ],
    'profile' => [
        'full_name' => ['trim', 'name'],
        'email' => ['trim', 'email'],
        'mobile' => ['trim', 'mobile']
    ],
    'case' => [
        'patient_name' => ['trim', 'name'],
        'patient_mobile' => ['trim', 'mobile'],
        'patient_age' => ['int'],
        'chief_complaint' => ['trim', 'html']
    ]
];