<?php

declare(strict_types=1);

namespace apexl\Io\middleware;

use apexl\Io\exceptions\EntityNotFoundException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Psr7\Factory\ResponseFactory;
use Slim\Psr7\Factory\StreamFactory;

/**
 * Catches {@see EntityNotFoundException} thrown by FindOr404Trait and
 * converts to a 404 JSON response. Lets controllers write a clean
 * `$x = $this->findOr404(...)` one-liner instead of the find/null-guard/
 * return boilerplate. Other exceptions pass through unchanged.
 */
final readonly class EntityNotFoundMiddleware implements MiddlewareInterface
{
    public function __construct(
        private ResponseFactory $responseFactory,
        private StreamFactory   $streamFactory,
    ) {}

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        try {
            return $handler->handle($request);
        } catch (EntityNotFoundException $e) {
            $body   = json_encode(['error' => $e->getMessage()]);
            $stream = $this->streamFactory->createStream($body);
            return $this->responseFactory->createResponse(404)
                ->withHeader('Content-Type', 'application/json')
                ->withBody($stream);
        }
    }
}
