<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Middleware;

/**
 * Input sanitization utilities for preventing XSS and injection attacks.
 *
 * All controller inputs should pass through these methods before use.
 * Vue handles output escaping on the frontend, but we sanitize inputs
 * as defense-in-depth.
 *
 * Part of Issue #64.
 */
class InputSanitizer {

    /**
     * Strip HTML tags and trim whitespace from a string.
     *
     * @param string|null $input Raw input
     * @return string|null Sanitized string, or null if input was null
     */
    public static function sanitizeString(?string $input): ?string {
        if ($input === null) {
            return null;
        }

        // Strip HTML/PHP tags
        $cleaned = strip_tags($input);

        // Trim whitespace
        $cleaned = trim($cleaned);

        return $cleaned;
    }

    /**
     * Sanitize an integer input.
     *
     * @param mixed $input Raw input
     * @return int|null Integer value or null
     */
    public static function sanitizeInt($input): ?int {
        if ($input === null || $input === '') {
            return null;
        }

        $filtered = filter_var($input, FILTER_VALIDATE_INT);
        return $filtered !== false ? $filtered : null;
    }

    /**
     * Sanitize a date string (YYYY-MM-DD format only).
     *
     * @param string|null $input Raw date input
     * @return string|null Valid date string or null
     */
    public static function sanitizeDate(?string $input): ?string {
        if ($input === null || $input === '') {
            return null;
        }

        $cleaned = trim($input);

        // Only allow YYYY-MM-DD format
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $cleaned)) {
            return null;
        }

        // Validate it's a real date
        $parts = explode('-', $cleaned);
        if (!checkdate((int)$parts[1], (int)$parts[2], (int)$parts[0])) {
            return null;
        }

        return $cleaned;
    }

    /**
     * Sanitize an email address.
     *
     * @param string|null $input Raw email input
     * @return string|null Valid email or null
     */
    public static function sanitizeEmail(?string $input): ?string {
        if ($input === null || $input === '') {
            return null;
        }

        $cleaned = trim($input);
        $filtered = filter_var($cleaned, FILTER_VALIDATE_EMAIL);
        return $filtered !== false ? $filtered : null;
    }

    /**
     * Sanitize an array of data with known field types.
     *
     * @param array $data Raw input data
     * @param array $fieldTypes Map of field_name => type ('string'|'int'|'date'|'email'|'text')
     * @return array Sanitized data
     */
    public static function sanitizeArray(array $data, array $fieldTypes): array {
        $sanitized = [];

        foreach ($data as $key => $value) {
            $type = $fieldTypes[$key] ?? 'string';

            $sanitized[$key] = match ($type) {
                'int' => self::sanitizeInt($value),
                'date' => self::sanitizeDate($value),
                'email' => self::sanitizeEmail($value),
                'text' => self::sanitizeString($value), // Same as string but could be extended
                'bool' => (bool)$value,
                'array' => is_array($value) ? $value : [],
                default => is_string($value) ? self::sanitizeString($value) : $value,
            };
        }

        return $sanitized;
    }
}
