<?php

namespace WordpressModelsPlugin\DependencyInjection\FederatedPages;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Reference;
use WordpressModels\DependencyInjection\Pages\PageRegistry;
use WordpressModels\Page\AbstractPage;
use WordpressModels\Page\AbstractPageStack;

class FederatedPagesExtension extends Extension implements CompilerPassInterface
{


    public function load(array $configs, ContainerBuilder $container)
    {
        $container->register(FederatedPluginApp::class)
            ->setPublic(true)
            ->setAutowired(true)
            ->setAutoconfigured(true);
    }

    public function process(ContainerBuilder $container)
    {
        if (!$container->has(PageRegistry::class)) {
            return;
        }

        $definition = $container->findDefinition(PageRegistry::class);

        // find all service IDs with the 'wpm_page' tag
        $taggedServices = $container->findTaggedServiceIds('wpm_page');

        foreach ($taggedServices as $id => $tags) {
            $serviceReflector = new \ReflectionClass($container->getDefinition($id)->getClass());
            if (!$serviceReflector->isSubclassOf(AbstractPage::class)) {
                throw new \InvalidArgumentException(sprintf('The service "%s" must extend the "%s" class.', $id, AbstractPage::class));
            }

            if ($serviceReflector->getName() === FederatedPage::class
                || $serviceReflector->getName() === FederatedPageStack::class) {
                // skip decorating the FederatedPage service, as it is the decorator itself
                continue;
            }

            $newId = $this->generateAliasName($id);

            if ($serviceReflector->isSubclassOf(AbstractPageStack::class)) {
                $container->register($newId, FederatedPageStack::class)
                    ->setDecoratedService($id)
                    ->setAutowired(true);
            } else {
                $container->register($newId, FederatedPage::class)
                    ->setDecoratedService($id)
                    ->setAutowired(true);
            }

            // add the page service to the PageRegistry service
            $definition->addMethodCall('addPage', [new Reference($id)]);
        }
    }

    /**
     * Generate a snake_case service name from the service class name
     */
    private function generateAliasName(string $serviceName)
    {
        if (false !== strpos($serviceName, '\\')) {
            $parts = explode('\\', $serviceName);
            $className = end($parts);
            $alias = strtolower(preg_replace('/[A-Z]/', '_\\0', lcfirst($className)));
        } else {
            $alias = $serviceName;
        }
        return $alias . '_decorator';
    }
}