<?php

declare(strict_types=1);

namespace Flowaxy\Support\Helpers;

use function json_decode;
use function json_encode;
use function json_last_error;
use function json_last_error_msg;
use const JSON_ERROR_NONE;
use const JSON_PRETTY_PRINT;
use const JSON_UNESCAPED_SLASHES;
use const JSON_UNESCAPED_UNICODE;

// Хелпер для роботи з JSON
final class JsonHelper
{
    // Кодувати дані в JSON
    public static function encode(mixed $value, int $flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES): string|false
    {
        return json_encode($value, $flags);
    }

    // Декодувати JSON в дані
    public static function decode(string $json, bool $assoc = true, int $depth = 512, int $flags = 0): mixed
    {
        return json_decode($json, $assoc, $depth, $flags);
    }

    // Кодувати дані в JSON з форматуванням
    public static function encodePretty(mixed $value, int $flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES): string|false
    {
        return json_encode($value, $flags | JSON_PRETTY_PRINT);
    }

    // Перевірити, чи рядок є валідним JSON
    public static function isValid(string $json): bool
    {
        json_decode($json);

        return json_last_error() === JSON_ERROR_NONE;
    }

    // Валідувати JSON файл
    public static function validate(string $path): bool
    {
        if (!FileHelper::exists($path)) {
            return false;
        }

        $content = FileHelper::get($path);
        if ($content === false) {
            return false;
        }

        return self::isValid($content);
    }

    // Отримати останню помилку JSON
    public static function getError(): string
    {
        return json_last_error_msg();
    }

    // Прочитати JSON з файлу
    public static function readFile(string $path, bool $assoc = true): mixed
    {
        if (!FileHelper::exists($path)) {
            return false;
        }

        $content = FileHelper::get($path);
        if ($content === false) {
            return false;
        }

        return self::decode($content, $assoc);
    }

    // Записати JSON у файл
    public static function writeFile(string $path, mixed $data, bool $pretty = false): bool
    {
        $json = $pretty ? self::encodePretty($data) : self::encode($data);
        if ($json === false) {
            return false;
        }

        return FileHelper::put($path, $json) !== false;
    }

    // Об'єднати JSON дані
    public static function merge(mixed ...$data): array|false
    {
        $result = [];

        foreach ($data as $item) {
            if (is_string($item)) {
                $item = self::decode($item, true);
                if ($item === null) {
                    return false;
                }
            }

            if (is_array($item)) {
                $result = array_merge_recursive($result, $item);
            } else {
                return false;
            }
        }

        return $result;
    }
}
