<?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\AdminBundle\Components;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Ferienpass\AdminBundle\LiveComponent\MultiSelect;
use Ferienpass\AdminBundle\LiveComponent\MultiSelectAction;
use Ferienpass\AdminBundle\LiveComponent\MultiSelectHandlerInterface;
use Ferienpass\CoreBundle\Entity\AttendanceStash;
use Ferienpass\CoreBundle\Facade\DecisionsFacade;
use Ferienpass\CoreBundle\Repository\AttendanceRepository;
use Ferienpass\CoreBundle\Repository\AttendanceStashRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveArg;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentToolsTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\ValidatableComponentTrait;

#[AsLiveComponent(route: 'live_component_admin')]
class CommitAttendances extends AbstractController implements MultiSelectHandlerInterface
{
    use ComponentToolsTrait;
    use DefaultActionTrait;
    use ValidatableComponentTrait;

    #[LiveProp(writable: true)]
    public ?AttendanceStash $stash = null;

    #[LiveProp(writable: true)]
    public bool $notify = true;

    public function __construct(private readonly DecisionsFacade $unconfirmedApplications, private readonly AttendanceStashRepository $stashRepository, private readonly AttendanceRepository $attendanceRepository, private readonly EntityManagerInterface $entityManager)
    {
    }

    public function mount(): void
    {
        if (null === $this->stash) {
            $this->stash = $this->stashRepository->findOneBy([]);
        }
    }

    public function getStashes(): array
    {
        return $this->stashRepository->findAll();
    }

    public function getQueryBuilder(): QueryBuilder
    {
        return $this->attendanceRepository->createQueryBuilder('a')
            ->innerJoin('a.participant', 'p')
            ->innerJoin('a.offer', 'o')
            ->innerJoin('o.edition', 'e')
            ->where('a.stash = :stash')
            ->setParameter('stash', $this->stash);
    }

    public function getMs(): MultiSelect
    {
        return new MultiSelect([
            new MultiSelectAction('changeStatus', 'admin_participants_attendances_status', method: 'GET', turboFrame: 'slideover', routeParameters: ['stashed' => 1]),
            new MultiSelectAction('moveToNewStash'),
            new MultiSelectAction('moveToStash', 'admin_stash_move', method: 'GET', turboFrame: 'slideover'),
        ], self::class);
    }

    public function handleMultiSelect(string $action, array $selected, Request $request): Response
    {
        if ('moveToNewStash' === $action) {
            $newStash = new AttendanceStash();
            $this->entityManager->persist($newStash);

            $oldStash = null;
            foreach ($selected as $id) {
                $attendance = $this->attendanceRepository->find($id);
                if ($attendance) {
                    $oldStash = $attendance->getStash();
                    $newStash->addAttendance($attendance);
                }
            }

            $this->entityManager->flush();

            if ($oldStash && $oldStash->getAttendances()->isEmpty()) {
                $this->entityManager->remove($oldStash);
                $this->entityManager->flush();
            }

            return $this->redirectToRoute('admin_commit_attendances');
        }

        return new Response('Action not handled', 400);
    }

    #[LiveAction]
    public function selectStash(#[LiveArg] int $id): void
    {
        $this->stash = $this->stashRepository->find($id);
    }
}
