<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Product\Model;

use CpCreation\VitiCore\Behavior\HasTimestamp;
use CpCreation\VitiCore\Behavior\HasTranslatable;
use CpCreation\VitiCore\Behavior\Impl\Timestamp;
use CpCreation\VitiCore\Behavior\Impl\Translatable;
use CpCreation\VitiCore\Product\Model\Translation\ProductVariantOptionTranslation;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Entity]
#[ORM\Table(name: 'product_variant_option')]
#[ORM\HasLifecycleCallbacks]
class ProductVariantOption implements HasTimestamp, HasTranslatable
{
    use Timestamp;
    use Translatable;

    /**
     * @var Collection<string, TranslationInterface>
     */
    #[Assert\Valid]
    #[ORM\OneToMany(
        targetEntity: ProductVariantOptionTranslation::class,
        mappedBy: 'translatable',
        cascade: ['all'],
        indexBy: 'locale',
        orphanRemoval: true
    )]
    protected $translations;

    #[ORM\Id]
    #[ORM\Column(type: 'uuid')]
    #[ORM\GeneratedValue(strategy: 'NONE')]
    private UuidInterface $id;

    #[ORM\ManyToOne(targetEntity: ProductVariant::class, inversedBy: 'options')]
    #[ORM\JoinColumn(name: 'variant_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
    #[Gedmo\SortableGroup]
    private ?ProductVariant $variant = null;

    #[ORM\Column(type: 'integer', nullable: true)]
    #[Gedmo\SortablePosition]
    private ?int $position = null;

    #[ORM\Column(type: 'integer', options: ['default' => 0])]
    #[Assert\GreaterThanOrEqual(0)]
    private int $price = 0;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $flatFee = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $soldOut = false;

    /**
     * @var Collection<int, ProductVariantOptionImage>
     */
    #[ORM\OneToMany(targetEntity: ProductVariantOptionImage::class, mappedBy: 'option', cascade: ['persist', 'remove'], orphanRemoval: true)]
    #[ORM\OrderBy(['position' => 'ASC'])]
    #[Assert\Valid]
    private Collection $images;

    public function __construct()
    {
        $this->id = Uuid::uuid4();
        $this->translations = new ArrayCollection();
        $this->images = new ArrayCollection();
    }

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

    public function getVariant(): ?ProductVariant
    {
        return $this->variant;
    }

    public function setVariant(?ProductVariant $variant): void
    {
        $this->variant = $variant;
    }

    public function getPosition(): ?int
    {
        return $this->position;
    }

    public function setPosition(?int $position): void
    {
        $this->position = $position;
    }

    public function getPrice(): int
    {
        return max(0, $this->price);
    }

    public function setPrice(?int $price): void
    {
        $this->price = max(0, (int) ($price ?? 0));
    }

    public function isFlatFee(): bool
    {
        return $this->flatFee;
    }

    public function setFlatFee(bool $flatFee): void
    {
        $this->flatFee = $flatFee;
    }

    public function isSoldOut(): bool
    {
        return $this->soldOut;
    }

    public function setSoldOut(bool $soldOut): void
    {
        $this->soldOut = $soldOut;
    }

    public function isAvailable(): bool
    {
        return !$this->isSoldOut();
    }

    public function addImage(ProductVariantOptionImage $image): self
    {
        if (!$this->images->contains($image)) {
            $this->images->add($image);
            $image->setOption($this);
        }

        return $this;
    }

    public function removeImage(ProductVariantOptionImage $image): self
    {
        if ($this->images->removeElement($image) && $image->getOption() === $this) {
            $image->setOption(null);
        }

        return $this;
    }

    /**
     * @return Collection<int, ProductVariantOptionImage>
     */
    public function getImages(): Collection
    {
        return $this->images;
    }
}
