<?php
declare (strict_types=1);


namespace App\Entity\Core;

use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\ApiResource;
use App\Entity\Access\Access;
use App\Entity\Organization\Organization;
use App\Repository\Core\NotificationRepository;

//use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JetBrains\PhpStorm\Pure;
use Symfony\Component\Validator\Constraints as Assert;
use App\Enum\Core\NotificationTypeEnum;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Annotation\Context;

/**
 * @todo : A la suite de la migration, il faut supprimer le nom de la table pour avoir une table Notification, et supprimer l'attribut discr.
 *
 * Classe Notification. qui permet de gérer les notifications aux utilisateurs.
 */
#[ApiResource(
    operations: [
        new Get(),
        new GetCollection(
            paginationMaximumItemsPerPage: 20,
            paginationClientItemsPerPage: true,
            order: ['id' => 'DESC']
        )
    ]
)]
//#[Auditable]
#[ORM\Entity(repositoryClass: NotificationRepository::class)]
class Notification extends AbstractInformation
{
    #[ORM\Id]
    #[ORM\Column]
    #[ORM\GeneratedValue]
    private ?int $id = null;

    #[ORM\ManyToOne(inversedBy: 'notifications')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Access $recipientAccess;

    #[ORM\ManyToOne(inversedBy: 'notifications')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Organization $recipientOrganization;

    #[ORM\Column(length: 40, nullable: true)]
    private ?string $name = null;

    #[ORM\Column(type: 'datetime', nullable: true)]
    private ?\DateTimeInterface $createDate;

    #[ORM\Column(type: 'datetime', nullable: true)]
    private ?\DateTimeInterface $updateDate;

    #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
    private mixed $message = [];

    #[ORM\Column(nullable: true)]
    #[Assert\Choice(callback: [NotificationTypeEnum::class, 'toArray'], message: 'invalid-type')]
    private ?string $type = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $link = null;

    #[ORM\Column(type: 'date', nullable: true)]
    #[Context(normalizationContext: [DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
    private ?\DateTimeInterface $availabilityDate = null;

    #[ORM\OneToMany(mappedBy: 'notification', targetEntity: NotificationUser::class, cascade: ['persist'], orphanRemoval: true)]
    private Collection $notificationUsers;

    #[Pure]
    public function __construct()
    {
        $this->notificationUsers = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function setName(?string $name): self
    {
        $this->name = $name;
        return $this;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setRecipientAccess(?Access $recipientAccess): self
    {
        $this->recipientAccess = $recipientAccess;
        return $this;
    }

    public function getRecipientAccess(): ?Access
    {
        return $this->recipientAccess;
    }

    /**
     * @return Organization|null
     */
    public function getRecipientOrganization(): ?Organization
    {
        return $this->recipientOrganization;
    }

    /**
     * @param Organization|null $recipientOrganization
     * @return Notification
     */
    public function setRecipientOrganization(?Organization $recipientOrganization): Notification
    {
        $this->recipientOrganization = $recipientOrganization;
        return $this;
    }

    /**
     * @return \DateTimeInterface|null
     */
    public function getCreateDate(): ?\DateTimeInterface
    {
        return $this->createDate;
    }

    /**
     * @param \DateTimeInterface|null $createDate
     */
    public function setCreateDate(?\DateTimeInterface $createDate): self
    {
        $this->createDate = $createDate;
        return $this;
    }

    /**
     * @return \DateTimeInterface|null
     */
    public function getUpdateDate(): ?\DateTimeInterface
    {
        return $this->updateDate;
    }

    /**
     * @param \DateTimeInterface|null $updateDate
     */
    public function setUpdateDate(?\DateTimeInterface $updateDate): self
    {
        $this->updateDate = $updateDate;
        return $this;
    }

    public function setMessage(mixed $message): self
    {
        $this->message = $message;
        return $this;
    }

    public function getMessage(): mixed
    {
        if (!is_array($this->message)) {
            return ['about' => $this->message];
        }
        return $this->message;
    }

    public function setType(?string $type): self
    {
        $this->type = $type;
        return $this;
    }

    public function getType(): ?string
    {
        return $this->type;
    }

    public function setLink(?string $link): self
    {
        $this->link = $link;
        return $this;
    }

    public function getLink(): ?string
    {
        return $this->link;
    }

    public function getAvailabilityDate(): ?\DateTimeInterface
    {
        return $this->availabilityDate;
    }

    public function setAvailabilityDate(?\DateTime $availabilityDate = null): self
    {
        if ($availabilityDate == null) {
            $availabilityDate = new \DateTime();
        }
        $this->availabilityDate = $availabilityDate;
        return $this;
    }

    public function getNotificationUsers(): Collection
    {
        return $this->notificationUsers;
    }

    public function addNotificationUser(NotificationUser $notificationUsers): self
    {
        if (!$this->notificationUsers->contains($notificationUsers)) {
            $this->notificationUsers[] = $notificationUsers;
            $notificationUsers->setNotification($this);
        }
        return $this;
    }

    public function removeNotificationUser(NotificationUser $notificationUsers): self
    {
        if ($this->notificationUsers->removeElement($notificationUsers)) {
            // set the owning side to null (unless already changed)
            if ($notificationUsers->getNotification() === $this) {
                $notificationUsers->setNotification(null);
            }
        }
        return $this;
    }
}
