<?php
declare(strict_types=1);

namespace App\Framework\Http\Middlewares;

use App\Framework\Http\HttpMiddleware;
use App\Framework\Http\MiddlewareContext;
use App\Framework\Http\MiddlewarePriority;
use App\Framework\Http\MiddlewarePriorityAttribute;
use App\Framework\Http\RequestStateManager;
use App\Framework\Http\ResponseManipulator;

#[MiddlewarePriorityAttribute(MiddlewarePriority::SECURITY)]
final readonly class SecurityHeaderMiddleware implements HttpMiddleware
{
    public function __construct(
        private ResponseManipulator $manipulator,
        private SecurityHeaderConfig $config = new SecurityHeaderConfig()
    ) {}

    public function __invoke(MiddlewareContext $context, callable $next, RequestStateManager $stateManager): MiddlewareContext
    {
        $this->removePoweredByHeader();

        // Nächste Middleware aufrufen
        $resultContext = $next($context);

        // Wenn eine Response vorhanden ist, Security-Header hinzufügen
        if ($resultContext->hasResponse()) {
            $response = $resultContext->response;
            $updatedHeaders = $response->headers;

            // Alle Security-Header hinzufügen
            foreach ($this->getSecurityHeaders() as $name => $value) {
                if ($this->shouldAddHeader($name, $updatedHeaders)) {
                    $updatedHeaders = $updatedHeaders->with($name, $value);
                }
            }

            // Neue Response mit aktualisierten Headers erstellen
            $updatedResponse = $this->manipulator->withHeaders($response, $updatedHeaders);

            return $resultContext->withResponse($updatedResponse);
        }

        return $resultContext;
    }

    private function getSecurityHeaders(): array
    {
        return [
            'Strict-Transport-Security' => $this->config->hstsHeader,
            'X-Frame-Options' => $this->config->frameOptions,
            'X-Content-Type-Options' => 'nosniff',
            'Referrer-Policy' => $this->config->referrerPolicy,
            'Content-Security-Policy' => $this->config->contentSecurityPolicy,
            'Permissions-Policy' => $this->config->permissionsPolicy,
            'X-Permitted-Cross-Domain-Policies' => 'none',
            'Cross-Origin-Embedder-Policy' => $this->config->crossOriginEmbedderPolicy,
            'Cross-Origin-Opener-Policy' => $this->config->crossOriginOpenerPolicy,
            'Cross-Origin-Resource-Policy' => $this->config->crossOriginResourcePolicy,
        ];
    }

    private function shouldAddHeader(string $headerName, $currentHeaders): bool
    {
        // Header nur hinzufügen, wenn er noch nicht gesetzt ist
        return !$currentHeaders->has($headerName);
    }

    private function removePoweredByHeader():void
    {
        if (!headers_sent()) {
            header_remove('X-Powered-By');
            header_remove('Server');
        }
    }
}
