<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Entity\Offer;

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

trait VariantsTrait
{
    #[ORM\OneToMany(mappedBy: 'variantBase', targetEntity: OfferInterface::class)]
    private Collection $variants;

    #[ORM\ManyToOne(targetEntity: OfferInterface::class, inversedBy: 'variants')]
    #[ORM\JoinColumn(name: 'varbase', referencedColumnName: 'id', onDelete: 'SET NULL')]
    private ?OfferInterface $variantBase = null;

    public function isVariantBase(): bool
    {
        return null === $this->variantBase;
    }

    public function isVariant(): bool
    {
        return !$this->isVariantBase();
    }

    public function isVariantOf(OfferInterface $offer): bool
    {
        return $this->getVariants(true)->contains($offer);
    }

    public function hasVariants(): bool
    {
        return $this->isVariantBase() && \count($this->variants) > 0;
    }

    public function getVariants(bool $include = false): Collection
    {
        if ($this->isVariantBase()) {
            $variants = $this->variants->filter(static fn (OfferInterface $offer) => true);

            if ($include) {
                $variants->add($this);
            }

            return $variants;
        }

        $variants = $this->variantBase->getVariants(true);
        if ($include) {
            return $variants;
        }

        return $variants->filter(fn (OfferInterface $v) => $v->getId() !== $this->getId());
    }

    public function getVariantBase(): ?OfferInterface
    {
        return $this->variantBase;
    }

    public function setVariantBase(?OfferInterface $variantBase): void
    {
        if ($variantBase instanceof OfferInterface && $variantBase->getVariantBase() && $variantBase->getVariantBase()->getId() !== $variantBase->getId()) {
            throw new \LogicException('Not allowed to set non-varbase as varbase');
        }

        $this->variantBase = $variantBase;
    }

    public function getVariantNumber(): ?string
    {
        $variants = $this->getVariants(true)->toArray();
        usort($variants, static fn (OfferInterface $a, OfferInterface $b) => $a->getDateBegin() <=> $b->getDateBegin());

        $k = array_find_key($variants, fn ($v) => $v === $this);
        if (null === $k) {
            return null;
        }

        return new \MessageFormatter('@numbers=roman', '{0, number}')->format([++$k]);
    }
}
