<?php

namespace App\Entity;

use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

#[ORM\Entity]
class Document
{
    public const STATUS_ACTIVE = 'ACTIVE';
    public const STATUS_ARCHIVED = 'ARCHIVED';

    #[ORM\Id]
    #[ORM\Column(type: 'uuid')]
    private Uuid $id;

    #[ORM\Column(length: 255)]
    private string $title;

    #[ORM\Column(length: 20)]
    private string $status = self::STATUS_ACTIVE;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: false)]
    private User $createdBy;

    #[ORM\Column]
    private DateTimeImmutable $createdAt;

    #[ORM\OneToMany(
        targetEntity: DocumentVersion::class,
        mappedBy: 'document',
        cascade: ['persist'],
        orphanRemoval: true
    )]
    private Collection $versions;

    #[ORM\ManyToOne]
    private ?DocumentVersion $currentVersion = null;

    // ---------------------------------------------------------
    // Tags via Join-Entity (DocumentTag)
    // ---------------------------------------------------------

    #[ORM\OneToMany(
        targetEntity: DocumentTag::class,
        mappedBy: 'document',
        cascade: ['persist', 'remove'],
        orphanRemoval: true
    )]
    private Collection $documentTags;

    public function __construct()
    {
        $this->id = Uuid::v4();
        $this->createdAt = new DateTimeImmutable();
        $this->versions = new ArrayCollection();
        $this->documentTags = new ArrayCollection();
    }

    // ---------------------------------------------------------
    // Basic Getters
    // ---------------------------------------------------------

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

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

    public function getTitle(): string
    {
        return $this->title;
    }

    public function setTitle(string $title): static
    {
        $this->title = $title;
        return $this;
    }

    public function getStatus(): string
    {
        return $this->status;
    }

    public function archive(): void
    {
        $this->status = self::STATUS_ARCHIVED;
    }

    public function getCreatedBy(): User
    {
        return $this->createdBy;
    }

    public function setCreatedBy(User $createdBy): void
    {
        $this->createdBy = $createdBy;
    }

    /**
     * @return Collection<int, DocumentVersion>
     */
    public function getVersions(): Collection
    {
        return $this->versions;
    }

    public function addVersion(DocumentVersion $version): void
    {
        if (!$this->versions->contains($version)) {
            $this->versions->add($version);
            $version->setDocument($this);
        }
    }

    public function getCurrentVersion(): ?DocumentVersion
    {
        return $this->currentVersion;
    }

    public function setCurrentVersion(?DocumentVersion $version): void
    {
        $this->currentVersion = $version;
    }

    // ---------------------------------------------------------
    // Tag API (Join-Entity basiert)
    // ---------------------------------------------------------

    /**
     * @return Collection<int, DocumentTag>
     */
    public function getDocumentTags(): Collection
    {
        return $this->documentTags;
    }

    /**
     * Convenience: liefert direkt Tag-Objekte
     *
     * @return Tag[]
     */
    public function getTags(): array
    {
        return array_map(
            fn (DocumentTag $dt) => $dt->getTag(),
            $this->documentTags->toArray()
        );
    }

    public function hasTag(Tag $tag): bool
    {
        foreach ($this->documentTags as $dt) {
            if ($dt->getTag()->getId()->equals($tag->getId())) {
                return true;
            }
        }
        return false;
    }

    public function addTag(Tag $tag): void
    {
        if ($this->hasTag($tag)) {
            return;
        }

        $this->documentTags->add(new DocumentTag($this, $tag));
    }

    public function removeTag(Tag $tag): void
    {
        foreach ($this->documentTags as $dt) {
            if ($dt->getTag()->getId()->equals($tag->getId())) {
                $this->documentTags->removeElement($dt);
                return;
            }
        }
    }
}