<?php

declare(strict_types=1);

namespace Fennec\Http;

/**
 * Réponse HTTP standard et unique du framework, au format JSON.
 *
 * Toujours construite via success() ou error() pour garantir une enveloppe stable :
 * { success, data, meta } en cas de succès, { success, data, error, meta } en cas d'erreur.
 */
final class JsonResponse
{
    /**
     * @param array<string, mixed> $payload
     */
    private function __construct(
        private readonly int $statusCode,
        private readonly array $payload,
    ) {
    }

    /**
     * @param array<string, mixed>|null $meta
     */
    public static function success(mixed $data = null, ?array $meta = null, int $statusCode = 200): self
    {
        return new self($statusCode, [
            'success' => true,
            'data' => $data,
            'meta' => $meta,
        ]);
    }

    /**
     * @param array<string, mixed>|null $details
     */
    public static function error(string $code, string $message, ?array $details = null, int $statusCode = 400): self
    {
        return new self($statusCode, [
            'success' => false,
            'data' => null,
            'error' => [
                'code' => $code,
                'message' => $message,
                'details' => $details,
            ],
            'meta' => null,
        ]);
    }

    /**
     * Émet le code HTTP, l'en-tête Content-Type et le corps JSON de la réponse.
     *
     * @throws \JsonException Si le contenu de la réponse ne peut pas être encodé en JSON.
     */
    public function send(): void
    {
        \http_response_code($this->statusCode);
        \header('Content-Type: application/json');
        echo \json_encode($this->payload, \JSON_THROW_ON_ERROR);
    }

    public function getStatusCode(): int
    {
        return $this->statusCode;
    }

    /**
     * @return array<string, mixed>
     */
    public function getPayload(): array
    {
        return $this->payload;
    }
}
