<?php

/**
 * ------------------------------------------------------------------------
 * SOLIDRES - Accommodation booking extension for Joomla
 * ------------------------------------------------------------------------
 * @author    Solidres Team <contact@solidres.com>
 * @website   https://www.solidres.com
 * @copyright Copyright (C) 2013 Solidres. All Rights Reserved.
 * @license   GNU General Public License version 3, or later
 * ------------------------------------------------------------------------
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Extension\ExtensionHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Installer\Installer;
use Joomla\CMS\Installer\InstallerAdapter;
use Joomla\CMS\Installer\InstallerScriptInterface;
use Joomla\CMS\Installer\InstallerScriptTrait;
use Joomla\CMS\Uri\Uri;
use Joomla\Database\DatabaseAwareInterface;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\Registry\Registry;

return new class () implements ServiceProviderInterface {
    public function register(Container $container): void
    {
        $container->set(
            InstallerScriptInterface::class,
            new class () implements
                InstallerScriptInterface,
                DatabaseAwareInterface {
                use DatabaseAwareTrait;
                use InstallerScriptTrait;

                public function __construct()
                {
                    $this->minimumPhp    = '8.3.0';
                    $this->minimumJoomla = '6.0';
                }

                public function preflight(string $type, InstallerAdapter $adapter): bool
                {
                    $namespaceMapFile = JPATH_ROOT . '/administrator/cache/autoload_psr4.php';

                    if (is_file($namespaceMapFile)) {
                        \Joomla\Filesystem\File::delete($namespaceMapFile);
                    }

                    $this->extension = $adapter->getName();

                    if (!$this->checkCompatibility($type, $adapter)) {
                        return false;
                    }

                    if (!$this->checkDowngrade($type, $adapter)) {
                        return false;
                    }

                    return true;
                }

                public function uninstall(InstallerAdapter $adapter): bool
                {
                    // Also uninstall sample media file package
                    $db    = $this->getDatabase();
                    $query = $db->createQuery()
                        ->delete()
                        ->from('#__extensions')
                        ->where('name LIKE ' . $db->quote('files_solidres_media'));
                    $db->setQuery($query)
                        ->execute();

                    $mediaLangFile = JPATH_SITE . '/language/en-GB/en-GB.files_solidres_media.sys.ini';
                    if (is_file($mediaLangFile)) {
                        File::delete($mediaLangFile);
                    }

                    // Remove content elements files
                    $destinationDir      = JPATH_SITE . '/administrator/components/com_falang/contentelements/';
                    $contentElementFiles = [
                        'sr_countries.xml',
                        'sr_coupons.xml',
                        'sr_currencies.xml',
                        'sr_extras.xml',
                        'sr_reservation_assets.xml',
                        'sr_room_types.xml',
                        'sr_statuses.xml',
                        'sr_tariffs.xml',
                    ];
                    foreach ($contentElementFiles as $file) {
                        $target = $destinationDir . $file;
                        if (is_file($target)) {
                            File::delete($target);
                        }
                    }

                    return true;
                }

                public function update(InstallerAdapter $adapter): bool
                {
                    $db    = $this->getDatabase();
                    $query = $db->createQuery()
                        ->select($db->quoteName('extension_id'))
                        ->from($db->quoteName('#__extensions'))
                        ->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
                        ->where($db->quoteName('folder') . ' = ' . $db->quote('solidres'))
                        ->where($db->quoteName('element') . ' = ' . $db->quote('api'));

                    if ($eid = $db->setQuery($query)->loadResult()) {
                        try {
                            $installer = new Installer();
                            $installer->setDatabase($db);
                            $installer->uninstall('plugin', $eid);
                        } catch (Throwable $e) {
                            Factory::getApplication()->enqueueMessage(
                                'Uninstall Solidres API plugin ERR: ' . $e->getMessage(),
                                'warning'
                            );
                        }
                    }

                    $query = $db->createQuery()
                        ->select($db->quoteName('extension_id'))
                        ->from($db->quoteName('#__extensions'))
                        ->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
                        ->where($db->quoteName('folder') . ' = ' . $db->quote('solidres'))
                        ->where($db->quoteName('element') . ' = ' . $db->quote('app'));

                    if ($eid = $db->setQuery($query)->loadResult()) {
                        try {
                            $installer = new Installer();
                            $installer->setDatabase($db);
                            $installer->uninstall('plugin', $eid);
                        } catch (Throwable $e) {
                            Factory::getApplication()->enqueueMessage(
                                'Uninstall Solidres APP plugin ERR: ' . $e->getMessage(),
                                'warning'
                            );
                        }
                    }

                    $component = ExtensionHelper::getExtensionRecord('com_solidres', 'component');
                    $db        = $this->getDatabase();
                    $query     = $db->createQuery();
                    $query->clear()
                        ->select('a.version_id')
                        ->from($db->quoteName('#__schemas', 'a'))
                        ->where('a.extension_id = ' . $component->extension_id);
                    $db->setQuery($query);

                    if (!$db->loadResult()) { // No Solidres database schema version found, let's fix it first
                        $currentVersion = (new Registry($component->manifest_cache ?: '{}'))->get('version');

                        if ($currentVersion) {
                            $version = $currentVersion;
                        } else {
                            $manifest = new SimpleXMLElement(
                                JPATH_ADMINISTRATOR . '/components/com_solidres/solidres.xml',
                                0,
                                true
                            );
                            $version  = (string) $manifest->version;
                        }

                        $query->clear()
                            ->delete($db->quoteName('#__schemas'))
                            ->where($db->quoteName('extension_id') . ' = ' . (int) $component->extension_id);
                        $db->setQuery($query)
                            ->execute();

                        $query->clear()
                            ->insert($db->quoteName('#__schemas'))
                            ->columns($db->quoteName('extension_id') . ',' . $db->quoteName('version_id'))
                            ->values($db->quote($component->id) . ',' . $db->quote($version));
                        $db->setQuery($query);

                        if (!$db->execute()) {
                            Factory::getApplication()->enqueueMessage("Solidres: Error while fixing database schema");

                            return false;
                        }
                    }


                    // Special update routine for Solidres 3.0.0: disable those extensions before updating, user must update those
                    // extensions first, then re-enable them manually after upgrading finished
                    $affectedExtensions = [
                        'hub'            => '1.13.1',
                        'experience'     => '1.9.1',
                        'feedback'       => '1.2.7',
                        'channelmanager' => '1.1.7',
                    ];

                    foreach ($affectedExtensions as $affectedExtension => $maxVersion) {
                        $extensionRecord = ExtensionHelper::getExtensionRecord(
                            $affectedExtension,
                            'plugin',
                            null,
                            'solidres'
                        );

                        if (!$extensionRecord) {
                            continue;
                        }

                        $currentVersion = (new Registry($extensionRecord->manifest_cache ?: '{}'))->get('version');

                        if ($currentVersion && version_compare($currentVersion, $maxVersion, 'le')) {
                            $query = $db->createQuery()
                                ->update($db->quoteName('#__extensions'))
                                ->set($db->quoteName('enabled') . ' = 0')
                                ->where($db->quoteName('extension_id') . ' = ' . (int) $extensionRecord->extension_id);

                            if ($db->setQuery($query)->execute()) {
                                Factory::getApplication()->enqueueMessage(
                                    "plg_solidres_$affectedExtension was disabled during the upgrade process. Please install the latest plg_solidres_$affectedExtension version then re-enable it.",
                                    "warning"
                                );
                            }
                        }
                    }

                    $this->removeFiles();

                    return true;
                }


                public function postflight(string $type, InstallerAdapter $adapter): bool
                {
                    if ($type == 'uninstall') {
                        return true;
                    }

                    JLoader::registerNamespace('Solidres', JPATH_LIBRARIES . '/solidres/src');

                    // Install content elements files
                    $destinationDir = JPATH_SITE . '/administrator/components/com_falang/contentelements/';
                    $sourceDir      = JPATH_SITE . '/administrator/components/com_solidres/falang/';

                    if (is_dir($destinationDir)) {
                        $files = Folder::files($sourceDir);
                        if (!empty($files)) {
                            foreach ($files as $file) {
                                File::copy($sourceDir . $file, $destinationDir . $file);
                            }
                        }
                    }

                    $installedVersion = $adapter->getManifest()->version;

                    echo '<div class="solidres-installation-result row">
				
				<div class="row">
					<div class="col-md-6">
						<img src="' . Uri::root() . '/media/com_solidres/assets/images/logo425x90.png" alt="Solidres\'s logo" class="mb-3" />
						<p>Solidres ' . $installedVersion . ' has been ' . ($type === 'update' ? 'upgraded' : 'installed') . ' successfully.</p>
					</div>
					<div class="col-md-6">
					</div>
				</div>
				<div class="row">
					<div class="col-md-6">
						
						<dl>
							<dd><span class="badge bg-success">1</span> Please visit our <a href="https://www.solidres.com/blog" target="_blank">Blog</a> for full change log (new features, bug fixes, improvements, ...) of this version.</dd>
							<dd><span class="badge bg-success">2</span> If you are a Solidres\'s subscriber, don\'t forget to update all installed plugins/modules (Complex Tariff, Invoice, Limit Booking, Hub etc) to ensure maximum compatibility with new version.</dd>
							<dd><span class="badge bg-success">3</span> Make sure that you visit our website to find new releases for your installed solidres\'s plugins and update them as well (if available).</dd>
							<dd><span class="badge bg-success">4</span> Make sure that all template override files are updated accordingly to this new version.</dd>
							<dd><span class="badge bg-success">5</span> Make a test reservation to make sure everything works normally.</dd>
						</dl>
					</div>
					<div class="col-md-6">
						<dl>
							<dt>Useful links</dt>
							<dd><a href="index.php?option=com_solidres&view=system" target="_blank">Your Solidres system page</a></dd>
							<dd><a href="https://www.solidres.com" target="_blank">Solidres Official Website</a></dd>
							<dd><a href="https://www.solidres.com/documentation" target="_blank">Solidres Documentation Site</a></dd>
							<dd><a href="https://www.solidres.com/support/frequently-asked-questions" target="_blank">Frequently asked questions</a></dd>
							<dd><a href="https://www.solidres.com/forum/index" target="_blank">Solidres Community Forum</a></dd>
							<dd><a href="https://www.solidres.com/subscribe/levels" target="_blank">Become a subscriber to access more features and official support</a></dd>
						</dl>
					</div>
				</div>
				
				<p><a href="' . Uri::root() . '/administrator/index.php?option=com_solidres" class="btn btn-outline-success"><i class="icon-out"></i> Go to Solidres now</a></p>
			</div>';

                    // Enable required plugins
                    $requiredPlugins = [
                        'content'         => ['solidres'],
                        'extension'       => ['solidres'],
                        'system'          => ['solidres'],
                        'solidrespayment' => [
                            'bankwire',
                            'paylater',
                        ],
                        'user' => ['solidres'],
                    ];
                    $dbo             = $this->getDatabase();
                    $query           = $dbo->createQuery();

                    foreach ($requiredPlugins as $group => $elements) {
                        foreach ($elements as $element) {
                            $query->clear();
                            $query->update($dbo->quoteName('#__extensions'));
                            $query->set('enabled = 1');
                            $query->where("element = " . $dbo->quote($element));
                            $query->where("type = " . $dbo->quote('plugin'));
                            $query->where("folder = " . $dbo->quote($group));

                            $dbo->setQuery($query);

                            if (!$dbo->execute()) {
                                Factory::getApplication()->enqueueMessage(
                                    "plg_{$group}_{$element}: auto publishing failed",
                                    'warning'
                                );
                            } else {
                                Factory::getApplication(
                                )->enqueueMessage("plg_{$group}_{$element} is published successfully.");
                            }
                        }
                    }

                    return true;
                }
            }
        );
    }
};
