<?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.

use Shopware\Plugins\ViisonCommon\Classes\ExceptionHandling\BackendExceptionHandling;
use Shopware\Plugins\ViisonDHL\Classes\CreateShipmentOrderRequest;
use Shopware\Plugins\ViisonDHL\Classes\DHLPortalConfigScraper\DhlConfigScraperInvalidCredentialsException;
use Shopware\Plugins\ViisonDHL\Classes\DHLPortalConfigScraper\DhlContractData;
use Shopware\Plugins\ViisonDHL\Classes\DHLPortalConfigScraper\DhlConfigScraper;
use Shopware\Plugins\ViisonDHL\Classes\DHLPortalConfigScraper\DhlContractPosition;
use Shopware\Plugins\ViisonDHL\Classes\PluginInfo;
use Shopware\Plugins\ViisonDHL\Util;
use Shopware\Plugins\ViisonShippingCommon\Classes\ShippingProvider;
use Shopware\Plugins\ViisonShippingCommon\Controllers\Backend\ViisonShippingCommonConfig;

/**
 * This controller adds some actions called in the config backend controller.
 * These actions are responsible for creating, updating and deleting custom configurations
 * of the DHL Adapter which are associated with (sub-)shop configurations.
 */
class Shopware_Controllers_Backend_ViisonDHLConfig extends ViisonShippingCommonConfig
{
    use BackendExceptionHandling;

    /**
     * @var array
     */
    private static $productCodeToConfigFieldMapping = [
        'V01PAK' => 'partnerIdEPN',
        'V01PRIO' => 'partnerIdEPO',
        'V53WPAK' => 'partnerIdBPI',
        'V54EPAK' => 'partnerIdEPI',
        'V55PAK' => 'partnerIdBPC',
        'V62WP' => 'partnerIdWAP',
        'V66WPI' => 'partnerIdWPI',
    ];

    public function __construct(Enlight_Controller_Request_Request $request = null, Enlight_Controller_Response_Response $response = null)
    {
        parent::__construct($request, $response, Util::instance());
    }

    /**
     * Returns an array containing all field keys that should be stored encrypted.
     * @return array
     */
    protected function getEncryptedFields()
    {
        return [];
    }

    /**
     * Action to get the supported shipping countries for Label creation.
     *
     * The shipping countries are grouped by Local and International shipping.
     * Right now the only International shipping is supported by DHL Express.
     * The Countries are sorted by Int shipping and also a separator is included for the UI.
     *
     * Note: The country model is expanded by:
     *       groupingTitle - The seperator name for the UI if needed
     *       codes - The participant codes used for the partnerId + defaultShippmentWeight
     *       isInternationalShipping - Flag to say if the Country supports only Int shipping
     */
    public function getSupportedCountriesAction()
    {
        try {
            /** @var PluginInfo */
            $supportedCountriesIsoWithParticipationCodes = $this->pluginInfo->getDefinedParticipantCodesForCountries();
            $countriesTable = new \Zend_Db_Table('s_core_countries');
            $supportedCountriesResults = $countriesTable->fetchAll($countriesTable->select())->toArray();
            $namespace = $this->get('snippets')->getNamespace('backend/viison_dhl_util/util');

            $util = $this->util; // PHP 5.3 compatibility
            $supportedCountriesResults = array_map(
                // Add participant codes field to country if listen in $supportedCountriesIsoWithParticipationCodes
                function ($country) use ($supportedCountriesIsoWithParticipationCodes, $util, $namespace) {
                    $match = $supportedCountriesIsoWithParticipationCodes[$country['countryiso']];
                    $isShopLanguageGerman = ($util->getShopLanguage() === 'de');
                    $isInternationalShipping = empty($match);

                    $country['isInternationalShipping'] = $isInternationalShipping;
                    if ($isInternationalShipping) {
                        $country['codes'] = [];
                        $country['groupingTitle'] = $namespace->get('seperator_message/config/only_express');
                    } else {
                        $country['codes'] = $match;
                        $country['groupingTitle'] = $namespace->get('seperator_message/config/with_express');
                    }

                    // Localize country name by shop language
                    $country['countryname'] = $country[($isShopLanguageGerman === true) ? 'countryname' : 'countryen'];

                    return $country;
                },
                $supportedCountriesResults
            );

            // Sort countries by DHL shipping, so at the top are the one with DHL + Express
            usort($supportedCountriesResults, function ($country) {
                return $country['isInternationalShipping'];
            });

            $this->View()->assign([
                'success' => (empty($supportedCountriesResults)) ? false : true,
                'data' => $supportedCountriesResults,
                'message' => (empty($supportedCountriesResults)) ? 'Empty Country Results!' : '',
            ]);
        } catch (Exception $e) {
            $this->handleException($e);
        }
    }

    /**
     * Take a DHL GKP login, verify it and fetch the customer number and the billing numbers.
     */
    public function getDataFromScraperAction()
    {
        $username = $this->Request()->getParam('username');
        $password = $this->Request()->getParam('password');

        try {
            $dhlService = new DhlConfigScraper($username, $password);

            /** @var DhlContractData $dhlContractData */
            $dhlContractData = $dhlService->scrape();

            $this->View()->assign([
                'success' => true,
                'EKP' => $dhlContractData->getCustomerNumberAsEkp(),
                'accountInformation' => $this->getProductInformationWithConfigFieldsMapping(
                    $dhlContractData->getBookedProducts()
                ),
            ]);
        } catch (DhlConfigScraperInvalidCredentialsException $e) {
            $this->handleException($e);
            $this->View()->error_cause = 'login_failed';
        } catch (Exception $e) {
            $this->handleException($e);
        }
    }

    /**
     * @param DhlContractPosition[] $dhlContractPositions
     * @return array
     */
    private function getProductInformationWithConfigFieldsMapping(array $dhlContractPositions)
    {
        $result = [];

        /** @var DhlContractPosition[] $dhlContractPositions */
        foreach ($dhlContractPositions as $dhlContractPosition) {
            $key = self::$productCodeToConfigFieldMapping[$dhlContractPosition->getProductCode()];
            $result[$key] = [
                'attendanceNumbers' => $dhlContractPosition->getAttendanceNumbers(),
                'productName' => $dhlContractPosition->getProductName(),
            ];
        }

        return $result;
    }

    /**
     * Take a DHL GKP login, verify it and fetch the customer number and the billing numbers.
     */
    public function verifyCredentialsAction()
    {
        $username = $this->Request()->getParam('username');
        $password = $this->Request()->getParam('password');

        try {
            $dhlService = new DhlConfigScraper($username, $password);

            $this->View()->assign([
                'success' => true,
                'areCredentialsValid' => $dhlService->checkCredentials(),
            ]);
        } catch (Exception $e) {
            $this->handleException($e);
        }
    }

    /**
     * @Override
     * @return array Data that can be used inside the Views
     */
    public function getViewParams()
    {
        return array_merge(
            parent::getViewParams(),
            [
                'retoureCountries' => Shopware\Plugins\ViisonDHL\Classes\OnlineRetoureCommunication::getRetoureCountries(),
                'viisonGdprConfig' => [
                    'never' => ShippingProvider::GDPR_NEVER,
                    'always' => ShippingProvider::GDPR_ALWAYS,
                    'customerChoice' => ShippingProvider::GDPR_CUSTOMER_CHOICE,
                ],
            ]
        );
    }

    /**
     * @inheritdoc
     */
    protected function getSecretFields()
    {
        return [
            'password',
            'expressPassword',
        ];
    }
}
