<?php

declare(strict_types=1);

namespace App\Framework\Performance;

use App\Framework\Http\HttpMiddleware;
use App\Framework\Http\MiddlewareContext;
use App\Framework\Http\Response;
use App\Framework\Config\Configuration;
use App\Framework\Http\ResponseManipulator;

readonly class PerformanceMiddleware implements XHttpMiddleware
{
    public function __construct(
        private PerformanceMeter $performanceMeter,
        private Configuration    $config
    ) {}

    public function __invoke(MiddlewareContext $context, callable $next): MiddlewareContext
    {
        $request = $context->request;
        // Marker für Anfrage-Start setzen
        $this->performanceMeter->mark('request_start', PerformanceCategory::SYSTEM);

        // Messung für Anfrageverarbeitung starten
        $this->performanceMeter->startMeasure('request_processing', PerformanceCategory::SYSTEM);

        // Anfrage weiterleiten
        $response = $next($request);

        // Messung beenden
        $this->performanceMeter->endMeasure('request_processing');
        $this->performanceMeter->mark('request_end', PerformanceCategory::SYSTEM);

        // Performance-Bericht hinzufügen, wenn Debug-Modus aktiv
        if ($this->config->get('debug', false) && !$request->isAjax()) {
            // Nur für HTML-Antworten
            $contentType = $response->headers->get('Content-Type', '');
            if (str_contains($contentType, 'text/html') || empty($contentType)) {
                $this->appendPerformanceReport($response);
            } else {
                $this->addPerformanceHeaders($response);
            }
        } elseif ($this->config->get('debug', false) && $request->isAjax()) {
            // Für AJAX-Anfragen Header hinzufügen
            $this->addPerformanceHeaders($response);
        }

        return $response;
    }

    private function appendPerformanceReport(Response $response): void
    {
        $body = $response->body;

        // Suchen nach dem schließenden </body> Tag
        $closingBodyPos = strripos($body, '</body>');

        if ($closingBodyPos !== false) {
            $report = $this->performanceMeter->generateHtmlReport();

            // Report vor dem schließenden </body> Tag einfügen
            $newBody = substr($body, 0, $closingBodyPos);
            $newBody .= $report;
            $newBody .= substr($body, $closingBodyPos);

            $response = new ResponseManipulator()->withBody($response, $newBody);
            //$response->setBody($newBody);
        }
    }

    private function addPerformanceHeaders(Response $response): void
    {
        $report = $this->performanceMeter->generateReport();

        $response->headers->set('X-Performance-Time', sprintf('%.2f ms', $report['summary']['total_time_ms']));
        $response->headers->set('X-Performance-Memory', sprintf('%.2f MB', $report['summary']['total_memory_mb']));
    }
}
