<?php
namespace Api\Helpers;

use Psr\Log\LoggerInterface;

class Json
{
    /**
     * Invia una risposta JSON coerente.
     *
     * @param mixed $data
     * @param int $status
     * @param bool $pretty
     * @param LoggerInterface|null $logger opzionale per loggare errori di encoding
     * @return void
     */
    public static function send($data, int $status = 200, bool $pretty = false, ?LoggerInterface $logger = null): void
    {
        if (!headers_sent()) {
            http_response_code($status);
            header('Content-Type: application/json; charset=utf-8');
        }

        $options = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
        if ($pretty) {
            $options |= JSON_PRETTY_PRINT;
        }

        try {
            $json = json_encode($data, $options | JSON_THROW_ON_ERROR);
            echo $json;
        } catch (\JsonException $e) {
            if ($logger) {
                $logger->error('JSON encode error', ['error' => $e->getMessage()]);
            }
            // fallback minimale: non esporre dettagli sensibili
            if (!headers_sent()) {
                http_response_code(500);
                header('Content-Type: application/json; charset=utf-8');
            }
            echo json_encode(['error' => 'Internal Server Error']);
        }

        exit;
    }

    /**
     * Invia un errore JSON standardizzato.
     *
     * @param string|array $message
     * @param int $status
     * @param LoggerInterface|null $logger
     * @return void
     */
    public static function sendError($message = 'Bad Request', int $status = 400, ?LoggerInterface $logger = null): void
    {
        $payload = [
            'error' => \is_array($message) ? $message : ['message' => $message]
        ];

        if ($logger) {
            $logger->warning('API error response', ['status' => $status, 'payload' => $payload]);
        }

        self::send($payload, $status);
    }

    /**
     * Legge e decodifica il body JSON della richiesta.
     *
     * @param bool $assoc
     * @param int $maxBytes limite in byte per proteggere da payload troppo grandi
     * @return mixed|null
     */
    public static function readJsonBody(bool $assoc = true, int $maxBytes = 1048576)
    {
        $raw = file_get_contents('php://input');

        if ($raw === false || $raw === '') {
            return null;
        }

        if (strlen($raw) > $maxBytes) {
            throw new \RuntimeException('Payload too large', 413);
        }

        try {
            return json_decode($raw, $assoc, 512, JSON_THROW_ON_ERROR);
        } catch (\JsonException $e) {
            throw new \InvalidArgumentException('Invalid JSON payload', 400);
        }
    }

    /**
     * Risposta per errori di validazione con formato coerente.
     *
     * @param array $errors mappa campo => messaggi
     * @param int $status
     * @return void
     */
    public static function validationError(array $errors, int $status = 422): void
    {
        $payload = [
            'error' => 'validation_failed',
            'details' => $errors
        ];
        self::send($payload, $status);
    }
}
