<?php

declare(strict_types=1);

namespace NoahVet\Reef\Mapper\Common\One;

use NoahVet\Reef\Mapper\AbstractMapper;
use Symfony\Component\Serializer\Exception\ExceptionInterface;

/**
 * @template EntityType of object
 *
 * @implements AbstractOneMapperInterface<EntityType>
 */
abstract class AbstractOneMapper extends AbstractMapper implements AbstractOneMapperInterface
{
    /**
     * @var EntityType
     */
    protected object $entity;

    /**
     * @template ResponseDtoType of object
     *
     * @param EntityType                    $entity
     * @param class-string<ResponseDtoType> $responseDtoFqcn
     *
     * @return ResponseDtoType
     *
     * @psalm-suppress ImplementedReturnTypeMismatch
     */
    public function mapEntityToResponseDto(
        object $entity,
        string $responseDtoFqcn,
    ): object {
        $data = $this->normalizeEntity($entity);
        $this->postNormalizeEntity($data);

        return $this->serializer->denormalize(
            $data,
            $responseDtoFqcn,
        );
    }

    /**
     * @param EntityType $entity
     *
     * @return array<string, mixed>
     *
     * @throws ExceptionInterface
     */
    public function normalizeEntity(
        object $entity,
    ): array {
        return (array) $this->serializer->normalize($entity);
    }

    /**
     * @return array<string, mixed>
     */
    public function normalizeResponseDto(
        object $responseDto,
    ): array {
        return (array) $this->serializer->normalize($responseDto);
    }

    /**
     * @param array<string, mixed> $data
     */
    protected function postNormalizeEntity(array &$data): void
    {
    }
}
