<?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\Attribute\Context;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Serializer\Attribute\SerializedName;

/**
 * Entity mapping for WordPress users table.
 *
 * Serialization groups:
 * - read_user -- for reading users.
 * - read_user_details -- for reading users with details, like meta.
 * - read_user_secure -- for reading users with secure data.
 */
#[
    ORM\Table('users'),
    ORM\Index(['user_login'], name: 'user_login_key'),
    ORM\Index(['user_email'], name: 'user_email'),
    ORM\Index(['user_nicename'], name: 'user_nicename'),
    ORM\Entity,
    ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'wp_users')
]
class User
{

    /**
     * @use GetMetaValueTrait<PostMeta>
     */
    use GetMetaValueTrait;

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

    #[ORM\Column(name: 'user_login', type: Types::STRING, length: 60)]
    #[Groups(['read_user'])]
    private string $login = '';

    #[ORM\Column(name: 'user_pass', type: Types::STRING, length: 255)]
    #[Groups(['read_user_secure'])]
    private string $password = '';

    #[ORM\Column(name: 'user_nicename', type: Types::STRING, length: 50)]
    #[Groups(['read_user'])]
    private string $niceName = '';

    #[ORM\Column(name: 'user_email', type: Types::STRING, length: 100)]
    #[Groups(['read_user_secure', 'read_user_details'])]
    private string $email = '';

    #[ORM\Column(name: 'user_url', type: Types::STRING, length: 100)]
    #[Groups(['read_user'])]
    private string $url = '';

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

    #[ORM\Column(name: 'user_activation_key', type: Types::STRING, length: 255)]
    #[Groups(['read_user_secure'])]
    private string $activationKey = '';

    /**
     * note: Unused legacy
     */
    #[ORM\Column(name: 'user_status', type: Types::INTEGER)]
    #[Groups(['read_user_secure'])]
    private int $status = 0;

    #[ORM\Column(name: 'display_name', type: Types::STRING, length: 250)]
    #[Groups(['read_user'])]
    private string $displayName = '';

    #[ORM\OneToMany(mappedBy: 'user', targetEntity: UserMeta::class, indexBy: 'key')]
    #[Context(normalizationContext: ['groups' => ['read_meta']])]
    #[Groups(['read_user_assoc', 'read_user_meta'])]
    private Collection $meta;

    #[ORM\OneToMany(mappedBy: 'author', targetEntity: Comment::class)]
    #[Groups(['read_user_assoc', 'read_user_comments'])]
    private Collection $comments;

    #[ORM\OneToMany(mappedBy: 'author', targetEntity: Post::class)]
    #[Groups(['read_user_assoc', 'read_user_posts'])]
    private Collection $posts;

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

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

    public function getLogin(): string
    {
        return $this->login;
    }

    public function setLogin(string $login): User
    {
        $this->login = $login;
        return $this;
    }

    public function getPassword(): string
    {
        return $this->password;
    }

    public function setPassword(string $password): User
    {
        $this->password = $password;
        return $this;
    }

    public function getNiceName(): string
    {
        return $this->niceName;
    }

    public function setNiceName(string $niceName): User
    {
        $this->niceName = $niceName;
        return $this;
    }

    public function getEmail(): string
    {
        return $this->email;
    }

    public function setEmail(string $email): User
    {
        $this->email = $email;
        return $this;
    }

    public function getUrl(): string
    {
        return $this->url;
    }

    public function setUrl(string $url): User
    {
        $this->url = $url;
        return $this;
    }

    public function getRegisteredAt(): DateTimeInterface
    {
        return $this->registeredAt;
    }

    public function setRegisteredAt(DateTimeInterface $registeredAt): User
    {
        $this->registeredAt = $registeredAt;
        return $this;
    }

    public function getActivationKey(): string
    {
        return $this->activationKey;
    }

    public function setActivationKey(string $activationKey): User
    {
        $this->activationKey = $activationKey;
        return $this;
    }

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

    public function setStatus(int $status): User
    {
        $this->status = $status;
        return $this;
    }

    public function getDisplayName(): string
    {
        return $this->displayName;
    }

    public function setDisplayName(string $displayName): User
    {
        $this->displayName = $displayName;
        return $this;
    }

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

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

    public function getComments(): Collection
    {
        return $this->comments;
    }

    public function setComments(Collection $comments): User
    {
        $this->comments = $comments;
        return $this;
    }

    public function getPosts(): Collection
    {
        return $this->posts;
    }

    public function setPosts(Collection $posts): User
    {
        $this->posts = $posts;
        return $this;
    }

    #[Groups(['read_user_simple', 'read_user'])]
    #[SerializedName('roles')]
    public function getRoles()
    {
        $value = $this->getMetaValue('wp_capabilities');

        $roles = wp_roles();

        return array_filter(array_keys($value ?? []), [$roles, 'is_role']);
    }

    #[Groups(['read_user_simple'])]
    #[SerializedName('name')]
    public function getName()
    {
        return $this->displayName;
    }

}
