<?php

declare(strict_types=1);

namespace App\Module\ProjectManagement\Domain\Entity;

use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use App\Module\ProjectManagement\Infrastructure\ApiPlatform\State\TaskDocumentProcessor;
use App\Module\ProjectManagement\Infrastructure\ApiPlatform\State\TaskDocumentProvider;
use App\Module\ProjectManagement\Infrastructure\EventListener\TaskDocumentListener;
use App\Shared\Domain\Contract\UserInterface;
use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;

#[ApiResource(
    operations: [
        new GetCollection(paginationEnabled: false, security: "is_granted('project-management.tasks.view')", provider: TaskDocumentProvider::class),
        new Get(security: "is_granted('project-management.tasks.view')", provider: TaskDocumentProvider::class),
        new Post(
            security: "is_granted('project-management.tasks.manage')",
            processor: TaskDocumentProcessor::class,
            deserialize: false,
        ),
        new Delete(security: "is_granted('project-management.tasks.manage')"),
    ],
    normalizationContext: ['groups' => ['task_document:read']],
    denormalizationContext: ['groups' => ['task_document:write']],
    order: ['id' => 'DESC'],
)]
#[ApiFilter(SearchFilter::class, properties: ['task' => 'exact'])]
#[ORM\Entity]
#[ORM\EntityListeners([TaskDocumentListener::class])]
class TaskDocument
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    #[Groups(['task_document:read', 'task:read'])]
    private ?int $id = null;

    #[ORM\ManyToOne(targetEntity: Task::class, inversedBy: 'documents')]
    #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
    #[Groups(['task_document:read', 'task_document:write'])]
    private ?Task $task = null;

    #[ORM\Column(length: 255)]
    #[Groups(['task_document:read', 'task:read'])]
    private ?string $originalName = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Groups(['task_document:read', 'task:read'])]
    private ?string $fileName = null;

    /**
     * Chemin relatif sur le partage SMB lorsque le document est un lien vers un fichier du partage
     * (au lieu d'un fichier uploadé stocké sur disque). Mutuellement exclusif avec fileName.
     */
    #[ORM\Column(length: 1024, nullable: true)]
    #[Groups(['task_document:read', 'task:read'])]
    private ?string $sharePath = null;

    #[ORM\Column(length: 100)]
    #[Groups(['task_document:read', 'task:read'])]
    private ?string $mimeType = null;

    #[ORM\Column]
    #[Groups(['task_document:read', 'task:read'])]
    private ?int $size = null;

    #[ORM\Column(type: 'datetime_immutable')]
    #[Groups(['task_document:read', 'task:read'])]
    private ?DateTimeImmutable $createdAt = null;

    #[ORM\ManyToOne(targetEntity: UserInterface::class)]
    #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
    #[Groups(['task_document:read', 'task:read'])]
    private ?UserInterface $uploadedBy = null;

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

    public function getTask(): ?Task
    {
        return $this->task;
    }

    public function setTask(?Task $task): static
    {
        $this->task = $task;

        return $this;
    }

    public function getOriginalName(): ?string
    {
        return $this->originalName;
    }

    public function setOriginalName(string $originalName): static
    {
        $this->originalName = $originalName;

        return $this;
    }

    public function getFileName(): ?string
    {
        return $this->fileName;
    }

    public function setFileName(?string $fileName): static
    {
        $this->fileName = $fileName;

        return $this;
    }

    public function getSharePath(): ?string
    {
        return $this->sharePath;
    }

    public function setSharePath(?string $sharePath): static
    {
        $this->sharePath = $sharePath;

        return $this;
    }

    public function isShareLink(): bool
    {
        return null !== $this->sharePath;
    }

    public function getMimeType(): ?string
    {
        return $this->mimeType;
    }

    public function setMimeType(string $mimeType): static
    {
        $this->mimeType = $mimeType;

        return $this;
    }

    public function getSize(): ?int
    {
        return $this->size;
    }

    public function setSize(int $size): static
    {
        $this->size = $size;

        return $this;
    }

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

    public function setCreatedAt(DateTimeImmutable $createdAt): static
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    public function getUploadedBy(): ?UserInterface
    {
        return $this->uploadedBy;
    }

    public function setUploadedBy(?UserInterface $uploadedBy): static
    {
        $this->uploadedBy = $uploadedBy;

        return $this;
    }
}
