<?php

use YesWiki\AutoUpdate\Service\AutoUpdateService;
use YesWiki\AutoUpdate\Service\MigrationService;
use YesWiki\AutoUpdate\Service\UpdateAdminPagesService;
use YesWiki\Core\Service\ArchiveService;
use YesWiki\Core\YesWikiAction;
use YesWiki\Security\Controller\SecurityController;

class UpdateAction extends YesWikiAction
{
    public function formatArguments($arg)
    {
        return [
            'version' => $arg['version'] ?? '',
        ];
    }

    public function run()
    {                        
        $vSecurityController = $this->getService(SecurityController::class);
        $vUpdateService = $this->getService(AutoUpdateService::class);
        $vMigrationService = $this->getService(MigrationService::class);
        $vArchiveService = $this->getService(ArchiveService::class);
        $vUpdateAdminPagesService = $this->getService(UpdateAdminPagesService::class);

        if (!$vUpdateService->initRepository($this->arguments['version'])) {
            return $this->render('@autoupdate/norepo.twig', []);
        }

        // At the time we introduced the migration concept in YesWiki, the old code was not redirecting
        // to "post_install" action. So we add this code to detect the first time the code is run
        // after migrations are introduced, and we run them.
        
        if (count($vMigrationService->getCompletedMigrations()) === 0) {
            $messages = $vMigrationService->run();
            foreach ($messages as $message) {
                flash(
                    $message['text'] . ' : ' . $message['status'],
                    $message['status'] == _t('AU_OK') ? 'success' : 'error'
                );
            }
        }

        $vIsReadOnly = $vArchiveService->isReadOnly ();

        $action = $vSecurityController->filterInput(INPUT_GET, 'action', FILTER_DEFAULT, true);
        if (empty($action) || !$this->wiki->UserIsAdmin() || $vIsReadOnly) {
            // Base action, display current status of software, extension and themes
            return $this->render('@autoupdate/status.twig', [
                'isAdmin' => $this->wiki->UserIsAdmin(),
                'isHibernated' => $vIsReadOnly,
                'core' => $vUpdateService->repository->getCorePackage(),
                'themes' => $vUpdateService->repository->getThemesPackages(),
                'tools' => $vUpdateService->repository->getToolsPackages(),
                'phpVersion' => PHP_VERSION,
            ]);
        }

        // Give 5 minutes time for the script to execute
        @ini_set('max_execution_time', 300);
        @set_time_limit(300);

        // Handle upgrade and delete actions
        // package can be 'yeswiki' for core upgrade, or extension name, or theme name
        $packageName = $vSecurityController->filterInput(INPUT_GET, 'package', FILTER_DEFAULT, true);

        switch ($action) {
            case 'upgrade':
                // Ensure a backup is made before the upgrade (or force upgrade)
                $forcedUpdateToken = $vSecurityController->filterInput(INPUT_GET, 'forcedUpdateToken', FILTER_DEFAULT, true);
                if (!$vArchiveService->hasValidatedBackup($forcedUpdateToken)) {
                    return $this->render('@core/preupdate-backup.twig', [
                        'packageName' => $packageName,
                    ]);
                }

                // Perform the upgrade
                $messages = $vUpdateService->upgrade($packageName);

                // Reload the page to perform postInstall operation with the new code
                $this->wiki->redirect($this->wiki->href('', '', [
                    'action' => 'post_install',
                    'messages' => json_encode($messages->toArray()),
                    'previous_version' => YESWIKI_VERSION,
                ], false));
                break;
            case 'post_install':
                $rawMessages = $vSecurityController->filterInput(INPUT_GET, 'messages', FILTER_UNSAFE_RAW, false, 'string');
                $messages = empty($rawMessages) ? [] : json_decode($rawMessages, true);
                if (!is_array($messages)) {
                    $messages = [];
                }
                // Run migrations
                $migrationMessages = $vMigrationService->run();
                $messages = array_merge($messages, $migrationMessages->toArray());
                break;
            case 'update_admin_pages':
                $messages = $vUpdateAdminPagesService->updateAll();
                break;
            case 'delete':
                $messages = $vUpdateService->delete($packageName);
                break;
            default:
                $messages = [];
                break;
        }

        // Display result of action, with a list of success/error messages
        return $this->wiki->render('@autoupdate/update-result.twig', [
            'messages' => $messages,
            'action' => $action,
        ]);
    }
}
