<?phpnamespace Whater\Domain\Product\Model;use BornFree\TacticianDomainEvent\Recorder\ContainsRecordedEvents;use BornFree\TacticianDomainEvent\Recorder\EventRecorderCapabilities;use Doctrine\Common\Collections\Collection;use Ramsey\Uuid\Uuid;use Whater\Domain\Common\Exception\InvalidUUIDException;use Whater\Domain\Product\Exception\InvalidCartOrderPackageStatusException;/** * Class CartOrderPackage * * @package Whater\Domain\Product\Model */class CartOrderPackage implements ContainsRecordedEvents{    use EventRecorderCapabilities;    public const PACKAGE_STATUS_PENDING = "READY_TO_SEND";    public const PACKAGE_STATUS_CANCELLED = "CANCELLED";    public const PACKAGE_STATUS_PROCESSING = "PROCESSING";    public const PACKAGE_STATUS_IN_TRANSIT = "IN_TRANSIT";    public const PACKAGE_STATUS_DELIVERED = "DELIVERED";    public const PACKAGE_STATUS_RETURNED = "RETURNED";    public const PACKAGE_STATUS_EXCEPTION = "EXCEPTION";    /**     * @var string     */    private $uuid;    /**     * @var CartOrder     */    protected $cartOrder;    /**     * @var Collection     */    private $cartOrderItems;    /**     * @var string     */    private $status;    /**     * @var string     */    private $shipmentTrackingCode;    /**     * @var float     */    private $totalShippingCost;    /**     * @var string     */    private $shippingCountry;    /**     * @var string     */    private $shippingAddress;    /**     * @var string     */    private $shippingTown;    /**     * @var string     */    private $shippingPostalCode;    /**     * @var string     */    private $shippingMethodName;    /**     * @var string     */    private $notes;    /**     * @var string     */    protected $trackingUrl;    /**     * @var \DateTime     */    private $createdAt;    /**     * @var null|\DateTime     */    private $updatedAt;    /**     * @var null|\DateTime     */    private $shippedAt;    /**     * @param string $CartOrderPackage     */    public function __construct(        ?string $cartOrderPackageId = null,        CartOrder $cartOrder,        Collection $cartOrderItems,        ?string $status    ) {        try {            $this->uuid = Uuid::fromString($cartOrderPackageId ?: Uuid::uuid4())->toString();        } catch (\InvalidArgumentException $e) {            throw new InvalidUUIDException();        }        switch ($status) {            case CartOrderPackage::PACKAGE_STATUS_PENDING:            case CartOrderPackage::PACKAGE_STATUS_CANCELLED:            case CartOrderPackage::PACKAGE_STATUS_PROCESSING:            case CartOrderPackage::PACKAGE_STATUS_IN_TRANSIT:            case CartOrderPackage::PACKAGE_STATUS_DELIVERED:            case CartOrderPackage::PACKAGE_STATUS_RETURNED:            case CartOrderPackage::PACKAGE_STATUS_EXCEPTION:                $this->status = $status;                break;            default:                throw new InvalidCartOrderPackageStatusException();        }        $this->cartOrder = $cartOrder;        $this->cartOrderItems = $cartOrderItems;        $this->createdAt = new \DateTime();        $this->updatedAt = new \DateTime();    }    public function updateShipmentTrackingCode(        ?string $shipmentTrackingCode = null,        ?\DateTime $shippedAt = null    ) {        $this->shipmentTrackingCode = $shipmentTrackingCode;        $this->shippedAt = $shippedAt;    }    public function updateStatus(        string $status    ) {        switch ($status) {            case CartOrderPackage::PACKAGE_STATUS_PENDING:            case CartOrderPackage::PACKAGE_STATUS_CANCELLED:            case CartOrderPackage::PACKAGE_STATUS_PROCESSING:            case CartOrderPackage::PACKAGE_STATUS_IN_TRANSIT:            case CartOrderPackage::PACKAGE_STATUS_DELIVERED:            case CartOrderPackage::PACKAGE_STATUS_RETURNED:            case CartOrderPackage::PACKAGE_STATUS_EXCEPTION:                $this->status = $status;                break;            default:                throw new InvalidCartOrderPackageStatusException();        }        $this->updatedAt = new \DateTime();        return $this;    }    public function updateShippingData(        float $totalShippingCost = 0,        ?string $shippingCountry = null,        ?string $shippingAddress = null,        ?string $shippingTown = null,        ?string $shippingPostalCode = null,        ?string $shippingMethodName = null    ) {        $this->totalShippingCost = $totalShippingCost;        $this->shippingCountry = $shippingCountry;        $this->shippingAddress = $shippingAddress;        $this->shippingTown = $shippingTown;        $this->shippingPostalCode = $shippingPostalCode;        $this->shippingMethodName = $shippingMethodName;    }    public function updateNotes(        string $notes    ) {        $this->notes = $notes;        $this->updatedAt = new \DateTime();    }    public function updateTrackingUrl(        ?string $trackingUrl = null    ) {        $this->trackingUrl = $trackingUrl;    }    /**     * @return string     */    public function id(): string    {        return $this->uuid;    }    /**     * @return CartOrder     */    public function cartOrder(): CartOrder    {        return $this->cartOrder;    }    /**     * @return Collection     */    public function cartOrderItems(): Collection    {        return $this->cartOrderItems;    }    public function cartItem(int $index)    {        if (count($this->cartOrderItems()) >= $index) {            return $this->cartOrderItems()->get($index);        }        return null;    }    /**     * @return string     */    public function status(): string    {        return $this->status;    }    /**     * @return float     */    public function totalShippingCost(): float    {        return $this->totalShippingCost;    }    /**     * @return string     */    public function shippingCountry(): ?string    {        return $this->shippingCountry;    }    /**     * @return string     */    public function shippingAddress(): ?string    {        return $this->shippingAddress;    }    /**     * @return string     */    public function shippingPostalCode(): ?string    {        return $this->shippingPostalCode;    }    /**     * @return string     */    public function shippingTown(): ?string    {        return $this->shippingTown;    }    /**     * @return string     */    public function shippingMethodName(): ?string    {        return $this->shippingMethodName;    }    /**     * @return string|null     */    public function notes(): ?string    {        return $this->notes;    }    /**     * @return string|null     */    public function trackingUrl(): ?string    {        return $this->trackingUrl;    }    /**     * @return \DateTime     */    public function createdAt(): \DateTime    {        return $this->createdAt;    }    /**     * @return \DateTime|null     */    public function updatedAt(): ?\DateTime    {        return $this->updatedAt;    }}