<?php

declare(strict_types=1);

namespace MauticPlugin\DealFlowBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
use Mautic\CoreBundle\Entity\FormEntity;

class DealStage extends FormEntity
{
    public const TABLE_NAME = 'dealflow_stages';

    private ?int $id = null;

    private ?Pipeline $pipeline = null;

    private string $name = '';

    private string $slug = '';

    private int $sortOrder = 0;

    private int $probability = 0;

    private string $stageType = 'open';

    /**
     * @var Collection<int, Deal>
     */
    private Collection $deals;

    public function __construct()
    {
        $this->deals = new ArrayCollection();
    }

    /** @param ORM\ClassMetadata<static> $metadata */
    public static function loadMetadata(ORM\ClassMetadata $metadata): void
    {
        $builder = new ClassMetadataBuilder($metadata);

        $builder->setTable(self::TABLE_NAME)
            ->setCustomRepositoryClass(DealStageRepository::class)
            ->addIndex(['slug'], 'dealflow_stage_slug_idx')
            ->addIndex(['sort_order'], 'dealflow_stage_sort_idx');

        $builder->addId();

        $builder->createManyToOne('pipeline', Pipeline::class)
            ->inversedBy('stages')
            ->addJoinColumn('pipeline_id', 'id', false, false, 'CASCADE')
            ->build();

        $builder->createField('name', 'string')
            ->length(191)
            ->build();

        $builder->createField('slug', 'string')
            ->length(191)
            ->build();

        $builder->createField('sortOrder', 'integer')
            ->columnName('sort_order')
            ->build();

        $builder->createField('probability', 'integer')
            ->build();

        $builder->createField('stageType', 'string')
            ->columnName('stage_type')
            ->length(32)
            ->build();

        $builder->createOneToMany('deals', Deal::class)
            ->mappedBy('stage')
            ->fetchExtraLazy()
            ->build();
    }

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

    public function getPipeline(): ?Pipeline
    {
        return $this->pipeline;
    }

    public function setPipeline(Pipeline $pipeline): self
    {
        $this->pipeline = $pipeline;

        return $this;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->isChanged('name', $name);
        $this->name = $name;

        return $this;
    }

    public function getSlug(): string
    {
        return $this->slug;
    }

    public function setSlug(string $slug): self
    {
        $this->isChanged('slug', $slug);
        $this->slug = $slug;

        return $this;
    }

    public function getSortOrder(): int
    {
        return $this->sortOrder;
    }

    public function setSortOrder(int $sortOrder): self
    {
        $this->isChanged('sortOrder', $sortOrder);
        $this->sortOrder = $sortOrder;

        return $this;
    }

    public function getProbability(): int
    {
        return $this->probability;
    }

    public function setProbability(int $probability): self
    {
        $probability = max(0, min(100, $probability));
        $this->isChanged('probability', $probability);
        $this->probability = $probability;

        return $this;
    }

    public function getStageType(): string
    {
        return $this->stageType;
    }

    public function setStageType(string $stageType): self
    {
        $this->isChanged('stageType', $stageType);
        $this->stageType = $stageType;

        return $this;
    }

    public function isWonStage(): bool
    {
        return 'won' === $this->stageType;
    }

    public function isLostStage(): bool
    {
        return 'lost' === $this->stageType;
    }

    /**
     * @return Collection<int, Deal>
     */
    public function getDeals(): Collection
    {
        return $this->deals;
    }
}
