package com.gnx.telemedicine.util;

import org.jsoup.Jsoup;
import org.jsoup.safety.Safelist;

import java.util.regex.Pattern;

/**
 * Utility class for input sanitization to prevent XSS and injection attacks.
 * Provides methods to clean and validate user input.
 */
public class InputSanitizer {

    // Pattern for SQL injection detection (basic patterns)
    private static final Pattern SQL_INJECTION_PATTERN = Pattern.compile(
        "(?i)(union|select|insert|update|delete|drop|create|alter|exec|execute|script|javascript|onload|onerror)"
    );

    // Pattern for script tags
    private static final Pattern SCRIPT_TAG_PATTERN = Pattern.compile(
        "(?i)<script[^>]*>.*?</script>", Pattern.DOTALL
    );

    // Pattern for event handlers
    private static final Pattern EVENT_HANDLER_PATTERN = Pattern.compile(
        "(?i)(on\\w+\\s*=\\s*[\"'][^\"']*[\"'])"
    );

    /**
     * Sanitizes HTML content by removing dangerous tags and attributes.
     * Uses Jsoup to clean HTML while preserving safe formatting.
     * 
     * @param input The HTML content to sanitize
     * @return Sanitized HTML content
     */
    public static String sanitizeHtml(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }

        // Use Jsoup to clean HTML - allows only safe tags
        Safelist safelist = Safelist.relaxed()
                .addTags("p", "br", "strong", "em", "u", "ol", "ul", "li")
                .addAttributes("a", "href")
                .addProtocols("a", "href", "http", "https");

        return Jsoup.clean(input, safelist);
    }

    /**
     * Sanitizes plain text by removing all HTML tags and special characters.
     * 
     * @param input The text to sanitize
     * @return Plain text without HTML tags
     */
    public static String sanitizeText(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }

        // Remove all HTML tags
        String cleaned = Jsoup.clean(input, Safelist.none());
        
        // Remove leading/trailing whitespace
        return cleaned.trim();
    }

    /**
     * Sanitizes email addresses.
     * 
     * @param email The email to sanitize
     * @return Sanitized email or null if invalid
     */
    public static String sanitizeEmail(String email) {
        if (email == null || email.isEmpty()) {
            return null;
        }

        // Remove whitespace
        email = email.trim().toLowerCase();

        // Basic email validation pattern
        Pattern emailPattern = Pattern.compile(
            "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
        );

        if (!emailPattern.matcher(email).matches()) {
            return null;
        }

        // Sanitize to prevent injection
        return sanitizeText(email);
    }

    /**
     * Sanitizes phone numbers.
     * 
     * @param phone The phone number to sanitize
     * @return Sanitized phone number
     */
    public static String sanitizePhone(String phone) {
        if (phone == null || phone.isEmpty()) {
            return null;
        }

        // Remove all non-digit characters except + and spaces
        phone = phone.replaceAll("[^\\d+\\s()-]", "");
        
        // Remove leading/trailing whitespace
        return phone.trim();
    }

    /**
     * Sanitizes UUID strings.
     * 
     * @param uuid The UUID string to sanitize
     * @return Sanitized UUID or null if invalid
     */
    public static String sanitizeUuid(String uuid) {
        if (uuid == null || uuid.isEmpty()) {
            return null;
        }

        // UUID pattern: 8-4-4-4-12 hexadecimal digits
        Pattern uuidPattern = Pattern.compile(
            "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
        );

        uuid = uuid.trim();
        
        if (!uuidPattern.matcher(uuid).matches()) {
            return null;
        }

        return uuid;
    }

    /**
     * Checks if input contains potentially dangerous SQL injection patterns.
     * 
     * @param input The input to check
     * @return true if potentially dangerous, false otherwise
     */
    public static boolean containsSqlInjection(String input) {
        if (input == null || input.isEmpty()) {
            return false;
        }

        return SQL_INJECTION_PATTERN.matcher(input).find();
    }

    /**
     * Checks if input contains potentially dangerous XSS patterns.
     * 
     * @param input The input to check
     * @return true if potentially dangerous, false otherwise
     */
    public static boolean containsXss(String input) {
        if (input == null || input.isEmpty()) {
            return false;
        }

        return SCRIPT_TAG_PATTERN.matcher(input).find() ||
               EVENT_HANDLER_PATTERN.matcher(input).find();
    }

    /**
     * Sanitizes input for use in SQL queries (parameterized queries are still recommended).
     * Escapes special characters that could be used for SQL injection.
     * 
     * @param input The input to sanitize
     * @return Sanitized input
     */
    public static String sanitizeForSql(String input) {
        if (input == null) {
            return null;
        }

        // Remove SQL comment patterns
        input = input.replace("--", "");
        input = input.replace("/*", "");
        input = input.replace("*/", "");
        
        // Escape single quotes
        input = input.replace("'", "''");
        
        // Remove semicolons (statement terminators)
        input = input.replace(";", "");

        return input.trim();
    }

    /**
     * Sanitizes input for use in file paths.
     * Prevents directory traversal attacks.
     * 
     * @param input The file path to sanitize
     * @return Sanitized file path
     */
    public static String sanitizeFilePath(String input) {
        if (input == null || input.isEmpty()) {
            return null;
        }

        // Remove directory traversal patterns
        input = input.replace("..", "");
        input = input.replace("//", "/");
        input = input.replace("\\\\", "\\");
        
        // Remove leading slashes
        input = input.replaceAll("^[/\\\\]+", "");
        
        // Remove dangerous characters
        input = input.replaceAll("[<>:\"|?*]", "");

        return input.trim();
    }

    /**
     * Sanitizes input for use in URLs.
     * 
     * @param input The URL to sanitize
     * @return Sanitized URL or null if invalid
     */
    public static String sanitizeUrl(String input) {
        if (input == null || input.isEmpty()) {
            return null;
        }

        input = input.trim();
        
        // Only allow http, https protocols
        if (!input.startsWith("http://") && !input.startsWith("https://")) {
            return null;
        }

        // Remove script tags and event handlers
        input = sanitizeHtml(input);
        
        return input;
    }

    /**
     * Validates and sanitizes input length.
     * 
     * @param input The input to validate
     * @param maxLength Maximum allowed length
     * @return Sanitized input or null if exceeds max length
     */
    public static String sanitizeLength(String input, int maxLength) {
        if (input == null) {
            return null;
        }

        input = input.trim();
        
        if (input.length() > maxLength) {
            return null;
        }

        return input;
    }

    /**
     * Sanitizes numeric input.
     * 
     * @param input The numeric string to sanitize
     * @return Sanitized numeric string or null if invalid
     */
    public static String sanitizeNumeric(String input) {
        if (input == null || input.isEmpty()) {
            return null;
        }

        // Remove all non-numeric characters (except decimal point and minus sign)
        String cleaned = input.replaceAll("[^0-9.-]", "");
        
        // Validate it's a valid number
        try {
            Double.parseDouble(cleaned);
            return cleaned;
        } catch (NumberFormatException e) {
            return null;
        }
    }
}

