<?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\MainBundle\Controller;

use Chill\MainBundle\Entity\Address;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\SerializerInterface;

class AddressToReferenceMatcherController
{
    public function __construct(private readonly Security $security, private readonly EntityManagerInterface $entityManager, private readonly SerializerInterface $serializer) {}

    #[Route(path: '/api/1.0/main/address/reference-match/{id}/set/reviewed', methods: ['POST'])]
    public function markAddressAsReviewed(Address $address): JsonResponse
    {
        if (!$this->security->isGranted('ROLE_USER')) {
            throw new AccessDeniedHttpException();
        }

        $address->setRefStatus(Address::ADDR_REFERENCE_STATUS_REVIEWED);

        $this->entityManager->flush();

        return new JsonResponse(
            $this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
            JsonResponse::HTTP_OK,
            [],
            true
        );
    }

    /**
     * Set an address back to "to review". Only if the address is in "reviewed" state.
     */
    #[Route(path: '/api/1.0/main/address/reference-match/{id}/set/to_review', methods: ['POST'])]
    public function markAddressAsToReview(Address $address): JsonResponse
    {
        if (!$this->security->isGranted('ROLE_USER')) {
            throw new AccessDeniedHttpException();
        }

        if (Address::ADDR_REFERENCE_STATUS_REVIEWED !== $address->getRefStatus()) {
            throw new AccessDeniedHttpException("forbidden to mark a matching address to 'to review'");
        }

        $address->setRefStatus(Address::ADDR_REFERENCE_STATUS_TO_REVIEW);

        $this->entityManager->flush();

        return new JsonResponse(
            $this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
            JsonResponse::HTTP_OK,
            [],
            true
        );
    }

    #[Route(path: '/api/1.0/main/address/reference-match/{id}/sync-with-reference', methods: ['POST'])]
    public function syncAddressWithReference(Address $address): JsonResponse
    {
        if (null === $address->getAddressReference()) {
            throw new BadRequestHttpException('this address does not have any address reference');
        }

        $address->syncWithReference($address->getAddressReference());

        $this->entityManager->flush();

        return new JsonResponse(
            $this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
            JsonResponse::HTTP_OK,
            [],
            true
        );
    }
}
