<?php

namespace Ecoyn\Setup;

use Ecoyn\Setup\Steps\BasicData;
use Ecoyn\Setup\Steps\Basics;
use Ecoyn\Setup\Steps\DistributionType;
use Ecoyn\Setup\Steps\InstallDemoData;
use Ecoyn\Setup\Steps\License;
use Ecoyn\Setup\Steps\LicenseUpload;
use Ecoyn\Setup\Steps\LogoUpload;
use Ecoyn\Setup\Steps\Modules;
use Ecoyn\Setup\Steps\Payments;
use Ecoyn\Setup\Steps\Tax;
use Ecoyn\Setup\Steps\Welcome;
use QUI;
use QUI\Composer\Exception;
use QUI\ERP\BankAccounts\Handler as BankAccountHandler;
use QUI\ERP\Shipping\Methods\Standard\ShippingType;
use QUI\ERP\Shipping\Rules\Factory as RuleFactory;
use QUI\ERP\Shipping\Types\Factory as ShippingFactory;
use QUI\InstallationWizard\AbstractInstallationWizard;
use QUI\InstallationWizard\ProviderHandler;
use QUI\InstallationWizard\QuiqqerSteps;
use QUI\Locale;

use function class_exists;

/**
 * Class SetupProvider
 */
class SetupProvider extends AbstractInstallationWizard
{
    /**
     * set it as main provider
     */
    public function getPriority(): int
    {
        return 1;
    }

    public function getTitle(?Locale $Locale = null): string
    {
        if ($Locale === null) {
            $Locale = QUI::getLocale();
        }

        return $Locale->get('ecoyn/core', 'set.up.title');
    }

    public function getDescription(?Locale $Locale = null): string
    {
        if ($Locale === null) {
            $Locale = QUI::getLocale();
        }

        return $Locale->get('ecoyn/core', 'set.up.description');
    }

    /**
     * @return string
     */
    public function getLogo(): string
    {
        return URL_OPT_DIR . 'ecoyn/core/bin/ecoyn_w_100px.png';
    }

    /**
     * @param array<array-key, mixed> $list
     */
    public function onListInit(&$list): void
    {
        // kill the quiqqer main step, ecoyn takes over it
        /* @var $Provider QUI\InstallationWizard\AbstractInstallationWizard */
        foreach ($list as $k => $Provider) {
            if ($Provider instanceof QUI\InstallationWizard\QuiqqerProvider) {
                unset($list[$k]);

                // add this to the executed list
                try {
                    ProviderHandler::setProviderStatus(
                        $Provider,
                        ProviderHandler::STATUS_SET_UP_DONE
                    );
                } catch (QUI\Exception $exception) {
                    QUI\System\Log::addError($exception->getMessage());
                }
            }
        }
    }

    /**
     * @return QUI\InstallationWizard\AbstractInstallationWizardStep[]
     */
    public function getSteps(): array
    {
        $steps = [];
        $steps[] = new Welcome();
        $steps[] = new License();

        // quiqqer setup
        $steps[] = new QuiqqerSteps\Country();
        $steps[] = new QuiqqerSteps\Groups();
        $steps[] = new QuiqqerSteps\Mail();
        $steps[] = new QuiqqerSteps\MailSMTP();
        $steps[] = new QuiqqerSteps\Cron();
        $steps[] = new QuiqqerSteps\Workspace();

        // ecoyn setup
        $steps[] = new BasicData\CompanyData();
        $steps[] = new BasicData\Bank();
        $steps[] = new Basics();
        $steps[] = new LogoUpload();
        $steps[] = new DistributionType();

        if (QUI::getPackageManager()->isInstalled('quiqqer/tax')) {
            $list = QUI\ERP\Tax\Utils::getAvailableTaxList();

            if (count($list)) {
                $steps[] = new Tax();
            }
        }

        $steps[] = new LicenseUpload();
        $steps[] = new Payments();
        $steps[] = new Modules();
        $steps[] = new InstallDemoData();

        // deine steps
        return $steps;
    }

    /**
     * @param array<string, mixed> $data
     * @throws QUI\Exception
     */
    public function execute(array $data = []): void
    {
        $this->write('QUIQQER setup execution');

        if (empty($data['quiqqer-country'])) {
            $data['quiqqer-country'] = 'de';
        }

        $QUIQQERSetup = new QUI\InstallationWizard\QuiqqerProvider();
        $QUIQQERSetup->execute($data);

        // install packages
        try {
            $this->write('Install needed packages');
            $this->installNeededPackages($data);
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addError($Exception->getMessage());

            throw $Exception;
        }

        // import currencies
        try {
            $this->write('Import currencies');
            QUI\ERP\Currency\Import::importCurrenciesFromECB();
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addError($Exception->getMessage());
        }

        $this->write('Set Basics');
        $this->setBasics($data);

        // import data
        if (!empty($data['installDemoData'])) {
            $this->write('Install Demo Data');
            $projects = QUI::getProjectManager()->getProjects(true);

            foreach ($projects as $P) {
                $languages = $P->getLanguages();
                $project = $P->getName();

                foreach ($languages as $language) {
                    $Project = QUI::getProject($project, $language);
                    $template = $Project->getAttribute('template');

                    if (is_string($template)) {
                        QUI\Utils\Project::applyDemoDataToProject($Project, $template);
                    }
                }
            }
        } else {
            $this->write('Setup Project sites');
            $this->createSites();
        }

        // set defaults
        $this->write('Set up default settings');
        $this->setDefaults($data);

        // setup basic data - company
        try {
            $this->setBasicCompanyData($data);
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addError($Exception->getMessage());
        }

        // setup basic data - bank
        try {
            $this->setBasicBankData($data);
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addError($Exception->getMessage());
        }

        // Widerrufsbelehrung installieren wenn B2C dabei ist
        // Aktuelles Land default aktivieren
        if (stripos($data['general.businessType'], 'b2c') !== false) {
            $this->setOrderCancellation($data);
        }
        // Shipping installieren wenn physische Produkte
        //     - Versandkosten anlegen (Standard Versand)
        //     - Versandkostenregel anlegen (Standard  Versandregel - 5.99)
        $this->setShipping();

        // wenn tags installiert ist
        $this->setTagSettings();


        // set mail defaults
        $this->setMail($data);

        $this->write('Create translations');
        QUI\Translator::create();

        $this->write('Clear cache');
        QUI\Cache\Manager::clearAll();

        $this->write('Done');
    }

    /**
     * @return string
     */
    public function finish(): string
    {
        return '<script src="' . URL_OPT_DIR . 'ecoyn/core/bin/installationFinish.js"></script>';
    }

    /**
     * @param array<string, mixed> $data
     * @return void
     * @throws Exception
     */
    protected function installNeededPackages(array $data = []): void
    {
        $packages = [
            'quiqqer/template-cologne' => '*'
        ];

        /**
         * payments
         */
        if (!empty($data['payment.invoice'])) {
            $packages['quiqqer/invoice'] = '*';
        }

        if (!empty($data['payment.paypal'])) {
            $packages['quiqqer/payment-paypal'] = '>=1.5';
        }

        if (!empty($data['payment.amazon'])) {
            $packages['quiqqer/payment-amazon'] = '>=1.3.1';
        }

        if (!empty($data['payment.stripe'])) {
            $packages['quiqqer/payment-stripe'] = '>=1.1.4';
        }

        if (!empty($data['payment.sepa'])) {
            $packages['quiqqer/payment-sepa'] = '*';
        }

        /**
         * plugins / modules
         */
        if (!empty($data['module.invoice'])) {
            $packages['quiqqer/invoice'] = '*';
        }

        if (!empty($data['module.accounting-export'])) {
            $packages['quiqqer/accounting-export'] = '*';
        }

        if (!empty($data['module.offer'])) {
            $packages['quiqqer/offer'] = '*';
        }

        if (!empty($data['module.purchasing'])) {
            $packages['quiqqer/purchasing'] = '*';
        }

        if (!empty($data['module.contracts'])) {
            $packages['quiqqer/contracts'] = '*';
        }

        if (!empty($data['module.salesorders'])) {
            $packages['quiqqer/salesorders'] = '*';
        }

        if (!empty($data['module.cashbook'])) {
            $packages['quiqqer/cashbook'] = '*';
        }

        if (!empty($data['module.plans'])) {
            $packages['quiqqer/plans'] = '*';
        }

        if (!empty($data['module.dunning'])) {
            $packages['quiqqer/dunning'] = '*';
        }

        if (!empty($data['module.coupons'])) {
            $packages['quiqqer/coupons'] = '*';
        }

        if (!empty($data['module.stock-management'])) {
            $packages['quiqqer/stock-management'] = '*';
        }

        // Widerrufsbelehrung installieren wenn B2C dabei ist
        if (stripos($data['general.businessType'], 'b2c') !== false) {
            $packages['quiqqer/order-cancellation-policy'] = '*';
        }


        // shipping nicht installieren -> wenn nur digitale Produkte
        if (stripos($data['general-import'], 'physical') !== false) {
            $packages['quiqqer/shipping'] = '*';
        }

        // check if some stuff is already installed
        $PackageManager = QUI::getPackageManager();

        foreach ($packages as $package => $version) {
            if ($PackageManager->isInstalled($package)) {
                unset($packages[$package]);
            }
        }


        $install = [];

        foreach ($packages as $package => $v) {
            $install[] = $package . ':' . $v;
        }

        if (empty($install)) {
            $this->write('Nothing to install');
            return;
        }

        // output to the console display
        $self = $this;
        $Composer = QUI::getPackageManager()->getComposer();
        $Composer->addEvent('output', function ($Instance, $output, $type) use ($self) {
            $self->write($output);
        });

        $Composer->unmute();
        $Composer->requirePackage($install);
    }

    /**
     * @param array<string, mixed> $data
     *
     * @throws QUI\Exception
     */
    protected function setBasics(array $data = []): void
    {
        $country = $data['quiqqer-country'];
        $import = $data['general-import'];

        // set default country
        $Country = QUI\Countries\Manager::get($country);

        $QuiqqerConfig = PackageConfig::get('quiqqer/core');
        $QuiqqerConfig->set('globals', 'country', $Country->getCode());
        $QuiqqerConfig->save();

        // default currency
        $CurrencyConfig = PackageConfig::get('quiqqer/currency');
        $CurrencyConfig->setValue('currency', 'defaultCurrency', $Country->getCurrencyCode());
        $CurrencyConfig->save();

        // default dates
        $ErpConfig = PackageConfig::get('quiqqer/erp');
        $ErpConfig->setValue('timestampFormat', 'de', 'dd.MM.yyyy HH:mm:ss');
        $ErpConfig->setValue('timestampFormat', 'en', 'dd/MM/yyyy HH:mm:ss');
        $ErpConfig->setValue('dateFormat', 'de', 'dd.MM.yyyy');
        $ErpConfig->setValue('dateFormat', 'en', 'dd/MM/yyyy');
        $ErpConfig->save();

        // basic import

        //<!-- alle areas importieren -> eu digital NUR EU ZONEN -->
        //<!-- TAX: alle TAX aktivieren -->
        //<!-- Tax import -> is euvat=0 von Land was ausgewählt ist, alle anderen EU länder auf 1 -->

        switch ($import) {
            case "manual.xml":
            case "DigitalGoodsInOneCountry.xml":
            case "DigitalGoodsFromEuropeToTheWorld.xml":
            case "DigitalGoodsFromEuropaToEuropa.xml":
            case "PhysicalDigitalGoodsInOneCountry.xml":
            case "PhysicalDigitalGoodsFromEuropeToTheWorld.xml":
            case "PhysicalDigitalGoodsFromEuropaToEuropa.xml":
            case "PhysicalGoodsInOneCountry.xml":
            case "PhysicalGoodsFromEuropeToTheWorld.xml":
            case "PhysicalGoodsFromEuropaToEuropa.xml":
                break;

            default:
                return;
        }

        // area import
        QUI\ERP\Areas\Import::importPreconfigureAreas($import);

        // tax import

        // reset tax rates if wanted
        if (!isset($data['reimport-tax-rates'])) {
            $data['reimport-tax-rates'] = false;
        }

        if ($data['reimport-tax-rates'] === true) {
            $TaxHandler = QUI\ERP\Tax\Handler::getInstance();
            $taxList = $TaxHandler->getChildren();

            // delete entries
            foreach ($taxList as $TaxEntry) {
                /* @var $TaxEntry \QUI\ERP\Tax\TaxEntry */
                $TaxEntry->delete();
            }

            // delete groups
            $groups = $TaxHandler->getTaxGroups();

            foreach ($groups as $TaxGroup) {
                $TaxGroup->delete();
            }

            // delete tax types
            $types = $TaxHandler->getTaxTypes();

            foreach ($types as $TaxType) {
                $TaxType->delete();
            }
        }

        if ($import !== 'manual.xml') {
            // if country is EU, import eu tax rates
            if ($Country->isEU()) {
                QUI\ERP\Tax\Import::import(OPT_DIR . 'quiqqer/tax/setup/euTaxRates.xml');
            }
        }

        switch ($import) {
            case "manual.xml":
                // nur ausgewähltes land anlegen + steuer 0
                QUI\ERP\Tax\Import::import(OPT_DIR . 'quiqqer/tax/setup/manual.xml');
                break;

            case "DigitalGoodsInOneCountry.xml":
            case "PhysicalGoodsInOneCountry.xml":
            case "PhysicalDigitalGoodsInOneCountry.xml":
                // TAX: wenn in EU -> aktivieren nur das aktuelle land vom shop
                $TaxHandler = QUI\ERP\Tax\Handler::getInstance();
                $taxList = $TaxHandler->getChildren();

                /* @var $Tax QUI\ERP\Tax\TaxEntry */
                foreach ($taxList as $Tax) {
                    try {
                        $Area = $Tax->getArea();

                        if ($Area !== null && $Area->contains($Country)) {
                            $Tax->setAttribute('active', 1);
                        } else {
                            $Tax->setAttribute('active', 0);
                        }

                        $Tax->update();
                    } catch (QUI\Exception) {
                    }
                }
                break;

            case "DigitalGoodsFromEuropeToTheWorld.xml":
            case "PhysicalDigitalGoodsFromEuropeToTheWorld.xml":
            case "PhysicalGoodsFromEuropeToTheWorld.xml":
            case "DigitalGoodsFromEuropaToEuropa.xml":
            case "PhysicalDigitalGoodsFromEuropaToEuropa.xml":
            case "PhysicalGoodsFromEuropaToEuropa.xml":
                // we need nothing to do, because all tax entries are active
                break;
        }
    }

    /**
     * @param array<string, mixed> $data
     * @return void
     * @throws QUI\Exception
     */
    protected function setDefaults(array $data = []): void
    {
        // Verwendete Nachkommastellen = 8
        try {
            $ErpConfig = PackageConfig::get('quiqqer/erp');
            $ErpConfig->set('general', 'precision', 8);

            // businessType
            switch ($data['general.businessType']) {
                case 'B2C':
                case 'B2B':
                case 'B2C-B2B':
                case 'B2B-B2C':
                    $ErpConfig->set('general', 'businessType', $data['general.businessType']);
                    break;

                default:
                    $ErpConfig->set('general', 'businessType', 'B2C-B2B');
            }

            // [sites]
            // terms_and_conditions="{\"de\":\"\",\"en\":\"\"}"
            $termsAndConditions = $this->getLanguageUrls('quiqqer/sitetypes:types/generalTermsAndConditions');

            // revocation="{\"de\":\"\",\"en\":\"\"}"
            // $revocations = $this->getLanguageUrls('quiqqer/sitetypes:types/revocation');

            // privacy_policy="{\"de\":\"\",\"en\":\"\"}"
            $privacyPolicy = $this->getLanguageUrls('quiqqer/sitetypes:types/privacypolicy');

            $termsAndConditionsJson = json_encode($termsAndConditions);
            $privacyPolicyJson = json_encode($privacyPolicy);

            if ($termsAndConditionsJson !== false) {
                $ErpConfig->set('sites', 'terms_and_conditions', $termsAndConditionsJson);
            }

            //$ErpConfig->set('sites', 'revocation', json_encode($revocations));

            if ($privacyPolicyJson !== false) {
                $ErpConfig->set('sites', 'privacy_policy', $privacyPolicyJson);
            }

            $ErpConfig->save();
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addAlert($Exception->getMessage());
        }

        // Login über die E-Mail-Adresse
        try {
            $QuiqqerConfig = PackageConfig::get('quiqqer/core');
            $QuiqqerConfig->set('general', 'emaillogin', 1);
            $QuiqqerConfig->set('auth_settings', 'showResetPasswordFrontend', 1);
            $QuiqqerConfig->save();
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addAlert($Exception->getMessage());
        }

        // Datumsformat muss nach Land gesetzt werden -> Locale Vorgaben
        try {
            $Country = null;
            $country = $data['quiqqer-country'];
            $Country = QUI\Countries\Manager::get($country);
        } catch (QUI\Exception) {
        }

        if (!$Country) {
            $Country = QUI\Countries\Manager::get('de');
        }

        // Standard Zone setzen
        try {
            // import areas
            $isNetto = stripos($data['general.businessType'], 'b2b');

            // workaround for special cases
            if ($Country->getCode() == 'en') {
                $Country = QUI\Countries\Manager::get('GB');
            }

            $Area = QUI\ERP\Areas\Utils::getAreaByCountry($Country);
            $TaxConfig = PackageConfig::get('quiqqer/tax');
            $TaxConfig->set('shop', 'vat', '0:0');
            $TaxConfig->set('shop', 'isNetto', $isNetto ? 1 : 0);

            if ($Area) {
                $TaxConfig->set('shop', 'area', $Area->getId());
            }

            $TaxConfig->save();
        } catch (QUI\Exception) {
        }

        // default currency
        try {
            $CurrencyConfig = PackageConfig::get('quiqqer/erp');
            $CurrencyConfig->set('currency', 'defaultCurrency', $Country->getCurrencyCode());
            $CurrencyConfig->set('currency', 'allowedCurrencies', $Country->getCurrencyCode());
            $CurrencyConfig->set('currency', 'accountingCurrency', $Country->getCurrencyCode());
            $CurrencyConfig->set('currency', 'accountingCurrencyDiffers', 0);
            $CurrencyConfig->set('currency', 'differentAccountingCurrencies', 0);
            $CurrencyConfig->save();
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addAlert($Exception->getMessage());
        }
    }

    /**
     * @param array<string, mixed> $data
     * @return void
     *
     * @throws QUI\Exception
     */
    protected function setBasicCompanyData(array $data = []): void
    {
        $Config = PackageConfig::get('quiqqer/erp');

        $fields = [
            'company.name',
            'company.owner',
            'company.street',
            'company.zipCode',
            'company.city',
            'company.country',
            'company.phone',
            'company.fax',
            'company.email',
            'company.web',
            'company.taxId',
            'company.taxNumber',
            'company.register',
            'company.court'
        ];

        foreach ($fields as $field) {
            if (isset($data[$field])) {
                $Config->set(
                    'company',
                    str_replace('company.', '', $field),
                    $data[$field]
                );
            }
        }

        $Config->save();
    }

    /**
     * @param array<string, mixed> $data
     * @return void
     *
     * @throws QUI\Exception
     */
    protected function setBasicBankData(array $data = []): void
    {
        $Config = PackageConfig::get('quiqqer/erp');

        $fields = [
            'company.name',
            'company.bankBic',
            'company.bankIban'
        ];

        foreach ($fields as $field) {
            if (isset($data[$field])) {
                $Config->set(
                    'company',
                    str_replace('company.', '', $field),
                    $data[$field]
                );
            }
        }

        $Config->save();

        // create new bank account
        BankAccountHandler::addBankAccount([
            'title' => $data['company.name'],
            'name' => $data['company.name'],
            'iban' => $data['company.bankIban'],
            'bic' => $data['company.bankBic'],
            'accountHolder' => true,
            'creditorId' => false,
            'default' => true,
            'financialAccountNo' => false
        ]);
    }

    /**
     * set up all mail stuff
     *
     * @param array<string, mixed> $data
     * @return void
     *
     * @throws QUI\Exception
     */
    protected function setMail(array $data = []): void
    {
        try {
            $Config = PackageConfig::get('quiqqer/order');
            $currentOrderAdminMail = $Config->get('order', 'orderAdminMails');
        } catch (QUI\Exception $Exception) {
            QUI\System\Log::addAlert($Exception->getMessage());
            return;
        }

        if (!empty($data['company.email']) && empty($currentOrderAdminMail)) {
            $Config->set('order', 'orderAdminMails', $data['company.email']);

            $Config->set('order', 'sendOrderConfirmationToAdmin', 1);
            $Config->set('order', 'sendAdminOrderConfirmation', 1);
        }

        // default quiqqer mail stuff
        $adminMail = QUI::conf('mail', 'admin_mail');
        $mailFrom = QUI::conf('mail', 'MAILFrom');
        $MAILFromText = QUI::conf('mail', 'MAILFromText');
        $mailReplyTo = QUI::conf('mail', 'MAILReplyTo');

        $QConf = QUI::getConfig('etc/conf.ini.php');

        if (!empty($data['company.email']) && empty($adminMail)) {
            $QConf->set('mail', 'admin_mail', $data['company.email']);
        }

        if (!empty($data['company.email']) && empty($mailFrom)) {
            $QConf->set('mail', 'MAILFrom', $data['company.email']);
        }

        if (!empty($data['company.email']) && empty($mailReplyTo)) {
            $QConf->set('mail', 'MAILReplyTo', $data['company.email']);
        }

        if (!empty($data['company.name']) && empty($MAILFromText)) {
            $QConf->set('mail', 'MAILReplyTo', $data['company.name']);
        }

        $QConf->save();
        $Config->save();
    }

    /**
     * - if cancellation policy is installed
     *     - Activate current country default
     *
     * @param array<string, mixed> $data
     * @return void
     */
    protected function setOrderCancellation(array $data = []): void
    {
        if (!class_exists('QUI\ERP\Order\CancellationPolicy\OCP')) {
            return;
        }

        try {
            $country = $data['quiqqer-country'];
            $Country = QUI\Countries\Manager::get($country);
            $Area = QUI\ERP\Areas\Utils::getAreaByCountry($Country);

            if ($Area) {
                QUI\ERP\Order\CancellationPolicy\OCP::activate($Area->getId());
            }
        } catch (QUI\Exception) {
        }
    }

    /**
     * Set up shipping stuff, if needed
     *
     * @return void
     *
     * @throws QUI\Exception
     */
    protected function setShipping(): void
    {
        $isInstalled = QUI::getPackageManager()->isInstalled('quiqqer/shipping');

        if (!$isInstalled) {
            return;
        }

        // standard Versand
        $Shipping = ShippingFactory::getInstance()->createChild([
            'active' => 1,
            'shipping_type' => ShippingType::class
        ]);

        $localeVar = 'shipping.' . $Shipping->getId() . '.title';

        // locale
        QUI\Translator::update('quiqqer/shipping', $localeVar, 'quiqqer/shipping', [
            'de' => 'Standard Versand',
            'en' => 'Default Shipping'
        ]);


        // standard Versandkostenregel
        $Rule = RuleFactory::getInstance()->createChild([
            'active' => 1,
            'title' => [
                'de' => 'Standard Versandkostenregel',
                'en' => 'Default shipping rule'
            ],
            'discount_type' => RuleFactory::DISCOUNT_TYPE_ABS,
            'discount' => 5.99
        ]);

        $Shipping->addShippingRule($Rule);
        $Shipping->update();
    }

    /**
     * @return void
     */
    protected function setTagSettings(): void
    {
        $isInstalled = QUI::getPackageManager()->isInstalled('quiqqer/tags');

        if (!$isInstalled) {
            return;
        }

        try {
            $TagConfig = PackageConfig::get('quiqqer/tags');
            $TagConfig->set('tags', 'useGroups', 1);
            $TagConfig->save();
        } catch (QUI\Exception) {
        }
    }

    /**
     * Create the needed sites
     *
     * @return void
     * @throws QUI\Exception
     */
    protected function createSites(): void
    {
        $projects = QUI::getProjectManager()->getProjects(true);

        /* @var $Project QUI\Projects\Project */
        foreach ($projects as $P) {
            $languages = $P->getLanguages();
            $project = $P->getName();

            foreach ($languages as $language) {
                $Project = QUI::getProject($project, $language);

                $this->createSite($Project, 'quiqqer/verification:types/verifier', [
                    'name' => 'verify',
                    'title' => QUI::getLocale()->getByLang($language, 'ecoyn/core', 'site.verify.title'),
                    'nav_hide' => 1
                ]);

                $this->createSite($Project, 'quiqqer/frontend-users:types/profile', [
                    'name' => 'Profile',
                    'title' => QUI::getLocale()->getByLang($language, 'ecoyn/core', 'site.profile.title'),
                    'nav_hide' => 1
                ]);

                $this->createSite($Project, 'quiqqer/frontend-users:types/registration', [
                    'name' => 'register',
                    'title' => QUI::getLocale()->getByLang($language, 'ecoyn/core', 'site.register.title'),
                    'nav_hide' => 1
                ]);

                $this->createSite($Project, 'quiqqer/order:types/orderingProcess', [
                    'name' => 'order',
                    'title' => QUI::getLocale()->getByLang($language, 'ecoyn/core', 'site.order.title'),
                    'nav_hide' => 1
                ]);

                $this->createSite($Project, 'quiqqer/order:types/shoppingCart', [
                    'name' => 'basket',
                    'title' => QUI::getLocale()->getByLang($language, 'ecoyn/core', 'site.basket.title'),
                    'nav_hide' => 1
                ]);
            }
        }
    }

    /**
     * @param QUI\Projects\Project $Project
     * @param array<string, mixed> $siteParams
     *
     * @return void
     * @throws QUI\Database\Exception
     */
    protected function createSite(QUI\Projects\Project $Project, string $siteType, array $siteParams): void
    {
        $sites = $Project->getSites([
            'where' => [
                'type' => $siteType
            ],
            'limit' => 1
        ]);

        // already exists
        if (is_array($sites) && count($sites)) {
            return;
        }

        try {
            $StartPage = $Project->firstChild();
            $StartPage = $StartPage->getEdit();

            if ($StartPage === null) {
                return;
            }

            $newSiteId = $StartPage->createChild($siteParams);
            $NewSite = $Project->get($newSiteId)->getEdit();

            if ($NewSite === null) {
                return;
            }

            $NewSite->setAttributes($siteParams);
            $NewSite->setAttribute('type', $siteType);
            $NewSite->save();
            $NewSite->activate();
        } catch (QUI\Exception) {
            // @todo collect errors and display them at the end
        }
    }

    /**
     * @return array<string, string>
     *
     * @throws QUI\Exception
     */
    protected function getLanguageUrls(string $type): array
    {
        $result = [];
        $Project = QUI::getProjectManager()->getStandard();

        if ($Project === null) {
            return $result;
        }

        $languages = $Project->getLanguages();
        $project = $Project->getName();

        foreach ($languages as $language) {
            $LanguageProject = QUI::getProject($project, $language);
            $sites = $LanguageProject->getSites([
                'where' => [
                    'type' => $type
                ],
                'limit' => 1
            ]);

            if (is_array($sites) && isset($sites[0])) {
                $result[$language] = $sites[0]->getUrl();
            } else {
                $result[$language] = '';
            }
        }

        return $result;
    }

    /**
     * @return string
     */
    public function getExecuteContent(): string
    {
        return QUI::getLocale()->get('ecoyn/core', 'execute.content');
    }

    /**
     * @return list<array{image: string, content: string}>
     */
    public function getExecuteSteps(): array
    {
        return [
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Invoice_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.invoice.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/AccountingExport_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.accountingExport.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Offers_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.offers.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Purchasing_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.purchasing.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Contracts_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.contracts.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/SalesOrders_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.salesOrders.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Cashbook_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.cashbook.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Plans_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.plans.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Dunning_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.dunning.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/SEPA_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.sepa.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Coupons_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.coupons.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/Discount_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.discount.description')
            ],
            [
                'image' => URL_OPT_DIR . 'ecoyn/core/bin/images/modules/StockManagement_Mockup.png',
                'content' => QUI::getLocale()->get('ecoyn/core', 'setup.data.modules.stockManagement.description')
            ]
        ];
    }
}
