<?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\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepHold;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Registry;

class WorkflowOnHoldController
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly Security $security,
        private readonly Registry $registry,
        private readonly UrlGeneratorInterface $urlGenerator,
    ) {}

    #[Route(path: '/{_locale}/main/workflow/{id}/hold', name: 'chill_main_workflow_on_hold')]
    public function putOnHold(EntityWorkflow $entityWorkflow, Request $request): Response
    {
        $currentStep = $entityWorkflow->getCurrentStep();
        $currentUser = $this->security->getUser();

        if (!$currentUser instanceof User) {
            throw new AccessDeniedHttpException('only user can put a workflow on hold');
        }

        $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
        $enabledTransitions = $workflow->getEnabledTransitions($entityWorkflow);

        if (0 === count($enabledTransitions)) {
            throw new AccessDeniedHttpException('You are not allowed to apply any transitions to this workflow, therefore you cannot toggle the hold status.');
        }

        $stepHold = new EntityWorkflowStepHold($currentStep, $currentUser);

        $this->entityManager->persist($stepHold);
        $this->entityManager->flush();

        return new RedirectResponse(
            $this->urlGenerator->generate(
                'chill_main_workflow_show',
                ['id' => $entityWorkflow->getId()]
            )
        );
    }

    #[Route(path: '/{_locale}/main/workflow/{id}/remove_hold', name: 'chill_main_workflow_remove_hold')]
    public function removeOnHold(EntityWorkflowStep $entityWorkflowStep): Response
    {
        $user = $this->security->getUser();

        if (!$user instanceof User) {
            throw new AccessDeniedHttpException('only user can remove workflow on hold');
        }

        if (!$entityWorkflowStep->isOnHoldByUser($user)) {
            throw new AccessDeniedHttpException('You are not allowed to remove workflow on hold');
        }

        $hold = $entityWorkflowStep->getHoldsOnStep()->findFirst(fn (int $index, EntityWorkflowStepHold $entityWorkflowStepHold) => $user === $entityWorkflowStepHold->getByUser());

        if (null === $hold) {
            // this should not happens...
            throw new NotFoundHttpException();
        }

        $this->entityManager->remove($hold);
        $this->entityManager->flush();

        return new RedirectResponse(
            $this->urlGenerator->generate(
                'chill_main_workflow_show',
                ['id' => $entityWorkflowStep->getEntityWorkflow()->getId()]
            )
        );
    }
}
