<?php

namespace WordpressModels\ORM\Entity;

use DateTimeInterface;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Attribute\Context;

/**
 * Entity Mapping for the WordPress comments table.
 *
 * Serialization:
 * - read_comment: The default serialization group for comments.
 * - read_comment_details: The serialization group for comments with more details.
 */
#[
    ORM\Table('comments'),
    ORM\Index(['comment_type']),
    ORM\Index(['comment_approved', 'comment_date_gmt'], name: 'comment_approved_date_gmt'),
    ORM\Index(['comment_date_gmt'], name: 'comment_date_gmt'),
    ORM\Index(['comment_author_email'], name: 'comment_author_email'),
    ORM\Entity,
    ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'wp_comments')
]
class Comment
{
    /**
     * @use GetMetaValueTrait<CommentMeta>
     */
    use GetMetaValueTrait;

    #[ORM\Column(name: 'comment_ID', type: Types::BIGINT, options: ['unsigned' => true])]
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'IDENTITY')]
    #[Groups(['read_comment'])]
    private ?int $id = null;

    #[ORM\Column('comment_post_ID', type: Types::BIGINT, options: ['unsigned' => true])]
    #[Groups(['read_comment_assoc', 'read_comment_post'])]
    private int $objectId;

    #[ORM\Column(name: 'comment_author', type: Types::TEXT, length: 255)]
    #[Groups(['read_comment'])]
    private ?string $commentAuthor = null;

    #[ORM\Column(name: 'comment_author_email', type: Types::STRING, length: 100)]
    #[Groups(['read_comment'])]
    private string $commentAuthorEmail = '';

    #[ORM\Column(name: 'comment_author_url', type: Types::STRING, length: 200)]
    #[Groups(['read_comment'])]
    private string $commentAuthorUrl = '';

    #[ORM\Column(name: 'comment_author_IP', type: Types::STRING, length: 100)]
    #[Groups(['read_comment_details'])]
    private string $commentAuthorIp = '';

    #[ORM\Column(name: 'comment_date', type: Types::DATETIME_MUTABLE, options: ['default' => '0000-00-00 00:00:00'])]
    #[Groups(['read_comment'])]
    private DateTimeInterface $createdAt;

    #[ORM\Column(name: 'comment_date_gmt', type: Types::DATETIME_MUTABLE, options: ['default' => '0000-00-00 00:00:00'])]
    #[Groups(['read_comment_details'])]
    private DateTimeInterface $createdAtGmt;

    #[ORM\Column(name: 'comment_content', type: Types::TEXT, length: 65535)]
    #[Groups(['read_comment'])]
    private ?string $content = null;

    #[ORM\Column(name: 'comment_karma', type: Types::INTEGER)]
    #[Groups(['read_comment'])]
    private int $karma = 0;

    #[ORM\Column(name: 'comment_approved', type: Types::BOOLEAN, length: 20, options: ['default' => true])]
    #[Groups(['read_comment_details'])]
    private bool $approved = true;

    #[ORM\Column(name: 'comment_agent', type: Types::STRING, length: 255)]
    #[Groups(['read_comment_details'])]
    private string $agent = '';

    /**
     * @todo: MappedSuperClass??
     */
    #[ORM\Column(name: 'comment_type', type: Types::STRING, length: 20, options: ['default' => 'comment'])]
    #[Groups(['read_comment'])]
    private string $type = 'comment';

    #[
        ORM\ManyToOne(targetEntity: Comment::class, inversedBy: 'children'),
        ORM\JoinColumn(name: 'comment_parent', referencedColumnName: 'comment_ID')
    ]
    #[Groups(['read_comment_assoc', 'read_comment_parent'])]
    private ?Comment $parent = null;

    /**
     * @var Collection<Comment>
     */
    #[ORM\OneToMany(mappedBy: 'parent', targetEntity: Comment::class)]
    #[Groups(['read_comment_assoc', 'read_comment_children'])]
    private Collection $children;

    #[
        ORM\ManyToOne(targetEntity: User::class, inversedBy: 'comments'),
        ORM\JoinColumn('user_id', referencedColumnName: 'ID')
    ]
    #[Groups(['read_comment_assoc', 'read_comment_author'])]
    private ?User $author = null;

    #[ORM\OneToMany(mappedBy: 'comment', targetEntity: CommentMeta::class, indexBy: 'key')]
    #[Context(normalizationContext: ['groups' => ['read_meta']])]
    #[Groups(['read_comment_assoc', 'read_comment_meta'])]
    private Collection $meta;

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

    public function getObjectId(): int
    {
        return $this->objectId;
    }

    public function setObjectId(int $objectId): Comment
    {
        $this->objectId = $objectId;
        return $this;
    }

    public function getCommentAuthor(): ?string
    {
        return $this->commentAuthor;
    }

    public function setCommentAuthor(?string $commentAuthor): Comment
    {
        $this->commentAuthor = $commentAuthor;
        return $this;
    }

    public function getCommentAuthorEmail(): string
    {
        return $this->commentAuthorEmail;
    }

    public function setCommentAuthorEmail(string $commentAuthorEmail): Comment
    {
        $this->commentAuthorEmail = $commentAuthorEmail;
        return $this;
    }

    public function getCommentAuthorUrl(): string
    {
        return $this->commentAuthorUrl;
    }

    public function setCommentAuthorUrl(string $commentAuthorUrl): Comment
    {
        $this->commentAuthorUrl = $commentAuthorUrl;
        return $this;
    }

    public function getCommentAuthorIp(): string
    {
        return $this->commentAuthorIp;
    }

    public function setCommentAuthorIp(string $commentAuthorIp): Comment
    {
        $this->commentAuthorIp = $commentAuthorIp;
        return $this;
    }

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

    public function setCreatedAt(DateTimeInterface $createdAt): Comment
    {
        $this->createdAt = $createdAt;
        return $this;
    }

    public function getCreatedAtGmt(): DateTimeInterface
    {
        return $this->createdAtGmt;
    }

    public function setCreatedAtGmt(DateTimeInterface $createdAtGmt): Comment
    {
        $this->createdAtGmt = $createdAtGmt;
        return $this;
    }

    public function getContent(): ?string
    {
        return $this->content;
    }

    public function setContent(?string $content): Comment
    {
        $this->content = $content;
        return $this;
    }

    public function getKarma(): int
    {
        return $this->karma;
    }

    public function setKarma(int $karma): Comment
    {
        $this->karma = $karma;
        return $this;
    }

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

    public function setApproved(bool $approved): Comment
    {
        $this->approved = $approved;
        return $this;
    }

    public function getAgent(): string
    {
        return $this->agent;
    }

    public function setAgent(string $agent): Comment
    {
        $this->agent = $agent;
        return $this;
    }

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

    public function setType(string $type): Comment
    {
        $this->type = $type;
        return $this;
    }

    public function getParent(): ?Comment
    {
        return $this->parent->id ? $this->parent : null;
    }

    public function setParent(?Comment $parent): Comment
    {
        $this->parent = $parent;
        return $this;
    }

    public function getChildren(): Collection
    {
        return $this->children;
    }

    public function setChildren(Collection $children): Comment
    {
        $this->children = $children;
        return $this;
    }

    public function getAuthor(): ?User
    {
        return $this->author?->getId() ? $this->author : null;
    }

    public function setAuthor(User $author): Comment
    {
        $this->author = $author;
        return $this;
    }

    public function getMeta(): Collection
    {
        return $this->meta;
    }

    public function setMeta(Collection $meta): Comment
    {
        $this->meta = $meta;
        return $this;
    }

}
