<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\DI\Compiler\Factory;

use PpPhp\Core\Platform\DI\Definition\ClassDefinition;
use PpPhp\Core\Platform\DI\Reflection\ReflectionService;

final class FactoryCodeGenerator
{
    public function __construct(private readonly ReflectionService $reflection = new ReflectionService()) {}

    public function generate(ClassDefinition $definition, string $namespace, string $className): string
    {
        $targetClass = '\\' . ltrim($definition->className(), '\\');
        $metadata = $this->reflection->inspect($definition->className());
        $constructor = $metadata->constructor();
        $args = [];

        if ($constructor) {
            foreach ($constructor->parameters() as $parameter) {
                $type = $parameter->type();

                if ($type !== null && !$parameter->builtin()) {
                    $args[] = '$container->get(' . var_export($type, true) . ')';
                    continue;
                }

                if ($parameter->hasDefault()) {
                    $args[] = var_export($parameter->defaultValue(), true);
                    continue;
                }

                if ($parameter->allowsNull()) {
                    $args[] = 'null';
                    continue;
                }

                $args[] = 'null';
            }
        }

        $argCode = implode(', ', $args);
        $serviceId = var_export($definition->id(), true);

        return <<<PHP
<?php
declare(strict_types=1);

namespace {$namespace};

use PpPhp\Core\Platform\DI\Contracts\ContainerInterface;
use PpPhp\Core\Platform\DI\Compiler\Factory\CompiledFactoryInterface;

final class {$className} implements CompiledFactoryInterface
{
    public function serviceId(): string
    {
        return {$serviceId};
    }

    public function create(ContainerInterface \$container): mixed
    {
        return new {$targetClass}({$argCode});
    }
}

PHP;
    }
}
