<?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\ViisonDHL\Classes\DHLPortalConfigScraper;

class DhlContractData
{
    /**
     * Associative array of products recognized by the DhlConfigScraper. The key is the unique product code used for
     * API requests. Value is an associative array filled with the product name and the product process code.
     *
     * @var array
     */
    private static $knownProducts = [
        'V01PAK' => [
            'processCode' => '01',
            'name' => 'DHL Paket',
            'bookingTexts' => [
                'DHL PAKET GKP',
            ],
        ],
        'V01PRIO' => [
            'processCode' => '01',
            'name' => 'DHL Paket Prio',
            'bookingTexts' => [
                'DHL PAKET PRIO',
            ],
        ],
        'V54EPAK' => [
            'processCode' => '54',
            'name' => 'DHL Europaket',
            'bookingTexts' => [],
        ],
        'V55PAK' => [
            'processCode' => '55',
            'name' => 'DHL Paket Connect',
            'bookingTexts' => [],
        ],
        'V53WPAK' => [
            'processCode' => '53',
            'name' => 'DHL Paket International',
            'bookingTexts' => [
                'DHL PAKET INTERNATIONAL',
                'DHL PAKET INTERN. GKP',
            ],
        ],
        'V62WP' => [
            'processCode' => '62',
            'name' => 'Warenpost',
            'bookingTexts' => [
                'WARENPOST',
                'WARENPOST INKLUSIVE ABHOLUN',
            ],
        ],
        'V66WPI' => [
            'processCode' => '66',
            'name' => 'Warenpost International',
            'bookingTexts' => [],
        ],
    ];

    /**
     * @var string
     */
    private $customerNumber;

    /**
     * @var array
     */
    private $billingNumbers;

    /**
     * @param string $customerNumber
     * @param array $billingNumbers
     */
    public function __construct($customerNumber, array $billingNumbers)
    {
        $this->customerNumber = $customerNumber;
        $this->billingNumbers = $billingNumbers;
    }

    /**
     * @return string
     */
    public function getCustomerNumber()
    {
        return $this->customerNumber;
    }

    /**
     * @return array
     */
    public function getBillingNumbers()
    {
        return $this->billingNumbers;
    }

    /**
     * @return string
     */
    public function getCustomerNumberAsEkp()
    {
        return mb_substr($this->customerNumber, 0, 10, 'UTF-8');
    }

    /**
     * Convert an array of billing numbers as received from DHLService into an array of DhlContractPositions.
     *
     * @return DhlContractPosition[]
     */
    public function getBookedProducts()
    {
        $result = [];

        foreach ($this->billingNumbers as $productName => $accountNumbers) {
            $product = $this->findDhlProductByNameAndAccountNumber(
                $productName,
                $accountNumbers[0]
            );

            if (!$product) {
                continue;
            }

            $result[] = new DhlContractPosition(
                $this->extractAttendanceNumbersFromAccountNumbers($accountNumbers),
                $product['name'],
                $product['code'],
                $product['processCode']
            );
        }

        return $result;
    }

    /**
     * Tries to find the the associated DHL Product via name and account number.
     *
     * @param string $bookingText
     * @param string $accountNumber
     * @return array|null
     */
    private function findDhlProductByNameAndAccountNumber($bookingText, $accountNumber)
    {
        $processCode = $this->extractProcessCodeFromAccountNumber($accountNumber);

        foreach (self::$knownProducts as $productCode => $product) {
            if ($product['processCode'] !== $processCode) {
                continue;
            }
            if (empty($product['bookingTexts'])) {
                $result = $product;
                $result['code'] = $productCode;

                return $result;
            }
            if (in_array($bookingText, $product['bookingTexts'])) {
                $result = $product;
                $result['code'] = $productCode;

                return $result;
            }
        }

        // If this case happens (example DHL Retorue from DHL GKP is not in our supported list), we return null.
        return null;
    }

    /**
     * @param string $billingNumber
     * @return string
     */
    private function extractProcessCodeFromAccountNumber($billingNumber)
    {
        return mb_substr($billingNumber, 10, 2, 'UTF-8');
    }

    /**
     * @param array $billingNumbers
     * @return array
     */
    private function extractAttendanceNumbersFromAccountNumbers(array $billingNumbers)
    {
        return array_map(
            function ($billingNumber) {
                return mb_substr($billingNumber, 12, 2, 'UTF-8');
            },
            $billingNumbers
        );
    }
}
