<?php

declare(strict_types=1);

namespace Seka\Portal\Modul\Terminy\Actions;

use DateTimeZone;
use Eluceo\iCal\Domain\Entity\Calendar;
use Eluceo\iCal\Domain\Entity\Event;
use Eluceo\iCal\Domain\Entity\TimeZone;
use Eluceo\iCal\Domain\ValueObject\DateTime;
use Eluceo\iCal\Domain\ValueObject\GeographicPosition;
use Eluceo\iCal\Domain\ValueObject\Location;
use Eluceo\iCal\Domain\ValueObject\TimeSpan;
use Eluceo\iCal\Domain\ValueObject\Timestamp;
use Eluceo\iCal\Presentation\Component;
use Eluceo\iCal\Presentation\Factory\CalendarFactory;
use Html2Text\Html2Text;
use Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost;

/**
 * Class iCalendarFactory
 *
 * @package Seka\Portal\Modul\Terminy\Actions
 */
class iCalendarFactory
{
    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost $udalost
     *
     * @return \Eluceo\iCal\Presentation\Component
     * @throws \DateInvalidOperationException
     * @throws \DateInvalidTimeZoneException
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \Exception
     */
    public static function make(Udalost $udalost): Component
    {
        $miestoKonania = $udalost->miestoKonania;

        $location = new Location($miestoKonania->adresa);

        if ($miestoKonania->obsahujeGeografickuPolohu()) {
            $location = $location->withGeographicPosition(
                new GeographicPosition($miestoKonania->latitude, $miestoKonania->longitude)
            );
        }

        $desc = (new Html2Text($udalost->popis))->getText();

        $descOut = <<<TEXT
        Druh udalosti: {$udalost->druh->label}
        Stav: {$udalost->stav->label}
        Kapacita: {$udalost->kapacita}
        Registrácia: {$udalost->registracia->label}
        ---
        $desc
        TEXT;

        $event = (new Event())
            ->setSummary($udalost->nazov . ' [' . $udalost->druh->label . ']')
            ->setDescription($descOut ?? '')
            ->setLocation($location)
            ->setOccurrence(
                new TimeSpan(
                    new DateTime($udalost->datum_od->toDateTimeImmutable(), true),
                    new DateTime($udalost->datum_do->toDateTimeImmutable(), true)
                )
            )
            ->touch(new Timestamp($udalost->updated_at->toDateTimeImmutable()));

        $calendar = new Calendar([$event]);
        $calendar->setProductIdentifier(config('app.name'));
        $calendar = $calendar->addTimeZone(TimeZone::createFromPhpDateTimeZone(
            new DateTimeZone(config('app.timezone')),
            $udalost->datum_od->toDateTimeImmutable(),
            $udalost->datum_do->toDateTimeImmutable()
        ));
        $componentFactory = new CalendarFactory();

        return $componentFactory->createCalendar($calendar);
    }
}
