<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\PersonBundle\Serializer\Normalizer;

use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use Symfony\Component\Workflow\Registry;

class AccompanyingPeriodWorkEvaluationNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;

    private const IGNORE_EVALUATION = 'evaluation:ignore';

    public function __construct(private readonly Registry $registry, private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly MetadataExtractor $metadataExtractor) {}

    /**
     * @param AccompanyingPeriodWorkEvaluation $object
     */
    public function normalize($object, ?string $format = null, array $context = []): array
    {
        $initial = $this->normalizer->normalize($object, $format, array_merge(
            $context,
            [self::IGNORE_EVALUATION => spl_object_hash($object)],
            [AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => static fn ($object, $format, $context) => $object->getId()]
        ));

        // due to bug: https://api-platform.com/docs/core/serialization/#collection-relation
        // and also: https://github.com/symfony/symfony/issues/36965
        // we have to rewrite the documents as a collection
        $initial['documents'] = $this->normalizer->normalize(
            $object->getDocuments()->getValues(),
            $format,
            $context
        );

        // then, we add normalization for things which are not into the entity

        $initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor(
            AccompanyingPeriodWorkEvaluation::class,
            $object->getId()
        );

        $workflows = $this->entityWorkflowRepository->findBy([
            'relatedEntityClass' => AccompanyingPeriodWorkEvaluation::class,
            'relatedEntityId' => $object->getId(),
        ]);
        $initial['workflows'] = $this->normalizer->normalize($workflows, 'json', $context);

        return $initial;
    }

    public function supportsNormalization($data, ?string $format = null, array $context = []): bool
    {
        return 'json' === $format
            && $data instanceof AccompanyingPeriodWorkEvaluation
            && !\array_key_exists(self::IGNORE_EVALUATION, $context);
    }
}
