<?php

declare(strict_types=1);

namespace Fennec\Exception;

use Fennec\Http\JsonResponse;
use Fennec\Routing\MethodNotAllowedException;

/**
 * Traduit toute exception non gérée en JsonResponse — garantit qu'aucune erreur PHP
 * brute n'est jamais renvoyée au client.
 *
 * Ne renvoie jamais le message technique de l'exception au client (§6 des conventions) :
 * chaque type est mappé vers un message générique en français, sauf ValidationException
 * dont les "details" champ par champ sont déjà pensés pour être lus par le client.
 */
final class ExceptionHandler
{
    public function __construct(private readonly bool $debug)
    {
    }

    public function handle(\Throwable $exception): JsonResponse
    {
        return match (true) {
            $exception instanceof NotFoundException => JsonResponse::error(
                'NOT_FOUND',
                'La ressource demandée est introuvable.',
                null,
                404,
            ),
            $exception instanceof UnauthorizedException => JsonResponse::error(
                'UNAUTHORIZED',
                'Authentification requise.',
                null,
                401,
            ),
            $exception instanceof ForbiddenException => JsonResponse::error(
                'FORBIDDEN',
                'Vous n\'avez pas les droits suffisants pour effectuer cette action.',
                null,
                403,
            ),
            $exception instanceof ValidationException => JsonResponse::error(
                'VALIDATION_ERROR',
                'Les données envoyées sont invalides.',
                $exception->getDetails(),
                422,
            ),
            $exception instanceof MethodNotAllowedException => JsonResponse::error(
                'METHOD_NOT_ALLOWED',
                'Cette méthode HTTP n\'est pas autorisée pour cette ressource.',
                null,
                405,
            ),
            default => $this->handleUnexpected($exception),
        };
    }

    private function handleUnexpected(\Throwable $exception): JsonResponse
    {
        $details = $this->debug
            ? ['exception' => $exception::class, 'message' => $exception->getMessage(), 'trace' => $exception->getTraceAsString()]
            : null;

        return JsonResponse::error('INTERNAL_ERROR', 'Une erreur interne est survenue.', $details, 500);
    }
}
