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

use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\AdminBundle\Section\SectionComponentInterface;
use Ferienpass\CoreBundle\Entity\Offer\OfferInterface;
use Ferienpass\CoreBundle\Settings\PageConfigManager;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
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;

#[AsLiveComponent(template: '@FerienpassAdmin/components/Offer/OfferDates.html.twig', route: 'live_component_admin')]
class OfferDates extends AbstractController implements SectionComponentInterface
{
    use ComponentToolsTrait;
    use DefaultActionTrait;

    #[LiveProp]
    public OfferInterface $offer;

    #[LiveProp(writable: true, hydrateWith: 'hydrateDateTime', dehydrateWith: 'dehydrateDateTime', onUpdated: 'setDirty')]
    public ?\DateTime $applicationDeadline = null;

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

    #[LiveProp]
    public bool $isDirty = false;

    #[LiveProp]
    public array $sections = [];

    #[LiveProp]
    public ?string $section = null;

    #[LiveProp]
    public bool $isReadonly = false;

    public string $message = '';

    private readonly string $timezone;

    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly PageConfigManager $pageConfigManager
    ) {
        $this->timezone = $this->pageConfigManager->getPageConfig()->getTimezone();
    }

    public function mount(OfferInterface $offer): void
    {
        $this->offer = $offer;
        $this->applicationDeadline = $this->offer->getApplicationDeadline();
    }

    public function hydrateDateTime(?string $value): ?\DateTime
    {
        if (!$value) {
            return null;
        }

        try {
            return new \DateTime($value, new \DateTimeZone($this->timezone));
        } catch (\DateMalformedStringException) {
            return null;
        }
    }

    public function dehydrateDateTime(?\DateTime $value): ?string
    {
        if (!$value) {
            return null;
        }

        return (clone $value)->setTimezone(new \DateTimeZone($this->timezone))->format('Y-m-d\TH:i');
    }

    public function setDirty(): void
    {
        $this->isDirty = true;
    }

    #[LiveAction]
    public function save(#[LiveArg] ?string $nextSection = null, #[LiveArg] ?string $redirect = null): ?Response
    {
        $this->denyAccessUnlessGranted('edit', $this->offer);

        if ($this->applicationDeadline) {
            $this->offer->setApplicationDeadline((clone $this->applicationDeadline)->setTimezone(new \DateTimeZone(date_default_timezone_get())));
        } else {
            $this->offer->setApplicationDeadline(null);
        }
        $this->entityManager->flush();

        $this->isDirty = false;

        if ($nextSection || $redirect) {
            $this->addFlash('success', ['type' => 'success', 'title' => 'Daten gespeichert', 'message' => 'Die Änderungen wurden erfolgreich übernommen.']);
        } else {
            $this->message = 'Die Änderungen wurden erfolgreich übernommen.';
        }

        $this->dispatchBrowserEvent('live:saved', ['success' => true]);

        if ($nextSection) {
            return $this->redirectToRoute('admin_offers_edit', ['uuid' => $this->offer->getUuid()->toBase58(), 'section' => $nextSection]);
        }
        if ($redirect) {
            return $this->redirectToRoute($redirect, ['uuid' => $this->offer->getUuid()->toBase58()]);
        }

        return null;
    }

    public static function getSectionName(): string
    {
        return 'dates';
    }

    public static function getSectionScope(): string
    {
        return 'offer';
    }
}
