<?php

declare(strict_types=1);

namespace App\Serializer;

use App\Entity\Document;
use ArrayObject;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

use function is_array;

class DocumentNormalizer implements NormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;

    private const ALREADY_CALLED = 'DOCUMENT_NORMALIZER_ALREADY_CALLED';

    /**
     * @return null|array<string, mixed>|ArrayObject<int|string, mixed>|bool|float|int|string
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): array|ArrayObject|bool|float|int|string|null
    {
        $context[self::ALREADY_CALLED] = true;

        /** @var null|array<string, mixed> $normalized */
        $normalized = $this->normalizer->normalize($data, $format, $context);

        if (is_array($normalized) && $data instanceof Document && $data->getId()) {
            // Remove raw 'path' if present (never expose it to the client)
            unset($normalized['path']);

            // Always provide URL-based access
            $normalized['fileUrl']     = '/api/documents/'.$data->getId().'/file';
            $normalized['downloadUrl'] = '/api/documents/'.$data->getId().'/download';
        }

        return $normalized;
    }

    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        if (isset($context[self::ALREADY_CALLED])) {
            return false;
        }

        return $data instanceof Document;
    }

    /**
     * @return array<class-string, bool>
     */
    public function getSupportedTypes(?string $format): array
    {
        return [
            Document::class => false,
        ];
    }
}
