<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonCommon\Components\Migration;

use Shopware\Plugins\ViisonCommon\Components\ExceptionTranslation\ExceptionTranslator;
use ViisonCommon_Plugin_BootstrapV15;

/**
 * Adapter to integrate global migration into our plugin bootstrap.
 */
class MigrationBootstrapAdapter
{
    /**
     * @var ViisonCommon_Plugin_BootstrapV15
     */
    private $pluginBootstrap;

    /**
     * @param ViisonCommon_Plugin_BootstrapV15 $pluginBootstrap
     */
    public function __construct(ViisonCommon_Plugin_BootstrapV15 $pluginBootstrap)
    {
        $this->pluginBootstrap = $pluginBootstrap;
    }

    /**
     * @param array $installationResult
     * @return array
     */
    public function onAfterInstall(array $installationResult)
    {
        if (!$installationResult['success']) {
            return $installationResult;
        }

        $migrationResult = $this->runMigrations();

        return $this->mergeMigrationExecutionResultIntoResult($migrationResult, $installationResult);
    }

    /**
     * @param array $uninstallResult
     * @return array
     */
    public function onAfterUninstall(array $uninstallResult)
    {
        if (!$uninstallResult['success']) {
            return $uninstallResult;
        }

        $migrationResult = $this->runMigrations();

        // When uninstalling a plugin completely, the status of its migrations should also be reset completely.
        /** @var MigrationService $migrationService */
        $migrationService = $this->pluginBootstrap->get('viison_common.migration_service');
        $migrationService->forgetStatusForMigrationSet($this->pluginBootstrap->getName());

        return $this->mergeMigrationExecutionResultIntoResult($migrationResult, $uninstallResult);
    }

    /**
     * @param array $secureUninstallResult
     * @return array
     */
    public function onAfterSecureUninstall(array $secureUninstallResult)
    {
        if (!$secureUninstallResult['success']) {
            return $secureUninstallResult;
        }

        $migrationResult = $this->runMigrations();

        return $this->mergeMigrationExecutionResultIntoResult($migrationResult, $secureUninstallResult);
    }

    /**
     * @param array $updateResult
     * @return array
     */
    public function onAfterUpdate(array $updateResult)
    {
        if (!$updateResult['success']) {
            return $updateResult;
        }

        $migrationResult = $this->runMigrations();

        return $this->mergeMigrationExecutionResultIntoResult($migrationResult, $updateResult);
    }

    /**
     * @param array $enableResult
     * @return array
     */
    public function onAfterEnable(array $enableResult)
    {
        if (!$enableResult['success']) {
            return $enableResult;
        }

        $migrationResult = $this->runMigrations();

        return $this->mergeMigrationExecutionResultIntoResult($migrationResult, $enableResult);
    }

    /**
     * @param array $disableResult
     * @return array
     */
    public function onAfterDisable(array $disableResult)
    {
        // Running migrations after disabling a plugin makes no sense.
        return $disableResult;
    }

    /**
     * @return MigrationExecutionResult
     */
    private function runMigrations()
    {
        $this->pluginBootstrap->registerMigrationSubscriber();
        /** @var MigrationService $migrationService */
        $migrationService = $this->pluginBootstrap->get('viison_common.migration_service');

        return $migrationService->executeMigrations();
    }

    /**
     * @param MigrationExecutionResult $migrationExecutionResult
     * @param array $installationResult
     * @return array
     */
    private function mergeMigrationExecutionResultIntoResult(MigrationExecutionResult $migrationExecutionResult, array $installationResult)
    {
        /** @var MigrationService $migrationService */
        foreach ($migrationExecutionResult->getMigrationTranscript()->getMessages() as $migrationMessage) {
            $installationResult['messages'][] = $migrationMessage->localize($this->pluginBootstrap->getBootstrapSnippetManager());
        }
        if ($migrationExecutionResult->hasFailedMigrationSets()) {
            $installationResult['success'] = false;
            $exceptionTranslator = new ExceptionTranslator($this->pluginBootstrap->getBootstrapSnippetManager());
            foreach ($migrationExecutionResult->getExceptions() as $exception) {
                $installationResult['messages'][] = $exceptionTranslator->translate($exception);
            }
        }
        if ($installationResult['success'] === true) {
            $installationResult['invalidateCache'] = array_unique(array_merge(
                $installationResult['invalidateCache'],
                $migrationExecutionResult->getMigrationTranscript()->getInvalidatedCaches()
            ));
        }

        return $installationResult;
    }
}
