<?php

namespace App\Entity;

use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JetBrains\PhpStorm\Pure;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 * @UniqueEntity(fields={"username"}, message="There is already an account with this username")
 * @ORM\HasLifecycleCallbacks
 * @method string getUserIdentifier()
 */
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
	/**
	 * @ORM\Id
	 * @ORM\GeneratedValue
	 * @ORM\Column(type="integer")
	 */
	private $id;
	
	/**
	 * @ORM\Column(type="string", length=180, unique=true)
	 */
	private $username;
	
	/**
	 * @ORM\Column(type="json")
	 */
	private $roles = [];
	
	/**
	 * @var string The hashed password
	 * @ORM\Column(type="string")
	 */
	private $password;
	
	/**
	 * @ORM\Column(type="string", length=255, nullable=true)
	 */
	private $firstName;
	
	/**
	 * @ORM\Column(type="string", length=255, nullable=true)
	 */
	private $lastName;
	
	/**
	 * @ORM\Column(type="string", length=255)
	 */
	private $email;
	
	/**
	 * @ORM\Column(type="datetime")
	 */
	private $createdAt;
	
	/**
	 * @ORM\Column(type="datetime", nullable=true)
	 */
	private $lastLoginAt;
	
	/**
	 * @ORM\OneToMany(targetEntity=Blog::class, mappedBy="author")
	 */
	private $blogs;
	
	/**
	 * @ORM\OneToMany(targetEntity=Comment::class, mappedBy="author")
	 */
	private $comments;
	
	/**
	 * @ORM\Column(type="boolean")
	 */
	private $isVerified = false;
	
	#[Pure] public function __construct()
	{
		$this->blogs = new ArrayCollection();
		$this->comments = new ArrayCollection();
	}
	
	public function __toString()
	{
		return $this->username;
	}
	
	public function getId(): ?int
	{
		return $this->id;
	}
	
	/**
	 * A visual identifier that represents this user.
	 *
	 * @see UserInterface
	 */
	public function getUsername(): string
	{
		return (string)$this->username;
	}
	
	public function setUsername(string $username): self
	{
		$this->username = $username;
		
		return $this;
	}
	
	/**
	 * @see UserInterface
	 */
	public function getRoles(): array
	{
		$roles = $this->roles;
		// guarantee every user at least has ROLE_USER
		$roles[] = 'ROLE_USER';
		
		return array_unique($roles);
	}
	
	public function setRoles(array $roles): self
	{
		$this->roles = $roles;
		
		return $this;
	}
	
	/**
	 * @see UserInterface
	 */
	public function getPassword(): string
	{
		return $this->password;
	}
	
	public function setPassword(string $password): self
	{
		$this->password = $password;
		
		return $this;
	}
	
	/**
	 * Returning a salt is only needed, if you are not using a modern
	 * hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
	 *
	 * @see UserInterface
	 */
	public function getSalt(): ?string
	{
		return null;
	}
	
	/**
	 * @see UserInterface
	 */
	public function eraseCredentials()
	{
		// If you store any temporary, sensitive data on the user, clear it here
		// $this->plainPassword = null;
	}
	
	public function getFirstName(): ?string
	{
		return $this->firstName;
	}
	
	public function setFirstName(?string $firstName): self
	{
		$this->firstName = $firstName;
		
		return $this;
	}
	
	public function getLastName(): ?string
	{
		return $this->lastName;
	}
	
	public function setLastName(?string $lastName): self
	{
		$this->lastName = $lastName;
		
		return $this;
	}
	
	public function getEmail(): ?string
	{
		return $this->email;
	}
	
	public function setEmail(string $email): self
	{
		$this->email = $email;
		
		return $this;
	}
	
	public function getCreatedAt(): ?\DateTimeInterface
	{
		return $this->createdAt;
	}
	
	public function setCreatedAt(\DateTimeInterface $createdAt): self
	{
		$this->createdAt = $createdAt;
		
		return $this;
	}
	
	public function getLastLoginAt(): ?\DateTimeInterface
	{
		return $this->lastLoginAt;
	}
	
	public function setLastLoginAt(?\DateTimeInterface $lastLoginAt): self
	{
		$this->lastLoginAt = $lastLoginAt;
		
		return $this;
	}
	
	/**
	 * @return Collection|Blog[]
	 */
	public function getBlogs(): Collection
	{
		return $this->blogs;
	}
	
	public function addBlog(Blog $blog): self
	{
		if (!$this->blogs->contains($blog)) {
			$this->blogs[] = $blog;
			$blog->setAuthor($this);
		}
		
		return $this;
	}
	
	public function removeBlog(Blog $blog): self
	{
		if ($this->blogs->removeElement($blog)) {
			// set the owning side to null (unless already changed)
			if ($blog->getAuthor() === $this) {
				$blog->setAuthor(null);
			}
		}
		
		return $this;
	}
	
	/**
	 * @return Collection|Comment[]
	 */
	public function getComments(): Collection
	{
		return $this->comments;
	}
	
	public function addComment(Comment $comment): self
	{
		if (!$this->comments->contains($comment)) {
			$this->comments[] = $comment;
			$comment->setAuthor($this);
		}
		
		return $this;
	}
	
	public function removeComment(Comment $comment): self
	{
		if ($this->comments->removeElement($comment)) {
			// set the owning side to null (unless already changed)
			if ($comment->getAuthor() === $this) {
				$comment->setAuthor(null);
			}
		}
		
		return $this;
	}
	
	public function isVerified(): bool
	{
		return $this->isVerified;
	}
	
	public function setIsVerified(bool $isVerified): self
	{
		$this->isVerified = $isVerified;
		
		return $this;
	}
	
	public function __call(string $name, array $arguments)
	{
		// TODO: Implement @method string getUserIdentifier()
	}
	
	/**
	 * Gets triggered only on insert
	 
	 * @ORM\PrePersist
	 */
	public function onPrePersist()
	{
		$this->createdAt = new \DateTime();
	}
	
}
