<?php

declare(strict_types=1);

namespace NoahVet\Reef\Controller\Common;

use NoahVet\Reef\Controller\AbstractController;
use NoahVet\Reef\Mapper\Common\One\Update\AbstractUpdateMapperInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

/**
 * @template EntityType of object
 * @template RequestDtoType of object
 * @template ResponseDtoType of object
 */
abstract class AbstractUpdateController extends AbstractController
{
    /**
     * @param AbstractUpdateMapperInterface<EntityType, RequestDtoType> $mapper
     * @param class-string<RequestDtoType>                              $requestDtoFqcn
     * @param EntityType                                                $existingEntity
     *
     * @return EntityType
     */
    protected function deserializeRequest(
        AbstractUpdateMapperInterface $mapper,
        string $requestDtoFqcn,
        object $existingEntity,
    ): object {
        return $mapper->mapRequestDtoToEntity(
            $mapper->mapDataToRequestDto(
                $this->request->getContent(),
                $requestDtoFqcn,
                $existingEntity,
            ),
        );
    }

    /**
     * @param array<string, mixed> $data
     */
    protected function getResponse(array $data): Response
    {
        return new JsonResponse(
            $data,
            Response::HTTP_OK,
            $this->headers,
        );
    }

    /**
     * @param AbstractUpdateMapperInterface<EntityType, RequestDtoType> $mapper
     * @param EntityType                                                $entity
     * @param class-string<ResponseDtoType>                             $responseDtoFqcn
     *
     * @return array<string, mixed>
     */
    protected function serializeResponse(
        AbstractUpdateMapperInterface $mapper,
        object $entity,
        string $responseDtoFqcn,
    ): array {
        return $mapper->normalizeResponseDto(
            $mapper->mapEntityToResponseDto(
                $entity,
                $responseDtoFqcn,
            ),
        );
    }
}
