<?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\Domain\Enum\RecurrenceType;
use App\Module\ProjectManagement\Infrastructure\Doctrine\DoctrineTaskRecurrenceRepository;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;

#[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')"),
    ],
    normalizationContext: ['groups' => ['task_recurrence:read']],
    denormalizationContext: ['groups' => ['task_recurrence:write']],
)]
#[ORM\Entity(repositoryClass: DoctrineTaskRecurrenceRepository::class)]
class TaskRecurrence
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    #[Groups(['task_recurrence:read', 'task:read'])]
    private ?int $id = null;

    #[ORM\Column(type: 'string', enumType: RecurrenceType::class)]
    #[Groups(['task_recurrence:read', 'task_recurrence:write', 'task:read'])]
    private ?RecurrenceType $type = null;

    #[ORM\Column(type: 'integer')]
    #[Groups(['task_recurrence:read', 'task_recurrence:write', 'task:read'])]
    private int $interval = 1;

    #[ORM\Column(type: 'json', nullable: true)]
    #[Groups(['task_recurrence:read', 'task_recurrence:write', 'task:read'])]
    private ?array $daysOfWeek = null;

    #[ORM\Column(type: 'integer', nullable: true)]
    #[Groups(['task_recurrence:read', 'task_recurrence:write', 'task:read'])]
    private ?int $dayOfMonth = null;

    #[ORM\Column(type: 'integer', nullable: true)]
    #[Groups(['task_recurrence:read', 'task_recurrence:write', 'task:read'])]
    private ?int $weekOfMonth = null;

    #[ORM\Column(type: 'date_immutable', nullable: true)]
    #[Groups(['task_recurrence:read', 'task_recurrence:write', 'task:read'])]
    private ?DateTimeImmutable $endDate = null;

    #[ORM\Column(type: 'integer', nullable: true)]
    #[Groups(['task_recurrence:read', 'task_recurrence:write', 'task:read'])]
    private ?int $maxOccurrences = null;

    #[ORM\Column(type: 'integer')]
    #[Groups(['task_recurrence:read'])]
    private int $occurrenceCount = 0;

    #[ORM\Version]
    #[ORM\Column(type: 'integer')]
    private int $version = 1;

    /** @var Collection<int, Task> */
    #[ORM\OneToMany(targetEntity: Task::class, mappedBy: 'recurrence')]
    private Collection $tasks;

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

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

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

    public function setType(RecurrenceType $type): static
    {
        $this->type = $type;

        return $this;
    }

    public function getInterval(): int
    {
        return $this->interval;
    }

    public function setInterval(int $interval): static
    {
        $this->interval = $interval;

        return $this;
    }

    public function getDaysOfWeek(): ?array
    {
        return $this->daysOfWeek;
    }

    public function setDaysOfWeek(?array $daysOfWeek): static
    {
        $this->daysOfWeek = $daysOfWeek;

        return $this;
    }

    public function getDayOfMonth(): ?int
    {
        return $this->dayOfMonth;
    }

    public function setDayOfMonth(?int $dayOfMonth): static
    {
        $this->dayOfMonth = $dayOfMonth;

        return $this;
    }

    public function getWeekOfMonth(): ?int
    {
        return $this->weekOfMonth;
    }

    public function setWeekOfMonth(?int $weekOfMonth): static
    {
        $this->weekOfMonth = $weekOfMonth;

        return $this;
    }

    public function getEndDate(): ?DateTimeImmutable
    {
        return $this->endDate;
    }

    public function setEndDate(?DateTimeImmutable $endDate): static
    {
        $this->endDate = $endDate;

        return $this;
    }

    public function getMaxOccurrences(): ?int
    {
        return $this->maxOccurrences;
    }

    public function setMaxOccurrences(?int $maxOccurrences): static
    {
        $this->maxOccurrences = $maxOccurrences;

        return $this;
    }

    public function getOccurrenceCount(): int
    {
        return $this->occurrenceCount;
    }

    public function getVersion(): int
    {
        return $this->version;
    }

    /** @return Collection<int, Task> */
    public function getTasks(): Collection
    {
        return $this->tasks;
    }

    public function incrementOccurrenceCount(): static
    {
        ++$this->occurrenceCount;

        return $this;
    }
}
