<?php

declare(strict_types=1);

namespace App\Framework\ErrorHandling\View;

use App\Framework\Exception\ErrorHandlerContext;
use App\Framework\Http\Headers;
use App\Framework\Http\HttpResponse;
use App\Framework\Http\Status;

/**
 * Factory für HTTP-Fehlermeldungen
 */
final readonly class ErrorResponseFactory
{
    public function __construct(
        private ErrorViewRendererInterface $htmlRenderer,
        private ErrorViewRendererInterface $apiRenderer
    ) {
    }

    /**
     * Erstellt eine HTTP-Response basierend auf dem ErrorHandlerContext
     */
    public function createResponseFromHandlerContext(ErrorHandlerContext $context, bool $isDebug = false, bool $isApiRequest = false): HttpResponse
    {
        // HTTP-Status aus Metadata extrahieren
        $status = $context->metadata['http_status'] ?? 500;

        // Headers aufbauen
        $headers = new Headers();

        // Content-Type basierend auf Request-Typ
        if ($isApiRequest) {
            $headers = $headers->with('Content-Type', 'application/json; charset=utf-8');
            $body = $this->apiRenderer->renderFromHandlerContext($context, $isDebug);
        } else {
            $headers = $headers->with('Content-Type', 'text/html; charset=utf-8');
            $body = $this->htmlRenderer->renderFromHandlerContext($context, $isDebug);
        }

        // Exception-spezifische Header hinzufügen
        if (isset($context->metadata['additional_headers'])) {
            foreach ($context->metadata['additional_headers'] as $name => $value) {
                $headers = $headers->with($name, $value);
            }
        }

        // Standard Security Header
        $headers = $headers
            ->with('Cache-Control', 'no-store, no-cache, must-revalidate')
            ->with('X-Content-Type-Options', 'nosniff')
            ->with('X-Frame-Options', 'DENY');

        // Security Event Header für Security-Exceptions
        if ($context->exception->metadata['security_event'] ?? false) {
            $headers = $headers->with('X-Security-Event', 'true');

            // Request-ID für Security-Tracking
            $headers = $headers->with('X-Request-ID', $context->request->requestId?->toString() ?? 'unknown');
        }

        return new HttpResponse(
            status: Status::from($status),
            headers: $headers,
            body: $body
        );
    }

    /**
     * Bestimmt, ob es sich um eine API-Anfrage handelt
     */
    public function isApiRequest(): bool
    {
        // Accept-Header prüfen
        $acceptHeader = $_SERVER['HTTP_ACCEPT'] ?? '';
        if (str_contains($acceptHeader, 'application/json')) {
            return true;
        }

        // URL-Pfad prüfen (z.B. /api/...)
        $requestUri = $_SERVER['REQUEST_URI'] ?? '';
        if (str_starts_with($requestUri, '/api/')) {
            return true;
        }

        // Content-Type prüfen
        $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
        if (str_contains($contentType, 'application/json')) {
            return true;
        }

        // X-Requested-With Header prüfen (für AJAX)
        $requestedWith = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '';
        if (strtolower($requestedWith) === 'xmlhttprequest') {
            return true;
        }

        return false;
    }
}
