<?php

namespace App\Entity;

use App\Repository\RemoteCalendarRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

#[ORM\Entity(repositoryClass: RemoteCalendarRepository::class)]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_NAME', fields: ['name'])]
#[UniqueEntity(fields: ['name'], message: 'This name is already in use.')]
class RemoteCalendar extends AbstractEntity
{
    use NameableTrait;

    /**
     * @var Collection<int, OrganizationalUnit>
     */
    #[ORM\OneToMany(mappedBy: 'remoteCalendar', targetEntity: OrganizationalUnit::class)]
    private Collection $organizationalUnits;

    /**
     * @var Collection<int, RemoteCalendarRule>
     */
    #[ORM\OneToMany(mappedBy: 'remoteCalendar', targetEntity: RemoteCalendarRule::class)]
    private Collection $rules;

    public function __construct()
    {
        parent::__construct();
        $this->rules = new ArrayCollection();
    }

    public function getOrganizationalUnits(): Collection
    {
        return $this->organizationalUnits;
    }

    public function setOrganizationalUnits(Collection $organizationalUnits): void
    {
        $this->organizationalUnits = $organizationalUnits;
    }

    /**
     * @return Collection<int, RemoteCalendarRule>
     */
    public function getRules(): Collection
    {
        return $this->rules;
    }

    public function setRules(array $rules): static
    {
        $this->rules->clear();

        foreach ($rules as $rule){
            $this->addRule($rule);
        }

        return $this;
    }

    public function addRule(RemoteCalendarRule $rule): static
    {
        if (!$this->rules->contains($rule)) {
            $this->rules->add($rule);
            $rule->setRemoteCalendar($this);
        }

        return $this;
    }

    public function removeRule(RemoteCalendarRule $rule): static
    {
        if ($this->rules->removeElement($rule)) {
            // set the owning side to null (unless already changed)
            if ($rule->getRemoteCalendar() === $this) {
                $rule->setRemoteCalendar(null);
            }
        }

        return $this;
    }

    public function isAvailable(): bool
    {
        $now = new \DateTime();

        foreach ($this->getRules() as $rule) {
            if ($rule->isRemoteAvailable()) {
                $fromDate = $rule->getAvailableFromDate();
                $toDate = $rule->getAvailableToDate();

                if ($fromDate && $toDate && $fromDate <= $now && $now <= $toDate) {
                    return true;
                }
            } else {
                $dayOfWeek = (int) $now->format('w');
                $adjustedDayOfWeek = ($dayOfWeek + 6) % 7;

                if (!in_array($adjustedDayOfWeek, $rule->getBusyWeekdays())) {
                    return true;
                }

                $currentTime = $now->format('H:i');
                if (!($currentTime >= $rule->getBusyFromHour() && $currentTime <= $rule->getBusyToHour())) {
                    return true;
                }
            }
        }

        return false;
    }
}
