<?php

namespace App\Module\Core\Service;

use App\Entity\Tenant\ModuleConfig;
use App\Shared\Interface\ModuleInterface;
use Doctrine\ORM\EntityManagerInterface;

class ModuleActivator
{
    public function __construct(
        private readonly ModuleRegistry $moduleRegistry,
        private readonly EntityManagerInterface $entityManager,
    ) {}

    public function activate(string $slug): bool
    {
        $module = $this->moduleRegistry->getModule($slug);
        if ($module === null) {
            throw new \InvalidArgumentException(sprintf('Module "%s" not found.', $slug));
        }

        // Check dependencies
        foreach ($module::getDependencies() as $dep) {
            if (!$this->moduleRegistry->isModuleActive($dep)) {
                throw new \RuntimeException(sprintf(
                    'Module "%s" requires "%s" to be active.',
                    $slug,
                    $dep
                ));
            }
        }

        $config = $this->getOrCreateConfig($slug);
        $config->setIsActive(true);
        $config->setActivatedAt(new \DateTimeImmutable());

        $this->entityManager->flush();
        $this->moduleRegistry->invalidateCache();

        return true;
    }

    public function deactivate(string $slug): bool
    {
        $module = $this->moduleRegistry->getModule($slug);
        if ($module === null) {
            throw new \InvalidArgumentException(sprintf('Module "%s" not found.', $slug));
        }

        if ($module::isCore()) {
            throw new \RuntimeException(sprintf('Core module "%s" cannot be deactivated.', $slug));
        }

        // Check if other active modules depend on this
        foreach ($this->moduleRegistry->getActiveModules() as $activeModule) {
            if (in_array($slug, $activeModule::getDependencies(), true)) {
                throw new \RuntimeException(sprintf(
                    'Cannot deactivate "%s": module "%s" depends on it.',
                    $slug,
                    $activeModule::getModuleSlug()
                ));
            }
        }

        $config = $this->getOrCreateConfig($slug);
        $config->setIsActive(false);

        $this->entityManager->flush();
        $this->moduleRegistry->invalidateCache();

        return true;
    }

    private function getOrCreateConfig(string $slug): ModuleConfig
    {
        $repo = $this->entityManager->getRepository(ModuleConfig::class);
        $config = $repo->findOneBy(['moduleSlug' => $slug]);

        if ($config === null) {
            $config = new ModuleConfig();
            $config->setModuleSlug($slug);
            $this->entityManager->persist($config);
        }

        return $config;
    }
}
