<?php

declare(strict_types=1);

namespace App\Module\ProjectManagement\Domain\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use App\Module\ProjectManagement\Infrastructure\ApiPlatform\State\WorkflowDeleteProcessor;
use App\Module\ProjectManagement\Infrastructure\Doctrine\DoctrineWorkflowRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Validator\Constraints as Assert;

#[ApiResource(
    operations: [
        new GetCollection(paginationEnabled: false, security: "is_granted('project-management.projects.view') or is_granted('project-management.tasks.view')"),
        new Get(security: "is_granted('project-management.projects.view') or is_granted('project-management.tasks.view')"),
        new Post(security: "is_granted('project-management.projects.manage') or is_granted('project-management.tasks.manage')"),
        new Patch(security: "is_granted('project-management.projects.manage') or is_granted('project-management.tasks.manage')"),
        new Delete(security: "is_granted('project-management.projects.manage') or is_granted('project-management.tasks.manage')", processor: WorkflowDeleteProcessor::class),
    ],
    normalizationContext: ['groups' => ['workflow:read']],
    denormalizationContext: ['groups' => ['workflow:write']],
    order: ['position' => 'ASC'],
)]
#[ORM\Entity(repositoryClass: DoctrineWorkflowRepository::class)]
#[UniqueEntity(fields: ['name'], message: 'Ce nom de workflow est déjà utilisé.')]
class Workflow
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    #[Groups(['workflow:read', 'project:read', 'task_status:read'])]
    private ?int $id = null;

    #[ORM\Column(length: 255, unique: true)]
    #[Groups(['workflow:read', 'workflow:write', 'project:read'])]
    #[Assert\NotBlank]
    private ?string $name = null;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    #[Groups(['workflow:read', 'workflow:write'])]
    private bool $isDefault = false;

    #[ORM\Column(type: 'integer', options: ['default' => 0])]
    #[Groups(['workflow:read', 'workflow:write'])]
    private int $position = 0;

    /** @var Collection<int, TaskStatus> */
    #[ORM\OneToMany(targetEntity: TaskStatus::class, mappedBy: 'workflow', cascade: ['persist', 'remove'], orphanRemoval: true)]
    #[ORM\OrderBy(['position' => 'ASC'])]
    #[Groups(['workflow:read', 'project:read'])]
    private Collection $statuses;

    public function __construct()
    {
        $this->statuses = new ArrayCollection();
    }

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

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

    public function setName(string $name): static
    {
        $this->name = $name;

        return $this;
    }

    public function isDefault(): bool
    {
        return $this->isDefault;
    }

    public function setIsDefault(bool $isDefault): static
    {
        $this->isDefault = $isDefault;

        return $this;
    }

    public function getPosition(): int
    {
        return $this->position;
    }

    public function setPosition(int $position): static
    {
        $this->position = $position;

        return $this;
    }

    /** @return Collection<int, TaskStatus> */
    public function getStatuses(): Collection
    {
        return $this->statuses;
    }

    public function addStatus(TaskStatus $status): static
    {
        if (!$this->statuses->contains($status)) {
            $this->statuses->add($status);
            $status->setWorkflow($this);
        }

        return $this;
    }

    public function removeStatus(TaskStatus $status): static
    {
        $this->statuses->removeElement($status);

        return $this;
    }
}
