<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\DocStoreBundle\Entity;

use Chill\MainBundle\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;

#[ORM\Entity]
#[ORM\Table(name: 'stored_object_lock', schema: 'chill_doc')]
class StoredObjectLock
{
    #[ORM\Id]
    #[ORM\Column(type: 'uuid', unique: true)]
    private UuidInterface $uuid;

    /**
     * @var Collection<int, User>
     */
    #[ORM\ManyToMany(targetEntity: User::class)]
    #[ORM\JoinTable(name: 'stored_object_lock_user', schema: 'chill_doc')]
    #[ORM\JoinColumn(referencedColumnName: 'uuid', nullable: false)]
    private Collection $users;

    /**
     * @param list<User> $users
     */
    public function __construct(
        #[ORM\ManyToOne(targetEntity: StoredObject::class, inversedBy: 'locks')]
        private StoredObject $storedObject,
        #[ORM\Column(type: 'string', length: 10, nullable: false, enumType: StoredObjectLockMethodEnum::class)]
        private StoredObjectLockMethodEnum $method,
        #[ORM\Column(type: 'datetimetz_immutable', nullable: false)]
        private \DateTimeImmutable $createdAt,
        #[ORM\Column(type: 'text', nullable: false, options: ['default' => ''])]
        private string $token = '',
        #[ORM\Column(type: 'datetimetz_immutable', nullable: true)]
        private ?\DateTimeImmutable $expireAt = null,
        array $users = [],
    ) {
        $this->uuid = Uuid::uuid7();
        $this->users = new ArrayCollection();
        $this->storedObject->addLock($this);

        foreach ($users as $user) {
            $this->addUser($user);
        }
    }

    public function addUser(User $user): void
    {
        if (!$this->users->contains($user)) {
            $this->users->add($user);
        }
    }

    public function removeUser(User $user): void
    {
        $this->users->removeElement($user);
    }

    /**
     * @return Collection<int, User>
     */
    public function getUsers(): Collection
    {
        return $this->users;
    }

    public function setToken(string $token): void
    {
        $this->token = $token;
    }

    public function setExpireAt(?\DateTimeImmutable $expireAt): void
    {
        $this->expireAt = $expireAt;
    }

    public function getUuid(): UuidInterface
    {
        return $this->uuid;
    }

    public function getStoredObject(): StoredObject
    {
        return $this->storedObject;
    }

    public function getMethod(): StoredObjectLockMethodEnum
    {
        return $this->method;
    }

    public function getToken(): string
    {
        return $this->token;
    }

    public function getCreatedAt(): \DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function getExpireAt(): ?\DateTimeImmutable
    {
        return $this->expireAt;
    }

    /**
     * Return true if the lock must be considered as active.
     *
     * A StoredObjectLock is active if there isn't any expiration date, or
     * if the expiration date and time is before the given time.
     */
    public function isActiveAt(\DateTimeImmutable $at): bool
    {
        return null === $this->getExpireAt() || $at < $this->getExpireAt();
    }
}
