<?php

/*
 * Copyright 2005 - 2025 Centreon (https://www.centreon.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * For more information : contact@centreon.com
 *
 */

declare(strict_types=1);

namespace Core\Common\Infrastructure\Routing;

use Core\Common\Infrastructure\ExceptionLogger\ExceptionLogger;
use Core\Module\Infrastructure\ModuleInstallationVerifier;
use Core\Platform\Domain\InstallationVerifierInterface;
use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Routing\Loader\AttributeFileLoader;
use Symfony\Component\Routing\RouteCollection;

abstract readonly class ModuleRouteLoader implements RouteLoaderInterface
{
    public function __construct(
        #[Autowire(service: 'routing.loader.attribute.file')]
        private AttributeFileLoader $loader,
        #[Autowire(param: 'kernel.project_dir')]
        private string $projectDir,
        private ModuleInstallationVerifier $moduleInstallationVerifier,
        private InstallationVerifierInterface $centreonInstallationVerifier,
    ) {
    }

    final public function __invoke(): RouteCollection
    {
        $routes = new RouteCollection();

        /**
         * Dont populate RouteCollection during install / upgrade process to avoid DI of services that could need
         * some configurations that don't exists at this moment of the lifecycle of the software.
         */
        if ($this->centreonInstallationVerifier->isCentreonWebInstallableOrUpgradable()) {
            return $routes;
        }

        try {
            if (! $this->moduleInstallationVerifier->isInstallComplete($this->getModuleName())) {
                return $routes;
            }
        } catch (\Throwable $ex) {
            ExceptionLogger::create()->log($ex, ['module_name' => $this->getModuleName()]);

            return $routes;
        }

        $controllerFilePattern = $this->projectDir . '/src/' . $this->getModuleDirectory() . '/**/*Controller.php';
        $routeCollections = $this->loader->import($controllerFilePattern, 'attribute');
        if (! is_iterable($routeCollections)) {
            return $routes;
        }

        // Modules with only one route will return directly a route collection
        if ($routeCollections instanceof RouteCollection) {
            $routeCollections->addPrefix('/{base_uri}api/{version}');
            $routeCollections->addDefaults(['base_uri' => 'centreon/', 'version' => 'latest']);
            $routeCollections->addRequirements(['base_uri' => '(.+/)|.{0}']);

            return $routeCollections;
        }
        foreach ($routeCollections as $routeCollection) {
            $routes->addCollection($routeCollection);
        }
        $routes->addPrefix('/{base_uri}api/{version}');
        $routes->addDefaults(['base_uri' => 'centreon/', 'version' => 'latest']);
        $routes->addRequirements(['base_uri' => '(.+/)|.{0}']);

        return $routes;
    }

    abstract protected function getModuleName(): string;

    abstract protected function getModuleDirectory(): string;
}
