<?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\Api\Point\Serializer;

use InPost\International\Api\Point\Model\TimeRange;
use Symfony\Component\Serializer\Exception\BadMethodCallException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;

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

final class TimeRangeArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterface
{
    /**
     * @var (SerializerInterface&DenormalizerInterface)
     */
    private $serializer;

    /**
     * @param mixed $data
     * @param string $type
     * @param string|null $format
     * @param array<string, mixed> $context
     *
     * @return TimeRange[]
     */
    public function denormalize($data, $type, $format = null, array $context = []): array
    {
        if (null === $this->serializer) {
            throw new BadMethodCallException(sprintf('The serializer needs to be set to allow "%s()" to be used.', __METHOD__));
        }

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

        foreach ($data as $key => $value) {
            try {
                $data[$key] = $this->serializer->denormalize($value, TimeRange::class, $format, $context);
            } catch (NotNormalizableValueException $e) {
                // remove invalid time range
                // as of writing this comment, sandbox data contains values such as "24:10 - 26:40"
                unset($data[$key]);
            }
        }

        return $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
    {
        if (null === $this->serializer) {
            throw new BadMethodCallException(sprintf('The serializer needs to be set to allow "%s()" to be used.', __METHOD__));
        }

        return TimeRange::class . '[]' === $type
            && $this->serializer->supportsDenormalization($data, TimeRange::class, $format, $context);
    }

    public function setSerializer(SerializerInterface $serializer): void
    {
        if (!$serializer instanceof DenormalizerInterface) {
            throw new InvalidArgumentException('Expected a serializer that also implements DenormalizerInterface.');
        }

        $this->serializer = $serializer;
    }
}
