<?php
declare(strict_types=1);

namespace App\Service;

use App\Entity\Access\Access;
use App\Entity\Core\File;
use App\Entity\Core\Notification;
use App\Enum\Core\NotificationTypeEnum;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;

class Notifier
{
    public function __construct(
        private EntityManagerInterface $em,
        private MercureHub $mercureHub
    ) {}

    /**
     * @param Access $access
     * @param string $name
     * @param string $type
     * @param list<string> $message
     * @param string|null $link
     * @return Notification
     */
    protected function createNotification(
        Access $access,
        string $name,
        string $type,
        array $message,
        string $link = null
    ): Notification {
        $now = new DateTime();

        $notification = new Notification();
        $notification->setName($name)
            ->setRecipientAccess($access)
            ->setRecipientOrganization($access->getOrganization())
            ->setType($type)
            ->setMessage($message)
            ->setLink($link)
            ->setCreateDate($now)
            ->setUpdateDate($now);
        return $notification;
    }

    /**
     * @param Access $access
     * @param string $name
     * @param string $type
     * @param array<string> $message
     * @param string|null $link
     * @return Notification
     */
    public function notify(
        Access $access,
        string $name,
        string $type,
        array $message,
        string $link = null
    ): Notification
    {
        $notification = $this->createNotification($access, $name, $type, $message, $link);

        $this->em->persist($notification);
        $this->em->flush();

        $this->mercureHub->publishCreate($access->getId(), $notification);

        return $notification;
    }

    /**
     * @param Access $access
     * @param File $file
     * @return Notification
     */
    public function notifyExport(
        Access $access,
        File $file
    ): Notification
    {
        return $this->notify(
            $access,
            'export',
            NotificationTypeEnum::FILE()->getValue(),
            ['fileName' => $file->getName()],
            '/api/files/' . $file->getId() . '/download'
        );
    }

    /**
     * @param Access $access
     * @param array<string> $message
     * @return Notification
     */
    public function notifyMessage(
        Access $access,
        array $message
    ): Notification
    {
        return $this->notify(
            $access,
            'message',
            NotificationTypeEnum::MESSAGE()->getValue(),
            $message
        );
    }

    /**
     * @param Access $access
     * @param  list<string> $message
     * @return Notification
     */
    public function notifySystem(
        Access $access,
        array $message
    ): Notification
    {
        return $this->notify(
            $access,
            'message',
            NotificationTypeEnum::SYSTEM()->getValue(),
            $message
        );
    }

    /**
     * @param Access $access
     * @param string $name
     * @param list<string> $message
     * @return Notification
     */
    public function notifyError(
        Access $access,
        string $name,
        array $message
    ): Notification
    {
        return $this->notify(
            $access,
            $name,
            NotificationTypeEnum::ERROR()->getValue(),
            $message
        );
    }

}
