<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Enum\Serializer;

use InPost\International\Enum\Enum;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

if (!defined('_PS_VERSION_')) {
    exit;
}

final class EnumDenormalizer implements DenormalizerInterface
{
    /**
     * @template T of Enum
     *
     * @param mixed $data
     * @param class-string<T> $type
     * @param string|null $format
     * @param array<string, mixed> $context
     *
     * @return T|null
     */
    public function denormalize($data, $type, $format = null, array $context = []): ?Enum
    {
        if (null === $data) {
            return null;
        }

        if (!is_scalar($data)) {
            throw new InvalidArgumentException(sprintf('Data expected to be scalar, "%s" given.', get_debug_type($data)));
        }

        if (!is_subclass_of($type, Enum::class)) {
            throw new InvalidArgumentException(sprintf('Unsupported type: "%s".', $type));
        }

        return $type::tryFrom($data);
    }

    /**
     * @param mixed $data
     * @param string $type
     * @param string|null $format
     * @param array<string, mixed> $context
     */
    public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
    {
        return is_scalar($data) && is_subclass_of($type, Enum::class);
    }
}
