<?php

declare(strict_types=1);

namespace Ekdos\Http\Middleware;

use Ekdos\Support\Json;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as Handler;
use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Exception\HttpNotFoundException;
use Slim\Psr7\Response as Psr7Response;
use Throwable;

/**
 * Ausnahmen werden protokolliert, nicht erzaehlt.
 *
 * Es gibt bewusst kein Info-/Debug-Logging: in das Protokoll gehoert nur, was
 * tatsaechlich schiefgegangen ist. error_log() landet im Fehlerkanal von php-fpm
 * und damit dort, wo auch nginx hinschreibt.
 *
 * Soll spaeter Sentry dazukommen, ist genau eine Zeile noetig -- siehe unten.
 */
final readonly class ErrorHandler implements MiddlewareInterface
{
    public function __construct(private bool $debug) {}

    public function process(Request $request, Handler $handler): Response
    {
        try {
            return $handler->handle($request);
        } catch (HttpMethodNotAllowedException) {
            return Json::error(new Psr7Response(), 'Diese Methode ist für diese Schnittstelle nicht vorgesehen.', 405);
        } catch (HttpNotFoundException) {
            // Kein Fehlerfall, sondern ein Tippfehler in der Adresse. Nicht protokollieren.
            return Json::error(new Psr7Response(), 'Diese Schnittstelle gibt es nicht.', 404);
        } catch (Throwable $exception) {
            error_log(sprintf(
                '[ekdos] %s %s -- %s: %s @ %s:%d',
                $request->getMethod(),
                (string) $request->getUri()->getPath(),
                $exception::class,
                $exception->getMessage(),
                $exception->getFile(),
                $exception->getLine(),
            ));

            // Sentry-Einstiegspunkt: \Sentry\captureException($exception);

            $message = $this->debug
                ? $exception::class . ': ' . $exception->getMessage()
                : 'Im Backend ist ein unerwarteter Fehler aufgetreten.';

            return Json::error(new Psr7Response(), $message, 500);
        }
    }
}
