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

use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Form\FindAccompanyingPeriodWorkType;
use Chill\PersonBundle\Form\PersonConfimDuplicateType;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use Chill\PersonBundle\Service\AccompanyingPeriodWork\AccompanyingPeriodWorkMergeService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Translation\TranslatableMessage;
use Symfony\Contracts\Translation\TranslatorInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

class AccompanyingPeriodWorkDuplicateController extends AbstractController
{
    public function __construct(private readonly AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository, private readonly TranslatorInterface $translator, private readonly AccompanyingPeriodWorkMergeService $accompanyingPeriodWorkMergeService) {}

    /**
     * @ParamConverter("accompanyingPeriodWork", options={"id": "acpw_id"})
     */
    #[Route(path: '{_locale}/person/accompanying-period/work/{id}/assign-duplicate', name: 'chill_person_accompanying_period_work_assign_duplicate')]
    public function assignDuplicate(AccompanyingPeriodWork $acpw, Request $request): Response
    {
        $accompanyingPeriod = $acpw->getAccompanyingPeriod();

        $this->denyAccessUnlessGranted(
            'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE',
            $acpw,
            'You are not allowed to merge this accompanying period work'
        );

        $form = $this->createForm(FindAccompanyingPeriodWorkType::class, null, ['accompanyingPeriod' => $accompanyingPeriod]);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $acpw2 = $this->accompanyingPeriodWorkRepository->find($form->get('acpw')->getData());

            $direction = $form->get('direction')->getData();

            if ('starting' === $direction) {
                $params = [
                    'acpw1_id' => $acpw->getId(),
                    'acpw2_id' => $acpw2->getId(),
                ];
            } else {
                $params = [
                    'acpw1_id' => $acpw2->getId(),
                    'acpw2_id' => $acpw->getId(),
                ];
            }

            return $this->redirectToRoute('chill_person_acpw_duplicate_confirm', $params);
        }

        return $this->render('@ChillPerson/AccompanyingPeriodWorkDuplicate/assign_acpw_duplicate.html.twig', [
            'accompanyingCourse' => $accompanyingPeriod,
            //            'acpwArray' => $acpwArray,
            'acpw' => $acpw,
            'form' => $form->createView(),
        ]);
    }

    /**
     * @ParamConverter("acpw1", options={"id": "acpw1_id"})
     * @ParamConverter("acpw2", options={"id": "acpw2_id"})
     */
    #[Route(path: '/{_locale}/person/{acpw1_id}/acpw-duplicate/{acpw2_id}/confirm', name: 'chill_person_acpw_duplicate_confirm')]
    public function confirmAction(AccompanyingPeriodWork $acpw1, AccompanyingPeriodWork $acpw2, Request $request): Response
    {
        $accompanyingPeriod = $acpw1->getAccompanyingPeriod();

        try {
            $this->validateMerge($acpw1, $acpw2);
            $form = $this->createForm(PersonConfimDuplicateType::class);

            $form->handleRequest($request);

            if ($form->isSubmitted() && $form->isValid()) {

                $this->accompanyingPeriodWorkMergeService->merge($acpw1, $acpw2);

                $session = $request->getSession();
                if ($session instanceof Session) {
                    $session->getFlashBag()->add('success', new TranslatableMessage('acpw_duplicate.Successfully merged'));
                }


                return $this->redirectToRoute('chill_person_accompanying_period_work_show', ['id' => $acpw1->getId()]);
            }

            return $this->render('@ChillPerson/AccompanyingPeriodWorkDuplicate/confirm.html.twig', [
                'acpw' => $acpw1,
                'acpw2' => $acpw2,
                'accompanyingCourse' => $accompanyingPeriod,
                'form' => $form->createView(),
            ]);
        } catch (\InvalidArgumentException $e) {
            $this->addFlash('error', $this->translator->trans($e->getMessage()));

            return $this->redirectToRoute('chill_person_accompanying_period_work_assign_duplicate', [
                'id' => $acpw1->getId(),
            ]);
        }
    }

    private function validateMerge(AccompanyingPeriodWork $acpw1, AccompanyingPeriodWork $acpw2): void
    {
        $constraints = [
            [$acpw1 === $acpw2, 'acpw_duplicate.You cannot merge a accompanying period work with itself. Please choose a different one'],
        ];

        foreach ($constraints as [$condition, $message]) {
            if ($condition) {
                throw new \InvalidArgumentException($message);
            }
        }
    }
}
