<?php

declare(strict_types=1);

namespace Apexl\Io\Factories;

use DI\Container;
use DI\ContainerBuilder;

final class ContainerFactory
{
    public function make(string $baseDir, string $containerClass = Container::class): Container
    {
        return new ContainerBuilder($containerClass)->addDefinitions([
            ...$this->coreDefinitions(),
            ...$this->moduleDefinitions($baseDir),
        ])->useAttributes(true)->build();
    }

    private function coreDefinitions(): array
    {
        return [];
    }

    private function moduleDefinitions(string $baseDir): array
    {
        // Definition merge contract: files are spread into a single array where
        // the LAST occurrence of a key wins. Vendor packages are loaded first so
        // that host application definitions (module/*/services.php) load last and
        // therefore override any vendor package binding of the same key.
        // See Plans/host-overrides-vendor-di.md.
        //
        // A package declares its definitions in exactly one file, `src/services.php`.
        // This used to be a `**` walk of the whole vendor/apexl tree, which allowed a
        // package to scatter several files at any depth — io itself had three — and left
        // the order between them decided by directory names. A file anywhere else is now
        // ignored, silently: if definitions go missing, that is the first thing to check.
        $definitionFiles = [
            ...glob($baseDir . '/vendor/apexl/*/src/services.php'), // VENDOR first
            ...glob($baseDir . '/module/*/services.php'),           // HOST last (wins)
        ];

        $definitions = [];

        foreach ($definitionFiles as $definitionFile) {
            $definitions = [
                ...$definitions,
                ...require $definitionFile,
            ];
        }

        return $definitions;
    }
}