<?php

declare(strict_types=1);

namespace App\Application\Security\Events\Input;

use App\Application\Security\{OWASPSecurityEvent};
use App\Application\Security\ValueObjects\{MaskedEmail, OWASPEventIdentifier, OWASPLogLevel};

final class SqlInjectionAttemptEvent implements OWASPSecurityEvent
{
    private ?MaskedEmail $maskedEmail;

    public function __construct(
        public readonly string $attackPayload,
        public readonly string $targetField,
        public readonly string $detectionMethod,
        public readonly ?string $email = null
    ) {
        $this->maskedEmail = $this->email ? MaskedEmail::fromString($this->email) : null;
    }

    public function getOWASPEventIdentifier(): OWASPEventIdentifier
    {
        return OWASPEventIdentifier::maliciousInput('sql_injection');
    }

    public function getOWASPLogLevel(): OWASPLogLevel
    {
        return OWASPLogLevel::ERROR;
    }

    public function getDescription(): string
    {
        return "SQL injection attempt detected";
    }

    /**
     * @return array<string, mixed>
     */
    public function getEventData(): array
    {
        return [
            'attack_payload' => $this->sanitizePayload($this->attackPayload),
            'target_field' => $this->targetField,
            'detection_method' => $this->detectionMethod,
            'username' => $this->maskedEmail?->toString() ?? 'anonymous',
        ];
    }

    public function getMaskedEmail(): ?MaskedEmail
    {
        return $this->maskedEmail;
    }

    private function sanitizePayload(string $payload): string
    {
        // SQL-Injection-Payload nur teilweise loggen für Analyse
        return substr(preg_replace('/[^\w\s\'\";=\-\(\)]/', '***', $payload), 0, 200);
    }
}
