<?php

declare(strict_types=1);

namespace PpPhp\Core\Platform\Services\Definition;

use PpPhp\Core\Platform\Services\Contracts\ServiceFactoryInterface;
use PpPhp\Core\Platform\Services\Metadata\ServiceMetadata;

final class ServiceDefinition
{
    public function __construct(
        private readonly ServiceMetadata $metadata,
        private readonly ?ServiceFactoryInterface $factory = null,
        private readonly ?object $instance = null
    ) {
        if ($this->factory !== null && $this->instance !== null) {
            throw new \InvalidArgumentException('A service definition cannot contain both factory and instance.');
        }
    }

    public static function fromFactory(ServiceMetadata $metadata, ServiceFactoryInterface $factory): self
    {
        return new self($metadata, $factory, null);
    }

    public static function fromInstance(ServiceMetadata $metadata, object $instance): self
    {
        return new self($metadata, null, $instance);
    }

    public static function metadataOnly(ServiceMetadata $metadata): self
    {
        return new self($metadata, null, null);
    }

    public function metadata(): ServiceMetadata
    {
        return $this->metadata;
    }

    public function factory(): ?ServiceFactoryInterface
    {
        return $this->factory;
    }

    public function instance(): ?object
    {
        return $this->instance;
    }

    public function hasFactory(): bool
    {
        return $this->factory !== null;
    }

    public function hasInstance(): bool
    {
        return $this->instance !== null;
    }

    public function toArray(): array
    {
        return [
            'metadata' => $this->metadata->toArray(),
            'hasFactory' => $this->hasFactory(),
            'hasInstance' => $this->hasInstance(),
        ];
    }
}
