<?php

declare(strict_types=1);

namespace App\Framework\DI\Dependency;

use App\Framework\Core\ValueObjects\ClassName;

/**
 * Represents a resolved dependency with caching information
 */
final readonly class Dependency
{
    private function __construct(
        public DependencyType $type,
        public mixed $value,
        public ?ClassName $className = null
    ) {
    }

    public static function default(mixed $value): self
    {
        return new self(DependencyType::DEFAULT, $value);
    }

    public static function null(): self
    {
        return new self(DependencyType::NULL, null);
    }

    public static function dependency(object $value, ClassName $className): self
    {
        return new self(DependencyType::DEPENDENCY, $value, $className);
    }

    public static function nullableDependency(object $value, ClassName $className): self
    {
        return new self(DependencyType::NULLABLE_DEPENDENCY, $value, $className);
    }

    public function getCacheInfo(): array
    {
        return match ($this->type) {
            DependencyType::DEFAULT => [
                'type' => $this->type->value,
                'value' => $this->value,
            ],
            DependencyType::NULL => [
                'type' => $this->type->value,
            ],
            DependencyType::DEPENDENCY, DependencyType::NULLABLE_DEPENDENCY => [
                'type' => $this->type->value,
                'class' => $this->className?->getFullyQualified(),
            ],
        };
    }

    public static function fromCacheInfo(array $cacheInfo): ?ClassName
    {
        $type = DependencyType::from($cacheInfo['type']);

        return match ($type) {
            DependencyType::DEPENDENCY, DependencyType::NULLABLE_DEPENDENCY =>
                isset($cacheInfo['class']) ? ClassName::create($cacheInfo['class']) : null,
            default => null
        };
    }
}
