<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CmsBundle\Components;

use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\CmsBundle\Form\RegistrationWelcomeType;
use Ferienpass\CoreBundle\Entity\PostalAddress;
use Ferienpass\CoreBundle\Entity\User;
use Ferienpass\CoreBundle\Repository\ParticipantRepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentToolsTrait;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\LiveCollectionTrait;
use Symfony\UX\LiveComponent\Metadata\UrlMapping;
use Symfony\UX\LiveComponent\ValidatableComponentTrait;

#[AsLiveComponent(template: '@Contao/components/registration_welcome.html.twig', route: 'live_component_cms')]
class RegistrationWelcome extends AbstractController
{
    use ComponentToolsTrait;
    use ComponentWithFormTrait;
    use DefaultActionTrait;
    use LiveCollectionTrait;
    use ValidatableComponentTrait;

    #[LiveProp(writable: true, url: new UrlMapping(as: 'eingabe'))]
    public string $step = 'willkommen';

    public function __construct(private readonly Security $security, private readonly ParticipantRepositoryInterface $participants, #[Autowire(param: 'ferienpass_cms.welcome_steps')] private readonly array $steps, #[Autowire(env: 'MAPBOX_TOKEN')] private readonly string $mapboxToken = '')
    {
    }

    public function mapboxToken(): string
    {
        return $this->mapboxToken;
    }

    #[LiveAction]
    public function continue(): ?Response
    {
        $currentStep = array_search($this->step, $this->steps, true);
        if (false === $currentStep) {
            $this->step = $this->steps[0];

            return null;
        }

        if (\count($this->steps) <= $currentStep + 1) {
            return $this->redirectToRoute('cms', ['to' => 'offer_list']);
        }

        $this->step = $this->steps[$currentStep + 1];

        return null;
    }

    #[LiveAction]
    public function back(): void
    {
        $currentStep = array_search($this->step, $this->steps, true);
        if (false === $currentStep || $currentStep <= 0) {
            $this->step = $this->steps[0];

            return;
        }

        $this->step = $this->steps[$currentStep - 1];
    }

    #[LiveAction]
    public function saveAndContinue(EntityManagerInterface $entityManager): ?Response
    {
        $this->save($entityManager);

        return $this->continue();
    }

    #[LiveAction]
    public function save(EntityManagerInterface $entityManager): void
    {
        $this->submitForm();

        $entityManager->flush();
    }

    protected function instantiateForm(): FormInterface
    {
        $this->ensurePostalAddressExists();
        $this->ensureParticipantExists();

        return $this->createForm(RegistrationWelcomeType::class, $this->security->getUser());
    }

    private function ensurePostalAddressExists(): void
    {
        $user = $this->security->getUser();
        if (!$user instanceof User) {
            return;
        }

        if (!$user->getPostalAddresses()->isEmpty()) {
            return;
        }

        $user->getPostalAddresses()->add(new PostalAddress());
    }

    private function ensureParticipantExists(): void
    {
        $user = $this->security->getUser();
        if (!$user instanceof User) {
            return;
        }

        if (!$user->getParticipants()->isEmpty()) {
            return;
        }

        $user->addParticipant($this->participants->createNew($user));
    }
}
