<?php

declare(strict_types=1);

namespace App\Application\Security\Events\Session;

use App\Application\Security\OWASPSecurityEvent;
use App\Application\Security\ValueObjects\OWASPEventIdentifier;
use App\Application\Security\ValueObjects\OWASPLogLevel;
use App\Application\Security\ValueObjects\RequestContext;
use App\Application\Security\ValueObjects\SecurityContext;

final readonly class SessionFingerprintMismatchEvent // implements EventInterface, OWASPSecurityEvent
{
    public function __construct(
        private string $sessionId,
        private string $expectedFingerprint,
        private string $actualFingerprint,
        private array $mismatchedComponents,
        private RequestContext $requestContext,
        private SecurityContext $securityContext,
    ) {
    }

    public function getEventIdentifier(): OWASPEventIdentifier
    {
        return new OWASPEventIdentifier(
            eventId: 'AppSec-Session-003',
            eventType: 'session_fingerprint_mismatch',
            category: 'authentication'
        );
    }

    public function getLogLevel(): OWASPLogLevel
    {
        return OWASPLogLevel::WARNING;
    }

    public function getMessage(): string
    {
        return sprintf(
            'Session fingerprint mismatch detected for session %s. Mismatched components: %s',
            substr($this->sessionId, 0, 8) . '...',
            implode(', ', $this->mismatchedComponents)
        );
    }

    public function getRequestContext(): RequestContext
    {
        return $this->requestContext;
    }

    public function getSecurityContext(): SecurityContext
    {
        return $this->securityContext;
    }

    public function getAdditionalData(): array
    {
        return [
            'session_id_prefix' => substr($this->sessionId, 0, 8),
            'expected_fingerprint_hash' => substr($this->expectedFingerprint, 0, 16),
            'actual_fingerprint_hash' => substr($this->actualFingerprint, 0, 16),
            'mismatched_components' => $this->mismatchedComponents,
            'component_count' => count($this->mismatchedComponents),
            'security_impact' => $this->assessSecurityImpact(),
        ];
    }

    private function assessSecurityImpact(): string
    {
        $criticalComponents = ['user_agent', 'ip_prefix'];
        $criticalMismatches = array_intersect($this->mismatchedComponents, $criticalComponents);

        if (count($criticalMismatches) >= 2) {
            return 'high';
        } elseif (count($criticalMismatches) === 1) {
            return 'medium';
        } else {
            return 'low';
        }
    }

    public function getSessionId(): string
    {
        return $this->sessionId;
    }

    public function getMismatchedComponents(): array
    {
        return $this->mismatchedComponents;
    }
}
