<?php

namespace App\Framework\Http\Middlewares;

use App\Framework\ErrorHandling\ErrorHandler;
use App\Framework\ErrorHandling\ExceptionConverter;
use App\Framework\Http\HttpMiddleware;
use App\Framework\Http\HttpResponse;
use App\Framework\Http\MiddlewareContext;
use App\Framework\Http\MiddlewarePriority;
use App\Framework\Http\MiddlewarePriorityAttribute;
use App\Framework\Http\RequestStateManager;
use App\Framework\Http\RequestIdGenerator;
use App\Framework\Logging\DefaultLogger;
use App\Framework\Validation\Exceptions\ValidationException;

#[MiddlewarePriorityAttribute(MiddlewarePriority::ERROR_HANDLING)]
final readonly class ExceptionHandlingMiddleware implements HttpMiddleware
{
    public function __construct(
        private DefaultLogger      $logger,
        private RequestIdGenerator $requestIdGenerator,
        private ErrorHandler $errorHandler,
    ) {}

    public function __invoke(MiddlewareContext $context, callable $next, RequestStateManager $stateManager): MiddlewareContext
    {
        try {
            return $next($context);
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Throwable $e) {

            $response = $this->errorHandler->createHttpResponse($e, $context);

            return $context->withResponse($response);




            // Detaillierte Fehlerinformationen loggen
            $this->logger->error('Unbehandelte Exception in Middleware-Chain', [
                'exception' => $e,
                'path' => $context->request->path,
                'method' => $context->request->method->value,
            ]);

            // Request-ID für die Antwort holen
            $requestId = $this->requestIdGenerator->generate();

            // Passende HTTP-Response basierend auf der Exception
            $status = ExceptionConverter::getStatusFromException($e);

            // Debug-Modus prüfen
            $isDebug = filter_var($_ENV['APP_DEBUG'] ?? false, FILTER_VALIDATE_BOOLEAN);

            // Response-Body erstellen
            $body = ExceptionConverter::getResponseBody(
                $e,
                $isDebug,
                $requestId->getId()
            );

            $response = new HttpResponse(
                status: $status,
                body: json_encode($body, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
            );

            return $context->withResponse($response);
        }
    }
}
