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

use Chill\PersonBundle\Form\PersonConfimDuplicateType;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Chill\ThirdPartyBundle\Form\ThirdpartyFindDuplicateType;
use Chill\ThirdPartyBundle\Service\ThirdpartyMergeService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\Translation\TranslatableMessage;
use Symfony\Contracts\Translation\TranslatorInterface;

class ThirdpartyDuplicateController extends AbstractController
{
    public function __construct(private readonly ThirdpartyMergeService $thirdPartyMergeService, private readonly TranslatorInterface $translator) {}

    /**
     * @ParamConverter("thirdparty", options={"id": "thirdparty_id"})
     */
    #[Route(path: '/{_locale}/3party/{thirdparty_id}/find-manually', name: 'chill_thirdparty_find_duplicate')]
    public function findManuallyDuplicateAction(ThirdParty $thirdparty, Request $request)
    {
        $suggested = [];

        if ('child' === $thirdparty->getKind()) {
            $suggested = $thirdparty->getParent()->getChildren();
        }

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

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $thirdparty2 = $form->get('thirdparty')->getData();

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

            if ('starting' === $direction) {
                $params = [
                    'thirdparty1_id' => $thirdparty->getId(),
                    'thirdparty2_id' => $thirdparty2->getId(),
                ];
            } else {
                $params = [
                    'thirdparty1_id' => $thirdparty2->getId(),
                    'thirdparty2_id' => $thirdparty->getId(),
                ];
            }

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

        return $this->render('@ChillThirdParty/ThirdPartyDuplicate/find_duplicate.html.twig', [
            'thirdparty' => $thirdparty,
            'form' => $form->createView(),
        ]);
    }

    /**
     * @ParamConverter("thirdparty1", options={"id": "thirdparty1_id"})
     * @ParamConverter("thirdparty2", options={"id": "thirdparty2_id"})
     */
    #[Route(path: '/{_locale}/3party/{thirdparty1_id}/duplicate/{thirdparty2_id}/confirm', name: 'chill_thirdparty_duplicate_confirm')]
    public function confirmAction(ThirdParty $thirdparty1, ThirdParty $thirdparty2, Request $request)
    {
        try {
            $this->validateThirdpartyMerge($thirdparty1, $thirdparty2);
            $form = $this->createForm(PersonConfimDuplicateType::class);

            $form->handleRequest($request);

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

                $this->thirdPartyMergeService->merge($thirdparty1, $thirdparty2);

                $session = $request->getSession();
                if ($session instanceof Session) {
                    $session->getFlashBag()->add('success', new TranslatableMessage('thirdparty_duplicate.Merge successful'));
                }

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

            return $this->render('@ChillThirdParty/ThirdPartyDuplicate/confirm.html.twig', [
                'thirdparty' => $thirdparty1,
                'thirdparty2' => $thirdparty2,
                'form' => $form->createView(),
            ]);
        } catch (\InvalidArgumentException $e) {
            $this->addFlash('error', $this->translator->trans($e->getMessage()));

            return $this->redirectToRoute('chill_thirdparty_find_duplicate', [
                'thirdparty_id' => $thirdparty1->getId(),
            ]);
        }
    }

    private function validateThirdpartyMerge(ThirdParty $thirdparty1, ThirdParty $thirdparty2): void
    {
        $constraints = [
            [$thirdparty1 === $thirdparty2, 'thirdparty_duplicate.You cannot merge a thirdparty with itself. Please choose a different thirdparty'],
            [$thirdparty1->getKind() !== $thirdparty2->getKind(), 'thirdparty_duplicate.A thirdparty can only be merged with a thirdparty of the same kind'],
            [$thirdparty1->getParent() !== $thirdparty2->getParent(), 'thirdparty_duplicate.Two child thirdparties must have the same parent'],
        ];

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