<?php

/**
 * Copyright (c) 2024 Ramble Ventures
 */

namespace PublishPress\FuturePro\Core;

// phpcs:disable Generic.Files.LineLength.TooLong

use PublishPress\Future\Core\HookableInterface;
use PublishPress\Future\Framework\InitializableInterface;
use PublishPress\Future\Framework\Logger\LoggerInterface;
use PublishPress\FuturePro\Modules\Notifications\Migrations\V040600NotificationsSchema as MigrationsV040600NotificationsSchema;
use PublishPress\FuturePro\Modules\Workflows\Migrations\V040600EventDrivenActionsSchema as MigrationsV040600EventDrivenActionsSchema;
use PublishPress\FuturePro\Modules\Workflows\Migrations\V040600EventDrivenActionsLogSchema as MigrationsV040600EventDrivenActionsLogSchema;
use Throwable;

// phpcs:enable Generic.Files.LineLength.TooLong

defined('ABSPATH') or die('No direct script access allowed.');

class PluginInitializator implements InitializableInterface
{
    public const PLUGIN_VERSION_OPTION = 'publishpressFutureProVersion';

    /**
     * @var bool
     */
    private $initialized = false;

    /**
     * @var InitializableInterface[]
     */
    private $controllers;

    /**
     * @var InitializableInterface[]
     */
    private $modules;

    /**
     * @var HookableInterface
     */
    private $hooks;

    /**
     * @var string
     */
    private $basePath;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var string
     */
    private $pluginVersion;

    /**
     * @var \Closure
     */
    private $migrationsFactory;

    /**
     * @param InitializableInterface[] $controllers
     * @param HookableInterface $hooksFacade
     * @param string $basePath
     */
    public function __construct(
        array $controllers,
        HookableInterface $hooksFacade,
        string $basePath,
        array $modules,
        LoggerInterface $logger,
        string $pluginVersion,
        \Closure $migrationsFactory
    ) {
        $this->controllers = $controllers;
        $this->hooks = $hooksFacade;
        $this->basePath = $basePath;
        $this->modules = $modules;
        $this->logger = $logger;
        $this->pluginVersion = $pluginVersion;
        $this->migrationsFactory = $migrationsFactory;
    }

    public function initialize()
    {
        if ($this->initialized) {
            return;
        }

        $this->initialized = true;

        $this->initializeModules();
        $this->initializeControllers();

        $this->hooks->doAction(HooksAbstract::ACTION_INIT_PLUGIN);
        $this->hooks->addAction(HooksAbstract::ACTION_INIT, [$this, 'manageUpgrade'], 99);
        $this->hooks->addAction(
            HooksAbstract::ACTION_ADMIN_ENQUEUE_SCRIPTS,
            [$this, 'initializeI18nForScripts'],
            6
        );

        call_user_func($this->migrationsFactory);
    }

    private function initializeModules()
    {
        foreach ($this->modules as $module) {
            if ($module instanceof InitializableInterface) {
                $module->initialize();
            }
        }
    }

    private function initializeControllers()
    {
        foreach ($this->controllers as $controller) {
            if (method_exists($controller, 'initialize')) {
                $controller->initialize();
            }
        }
    }

    public function manageUpgrade()
    {
        try {
            // Check for current version, if not exists, run activation
            $version = get_option(self::PLUGIN_VERSION_OPTION);
            $isFreshInstall = $version === false;

            // TODO: Make this descentralized from the plugin. Each module can manage its own migrations.
            if ($isFreshInstall) {
                // Fresh install. Run migrations that create the DB tables.
                $this->hooks->doAction(MigrationsV040600NotificationsSchema::HOOK);
                $this->hooks->doAction(MigrationsV040600EventDrivenActionsSchema::HOOK);
                $this->hooks->doAction(MigrationsV040600EventDrivenActionsLogSchema::HOOK);
            } else {
                if (version_compare($version, '4.6.0') === -1) {
                    $this->hooks->doAction(MigrationsV040600NotificationsSchema::HOOK);
                    $this->hooks->doAction(MigrationsV040600EventDrivenActionsSchema::HOOK);
                    $this->hooks->doAction(MigrationsV040600EventDrivenActionsLogSchema::HOOK);
                }
            }

            $this->hooks->doAction(HooksAbstract::ACTION_UPGRADE_PLUGIN, $version);

            if ($version !== $this->pluginVersion) {
                update_option(self::PLUGIN_VERSION_OPTION, $this->pluginVersion);
            }
        } catch (Throwable $th) {
            $this->logger->error('Error managing upgrade: ' . $th->getMessage());
        }
    }

    public function initializeI18nForScripts()
    {
        $json = $this->getLocalizedTranslations();

        wp_localize_script(
            'publishpress-i18n',
            'publishpressI18nProConfig',
            [
                'data' => $json,
            ]
        );
    }

    private function getLocalizedTranslations()
    {
        $currentLocale = get_locale();
        $jsonPath = $this->basePath . '/languages/publishpress-future-pro-' . $currentLocale . '.json';

        if (! file_exists($jsonPath)) {
            return [];
        }

        // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
        $json = file_get_contents($jsonPath);
        return json_decode($json, true);
    }
}
