<?php
declare(strict_types=1);

namespace App\Theme;

use InvalidArgumentException;
use JsonException;

final class ThemeProfilePackageService
{
    public const FORMAT = 'quaeriva-theme-profile';
    public const SCHEMA = 1;

    /** @param array<string,mixed> $tokens */
    public static function export(string $name, string $description, array $tokens): string
    {
        $name = trim($name);
        if ($name === '' || self::length($name) > 120) throw new InvalidArgumentException('Theme profile name is invalid.');
        if (self::length($description) > 500) throw new InvalidArgumentException('Theme profile description is too long.');
        $safe = ThemeTokenService::normalize($tokens);
        return json_encode([
            'format' => self::FORMAT,
            'schema' => self::SCHEMA,
            'name' => $name,
            'description' => trim($description),
            'tokens' => $safe,
        ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
    }

    /** @return array{name:string,description:string,tokens:array<string,array<string,string>>} */
    public static function import(string $json): array
    {
        if (strlen($json) > 512 * 1024) throw new InvalidArgumentException('Theme profile package is too large.');
        try { $data = json_decode($json, true, 48, JSON_THROW_ON_ERROR); }
        catch (JsonException $exception) { throw new InvalidArgumentException('Theme profile JSON is invalid.', 0, $exception); }
        if (!is_array($data) || ($data['format'] ?? '') !== self::FORMAT || (int) ($data['schema'] ?? 0) !== self::SCHEMA) {
            throw new InvalidArgumentException('Theme profile package format is invalid.');
        }
        $name = trim((string) ($data['name'] ?? ''));
        $description = trim((string) ($data['description'] ?? ''));
        if ($name === '' || self::length($name) > 120 || self::length($description) > 500 || !is_array($data['tokens'] ?? null)) {
            throw new InvalidArgumentException('Theme profile package metadata is invalid.');
        }
        return ['name'=>$name,'description'=>$description,'tokens'=>ThemeTokenService::normalize($data['tokens'])];
    }

    private static function length(string $value): int { return function_exists('mb_strlen') ? mb_strlen($value, 'UTF-8') : strlen($value); }
}
