<?php

declare(strict_types=1);

namespace Seka\Portal\Modul\Terminy\Services\External\Calendar\Google;

use Exception;
use Html2Text\Html2Text;
use Illuminate\Support\Facades\Log;
use Koksosk\Base32Hex;
use Seka\Portal\Modul\Terminy\Entities\Dtos\UdalostDTO;
use Seka\Portal\Modul\Terminy\Services\External\Calendar\CalendarService;
use Spatie\GoogleCalendar\Event;

/**
 *
 */
final class GoogleCalendarService implements CalendarService
{
    /**
     *
     */
    private const ID_PREFIX = 'google-cal-portal-terminy-id';

    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Dtos\UdalostDTO $udalost
     */
    public function createEvent(UdalostDTO $udalost): void
    {
        $this->saveEvent($udalost);
    }

    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Dtos\UdalostDTO $udalost
     */
    public function updateEvent(UdalostDTO $udalost): void
    {
        $this->saveEvent($udalost);
    }

    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Dtos\UdalostDTO $udalost
     */
    public function deleteEvent(UdalostDTO $udalost): void
    {
        $googleCalEvent = new Event();
        $googleCalEvent = $this->fillGoogleCalEvent($googleCalEvent, $udalost);

        try {
            $googleCalEvent = Event::find($googleCalEvent->googleEvent->getId());
            $googleCalEvent->delete();
        } catch (Exception $e) {
            Log::error($e->getMessage(), $e->getTrace());
        }
    }

    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Dtos\UdalostDTO $udalost
     */
    private function saveEvent(UdalostDTO $udalost): void
    {
        $exists = false;
        $googleCalEvent = new Event();
        $googleCalEvent = $this->fillGoogleCalEvent($googleCalEvent, $udalost);

        try {
            $exists = Event::find($googleCalEvent->googleEvent->getId())->exists();
        } catch (Exception $e) {
            Log::error($e->getMessage(), $e->getTrace());
        } finally {
            if ($exists) {
                $googleCalEvent->save('updateEvent');
            } else {
                $googleCalEvent->save('insertEvent');
            }
        }
    }

    /**
     * @param \Spatie\GoogleCalendar\Event                        $event
     * @param \Seka\Portal\Modul\Terminy\Entities\Dtos\UdalostDTO $udalost
     *
     * @return \Spatie\GoogleCalendar\Event
     */
    private function fillGoogleCalEvent(Event $event, UdalostDTO $udalost): Event
    {
        $event->id = $this->hashId($udalost->id);
        $event->name = sprintf('%s [%s]', $udalost->nazov, $udalost->stav->label);
        $event->startDateTime = $udalost->datum_od;
        $event->endDateTime = $udalost->datum_do;
        $event->location = $udalost->miesto_konania->adresa;
        $event->description = $this->fillDescription($udalost);

        return $event;
    }

    /**
     * @param int $udalostId
     *
     * @return string
     */
    private function hashId(int $udalostId): string
    {
        return strtolower(
            Base32Hex::encode(
                sprintf('%s-%d', self::ID_PREFIX, $udalostId)
            )
        );
    }

    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Dtos\UdalostDTO $udalost
     *
     * @return string
     */
    private function fillDescription(UdalostDTO $udalost): string
    {
        $popis = (new Html2Text($udalost->popis))->getText();

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