<?php

/*
 * This file is part of the Serenity package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Serenity\CoreBundle\Shared\Normalizer;

use Serenity\CoreBundle\Shared\Common\EmptyInterface;
use Serenity\CoreBundle\Shared\Common\IdentifierInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

final readonly class DoctrineJsonEmptyNormalizer implements NormalizerInterface, DenormalizerInterface
{
    public function __construct(
        #[Autowire(service: 'serializer.normalizer.object')]
        private DenormalizerInterface $objectNormalizer,
    ) {
    }

    public function normalize(mixed $data, ?string $format = null, array $context = []): bool
    {
        if (!$data instanceof EmptyInterface) {
            throw new InvalidArgumentException('The object must implement EmptyInterface with method "isEmpty(): bool".');
        }

        // supportsNormalization() garantit déjà isEmpty() === true
        return false;
    }

    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof EmptyInterface && $data->isEmpty();
    }

    public function getSupportedTypes(?string $format): array
    {
        return [
            EmptyInterface::class => true,
        ];
    }

    public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): ?EmptyInterface
    {
        // On considère uniquement false / null comme “vide”.
        if (null === $data || false === $data) {
            return null;
        }

        /** @var EmptyInterface $obj */
        $obj = $this->objectNormalizer->denormalize($data, $type, $format, $context);

        return $obj;
    }

    public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
    {
        return is_subclass_of($type, EmptyInterface::class) && !is_subclass_of($type, IdentifierInterface::class);
    }
}
