<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use App\Entity\Trait\DeletableTrait;
use App\Repository\EventDateRepository;
use App\Entity\Trait\TimestampableTrait;
use Doctrine\ORM\Mapping\UniqueConstraint;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

#[ORM\HasLifecycleCallbacks]
#[UniqueEntity(fields: ["event", "date"], message: "admin.event-date.fields.@event+date.errors.already-existing")]
#[UniqueConstraint(name: "IDX_event_date_event_id_date", columns: ["event_id", "date"])]
#[ORM\Entity(repositoryClass: EventDateRepository::class)]
#[ORM\Table(name: 'event_date')]
class EventDate
{
    use TimestampableTrait;
    use DeletableTrait;

    const t_root = 'admin.event-date'; 

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne(inversedBy: 'dates')]
    #[ORM\JoinColumn(name: 'event_id', nullable: false)]
    private ?Event $event = null;

    #[ORM\Column]
    // #[Assert\DateTime(format: "yyyy-MM-dd HH:mm" , message: self::t_root . '.fields.@date.errors.date-invalid')]
    // #[Assert\DateTime(format: "Y-m-d H:i:s" )]
    #[Assert\Type("\DateTimeInterface", message: self::t_root . '.fields.@date.errors.date-invalid')]
    private ?\DateTime $date = null;

    #[Assert\NotBlank(message: self::t_root . ".fields.@place.errors.not-null")]
    #[ORM\Column(length: 255)]
    private ?string $place = null;

    #[Assert\NotBlank(message: self::t_root . ".fields.@city.errors.not-null")]
    #[ORM\Column(length: 255)]
    private ?string $city = null;

    #[ORM\Column(type: 'event_date_status_enum', options: ["default" => "pending"])]
    private ?EventDateStatus $status = EventDateStatus::UNKNOWN;

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

    public function getEvent(): ?Event
    {
        return $this->event;
    }

    public function setEvent(?Event $event): static
    {
        $this->event = $event;

        return $this;
    }

    public function getDate(): ?\DateTime
    {
        return $this->date;
    }

    public function getDateIso(): ?string
    {
        return ($this->date ? $this->date->format(\DateTime::ISO8601) : "");
    }

    public function setDate(\DateTime $date): static
    {
        $this->date = $date;
        if ($this->getEvent()) {
            $this->getEvent()->refreshFirstAndLastDates();
        }
        return $this;
    }

    public function setDateIso(string $date): static
    {
        return $this->setDate(new \DateTime($date));
    }

    public function getPlace(): ?string
    {
        return $this->place;
    }

    public function setPlace(string $place): static
    {
        $this->place = $place;

        return $this;
    }

    public function getCity(): ?string
    {
        return $this->city;
    }

    public function setCity(string $city): static
    {
        $this->city = $city;

        return $this;
    }

    public function getStatus(): ?EventDateStatus
    {
        $computed_status = EventDateStatus::UNKNOWN;
        if ($this->date < new \DateTime("now")) {
            $computed_status = EventDateStatus::DONE;
        } else {
            $computed_status = EventDateStatus::PENDING;
        }

        return EventDateStatus::combine($this->status, $computed_status);
    }

    public function setStatus(EventDateStatus|string $status): static
    {
        if ($status instanceof EventDateStatus) {
            $this->status = $status;
        } else {
            $this->status = EventDateStatus::from($status);
        }

        // dd($this);
        return $this;
    }

    #[ORM\PrePersist]
    #[ORM\PreUpdate]
    public function preUpdateStatus(): void
    {
        $this->status = $this->getStatus();
    }
    
    public function __serialize() : array
    {
        return [
            "id"       =>          $this->id,
            "event"    => ["id" => ($this->event   ? $this->event->getId()   : -1)],
            "date"     =>          $this->getDateIso(),
            "place"    =>          $this->place,
            "city"     =>          $this->city,
            "status"   =>          $this->getStatus(),
        ];
    }

    public function __unserialize(array $data)
    {
        $this->id     = $data["id"];
        $this->event  = null; // ignore
        $this->date   = new \DateTime($data["date"]);
        $this->place  = $data["place"];
        $this->city   = $data["city"];
        $this->status = EventDateStatus::from($data["status"]);
    }
}
