<?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\ViisonShippingCommon\Installation;

use \Enlight_Components_Db_Adapter_Pdo_Mysql;
use Shopware\Components\DependencyInjection\Container;
use Shopware\Components\Model\ModelManager;
use Shopware\Plugins\ViisonCommon\Classes\Installation\ArticleAttributeElement;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeColumn\AttributeColumnDescription;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeColumn\AttributeColumnInstaller;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeColumn\AttributeColumnUninstaller;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeConfiguration\InstallationHelper;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeConfiguration\UninstallationHelper;
use Shopware\Plugins\ViisonCommon\Classes\Installation\SQLHelper;

/**
 * Handles installing and uninstalling ViisonShippingCommon.
 */
class ShippingCommonInstaller
{
    /** @var ModelManager $db */
    private $entityManager;
    /** @var SQLHelper $sqlHelper */
    private $sqlHelper;
    /** @var Enlight_Components_Db_Adapter_Pdo_Mysql $db */
    private $db;
    /** @var Container $container */
    private $container;

    public function __construct(
        ModelManager $entityManager,
        SQLHelper $sqlHelper,
        Enlight_Components_Db_Adapter_Pdo_Mysql $db,
        Container $container
    ) {
        $this->entityManager = $entityManager;
        $this->sqlHelper = $sqlHelper;
        $this->db = $db;
        $this->container = $container;
    }

    /**
     * Perform the necessary installation steps for ViisonShippingCommon.
     */
    public function installViisonShippingCommon()
    {
        $articleAttributeElementInstallationHelper = new ArticleAttributeElement\InstallationHelper($this->entityManager);
        $attributeInstallationHelper = new AttributeColumnInstaller($this->entityManager, $this->sqlHelper);
        $attributeConfigurationInstallationHelper = new InstallationHelper($this->entityManager);

        $attributeInstallationHelper->addAttributeColumnsIfNotExist([
            new AttributeColumnDescription(
                's_order_attributes',
                'viison_transfer_customer_contact_data_allowed',
                'tinyint(1)',
                false,
                false
            ),
            new AttributeColumnDescription(
                's_order_attributes',
                'viison_cash_on_delivery_shipment_identifier',
                'VARCHAR(255)'
            ),
            new AttributeColumnDescription(
                's_order_attributes',
                'viison_return_label_tracking_id',
                'VARCHAR(255)'
            ),
            // Add country of origin and tariff number field (is used for export documents)
            new AttributeColumnDescription(
                's_articles_attributes',
                'viison_country_of_origin',
                'INT(11)'
            ),
            new AttributeColumnDescription(
                's_articles_attributes',
                'viison_customs_tariff_number',
                'VARCHAR(255)'
            ),
        ]);

        $attributeConfigurationInstallationHelper->createAttributeConfigurationUnlessExists(
            's_order_attributes',
            'viison_transfer_customer_contact_data_allowed',
            'boolean',
            'Weitergabe der Daten an Versanddienstleister gestattet',
            'Dieses Feld zeigt an, ob der Kunde der Übermittlung von E-Mail-Adresse und Telefonnummer an den Versanddienstleister zugestimmt hat.'
        );
        // Update attribute field label and hint to reflect that only the mail is managed by the attribute
        if (class_exists('Shopware\\Models\\Attribute\\Configuration')) {
            // Attribute configurations exists only since SW 5.2
            $dataTransferConfigurationField = $this->entityManager->getRepository('Shopware\\Models\\Attribute\\Configuration')->findOneBy([
                'tableName' => 's_order_attributes',
                'columnName' => 'viison_transfer_customer_contact_data_allowed',
            ]);
            if ($dataTransferConfigurationField) {
                $dataTransferConfigurationField->setLabel('Weitergabe der Kunden-E-Mail an Versanddienstleister gestattet');
                $dataTransferConfigurationField->setHelpText('Dieses Feld zeigt an, ob der Kunde der Übermittlung seiner E-Mail-Adresse an den Versanddienstleister zugestimmt hat.');
                $this->entityManager->flush($dataTransferConfigurationField);
            }
        }

        // Add element for the customs tariff number (element is converted to attribute configuration
        // automatically when installing in Shopware >= 5.2)
        $articleAttributeElementInstallationHelper->createArticleAttributeElementUnlessNameExists(
            'string',
            'viisonCustomsTariffNumber',
            'Zolltarifnummer',
            'Hinterlegen Sie hier die Zolltarifnummer, die bei Erstellung von Exportdokumenten verwendet werden soll.',
            101
        );

        // Add element for the country of origin (element cannot be converted automatically for Shopware
        // >= 5.2, because it represents an entity selection)
        if (class_exists('Shopware\Models\Attribute\Configuration')) {
            $attributeConfigurationInstallationHelper->createAttributeConfigurationUnlessExists(
                's_articles_attributes',
                'viison_country_of_origin',
                'single_selection',
                'Herkunftsland',
                'Hinterlegen Sie hier das Herkunftsland des Artikels, das bei Erstellung von Exportdokumenten verwendet werden soll.',
                102,
                'Shopware\Models\Country\Country'
            );
        } else {
            // Shopware < 5.2
            $articleAttributeElementInstallationHelper->createArticleAttributeElementUnlessNameExists(
                'select',
                'viisonCountryOfOrigin',
                'Herkunftsland',
                'Hinterlegen Sie hier das Herkunftsland des Artikels, das bei Erstellung von Exportdokumenten verwendet werden soll.',
                102,
                null,
                false,
                true,
                'base.Country'
            );
        }

        $attributeConfigurationInstallationHelper->createAttributeConfigurationUnlessExists(
            's_order_attributes',
            'viison_return_label_tracking_id',
            'string',
            'Trackingcodes von Retourenetiketten',
            'Trackingcodes von Retourenetiketten'
        );

        // Load snippets
        $this->container->get('shopware.snippet_database_handler')->loadToDatabase(__DIR__ . '/../Snippets/');
    }

    /**
     * Uninstall ViisonShippingCommon if at most one plugin using ViisonShippingCommon is installed (which means this
     * method was called because the last one is being uninstalled).
     *
     * Usage: Call once in the uninstall method.
     *
     */
    public function uninstallViisonShippingCommon()
    {
        if ($this->numberOfPluginsUsingShippingCommon() > 1) {
            return;
        }

        $attributeUninstallationHelper = new AttributeColumnUninstaller($this->entityManager, $this->sqlHelper);
        $attributeConfigurationUninstallationHelper = new UninstallationHelper($this->entityManager);
        $articleAttributeElementUninstallHelper = new ArticleAttributeElement\UninstallationHelper($this->entityManager);

        // Remove custom attribute configurations/elements
        $articleAttributeElementUninstallHelper->removeArticleAttributeElementsIfExist([
            'viisonCustomsTariffNumber',
            'viisonCountryOfOrigin',
        ]);

        $attributeUninstallationHelper->removeAttributeColumnsIfExist([
            new AttributeColumnDescription(
                's_order_attributes',
                'viison_transfer_customer_contact_data_allowed',
                'tinyint(1)'
            ),
            new AttributeColumnDescription(
                's_order_attributes',
                'viison_cash_on_delivery_shipment_identifier'
            ),
            new AttributeColumnDescription(
                's_articles_attributes',
                'viison_country_of_origin',
                'INT(11)'
            ),
            new AttributeColumnDescription(
                's_articles_attributes',
                'viison_customs_tariff_number',
                'VARCHAR(255)'
            ),
        ]);

        $attributeConfigurationUninstallationHelper->removeAttributeConfigurationsIfExist([
            's_order_attributes' => ['viison_transfer_customer_contact_data_allowed'],
            's_articles_attributes' => ['viison_country_of_origin'],
            's_articles_attributes' => ['viison_customs_tariff_number'],
        ]);
    }

    /**
     * Counts the installed plugins which use ViisonShippingCommon.
     *
     * @return int
     */
    private function numberOfPluginsUsingShippingCommon()
    {
        // Find all installed VIISON plugins
        $installedViisonPlugins = $this->db->fetchAll(
            'SELECT source, namespace, name
            FROM s_core_plugins
            WHERE name LIKE \'Viison%\'
            AND installation_date IS NOT NULL'
        );

        // `shopware.plugin_directories` is available since SW 5.2
        if ($this->container->hasParameter('shopware.plugin_directories')) {
            $pluginRootPaths = $this->container->getParameter('shopware.plugin_directories');
        } else {
            $pluginRootDir = $this->container->getParameter('kernel.root_dir') . '/engine/Shopware/Plugins/';
            $pluginRootPaths = [
                'Default' => $pluginRootDir . 'Default',
                'Local' => $pluginRootDir . 'Local',
                'Community' => $pluginRootDir . 'Community',
            ];
        }

        // Check the plugin directories for 'ViisonShippingCommon'
        $shippingCommonPlugins = array_filter($installedViisonPlugins, function ($plugin) use ($pluginRootPaths) {
            return realpath($pluginRootPaths[$plugin['source']] . '/' . $plugin['namespace'] . '/' . $plugin['name'] . '/ViisonShippingCommon') !== false;
        });

        return count($shippingCommonPlugins);
    }
}
