<?php

use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\OrderingBundle\Exception\DeliveryException;

class Zasilkovna extends Delivery
{
    use DatabaseCommunication;

    public static $type = Delivery::TYPE_POINT;
    public static $className = 'Zásilkovna';

    protected $templateDescription = 'deliveries/delivery.Zasilkovna.widget.tpl';
    protected $templateInit = 'deliveries/delivery.Zasilkovna.init.tpl';

    protected $AdminTemplateSettings = 'deliveries/block.delivery.Zasilkovna.tpl';
    protected $adminWindowTemplate = 'delivery/settings.Zasilkovna.tpl';

    public static $tableName = '`kupshop_shared`.`delivery_zasilkovna`';

    protected $track_and_trace = [
        'CZ' => 'https://tracking.packeta.com/cs/?id=[PACKAGE_ID]',
        'DE' => 'https://tracking.packeta.com/de/?id=[PACKAGE_ID]',
        'HR' => 'https://tracking.packeta.com/hr/?id=[PACKAGE_ID]',
        'SI' => 'https://tracking.packeta.com/sl/?id=[PACKAGE_ID]',
        'RO' => 'https://tracking.packeta.com/ro/?id=[PACKAGE_ID]',
        'SK' => 'https://tracking.packeta.com/sk/?id=[PACKAGE_ID]',
        'HU' => 'https://tracking.packeta.com/hu/?id=[PACKAGE_ID]',
        'DK' => 'https://tracking.packeta.com/dk/?id=[PACKAGE_ID]',
        'ES' => 'https://tracking.packeta.com/es/?id=[PACKAGE_ID]',
        'FI' => 'https://tracking.packeta.com/fi/?id=[PACKAGE_ID]',
        'FR' => 'https://tracking.packeta.com/fr/?id=[PACKAGE_ID]',
        'BE' => 'https://tracking.packeta.com/fr/?id=[PACKAGE_ID]',
        'IE' => 'https://tracking.packeta.com/en/?id=[PACKAGE_ID]',
        'IT' => 'https://tracking.packeta.com/it/?id=[PACKAGE_ID]',
        'PL' => 'https://tracking.packeta.com/pl/?id=[PACKAGE_ID]',
        'SV' => 'https://tracking.packeta.com/sv/?id=[PACKAGE_ID]',
        'LV' => 'https://tracking.packeta.com/lv/?id=[PACKAGE_ID]',
        'LT' => 'https://tracking.packeta.com/lt/?id=[PACKAGE_ID]',
        'EE' => 'https://tracking.packeta.com/et/?id=[PACKAGE_ID]',
        'UA' => 'https://tracking.packeta.com/uk/?id=[PACKAGE_ID]',
        'GR' => 'https://tracking.packeta.com/el/?id=[PACKAGE_ID]',
    ];

    public static $jsonDelivery = 'http://www.zasilkovna.cz/api/v4/80aa13c913f62111/branch.json';

    protected $heureka_delivery_id = 'ZASILKOVNA';
    protected $zbozi_delivery_id = 'ZASILKOVNA';

    public $zip;

    public $config = [
        'maxCOD' => 20000,
        'maxWeight' => 10.0,
        'maxLength' => 120.0, // Maximální rozměr strany položky
        'maxSumOfDimensions' => 150.0, // Maximální součet rozměrů všech tří stran položky
        // legacy config:
        'limit' => [
            'CZK' => 20000,
            'EUR' => 700,
        ],
        'weight_limit' => 15,
        'max_length' => 70, // Maximální rozměr jedné strany zásilky: 70 cm
        'max_dimensions' => 150, // Maximální součet rozměrů všech tří stran zásilky
    ];

    public $defaultIcon = '../../common/static/deliveries/zasilkovna.svg';

    public static function getSettingsConfiguration(): array
    {
        return [
            'fields' => [
                'apiKey' => [
                    'title' => 'API klíč',
                    'type' => 'text',
                ],
            ],
        ];
    }

    public function getName()
    {
        $info = self::getInfo();

        return parent::getName().' - '.$info['name'];
    }

    public function storeDeliveryInfo($data): array
    {
        parent::storeDeliveryInfo($data);

        $pointData = $data['zasilkovna_point_data'] ?? '';
        $pointData = json_decode($pointData, true);

        if (empty($pointData)) {
            return [];
        }

        $label = getVal('routingCode', $pointData) ?? getVal('labelRouting', $pointData);

        return $this->data += [
            'fromWidget' => true,
            'idZ' => $pointData['id'] ?? $pointData['idZ'] ?? '',
            'carrierId' => $pointData['carrierId'] ?? null,
            'zip' => getVal('zip', $pointData),
            'hours' => getVal('openingHours', $pointData) ?? getVal('hours', $pointData),
            'street' => getVal('street', $pointData),
            'country' => strtoupper(getVal('country', $pointData)),
            'city' => getVal('city', $pointData),
            'place_name' => getVal('name', $pointData),
            'place' => getVal('place', $pointData),
            'labelRouting' => $label,
            'directions' => getVal('directions', $pointData),
        ];
    }

    public function setPointId($id): self
    {
        $this->data['idZ'] = $id;

        return $this;
    }

    public function getPointId()
    {
        return $this->data['idZ'] ?? null;
    }

    public function getInfo($idZ = null)
    {
        $data = null;

        if (is_null($idZ)) {
            $idZ = $this->data['idZ'] ?? null;
        }

        if (getVal('fromWidget', $this->data)) {
            $data = $this->data;
            $data['name'] = getVal('name', $this->data) ?? getVal('place_name', $this->data);
            unset($data['place_name']);
        } elseif ($idZ) {
            $data = sqlFetchAssoc(sqlQuery('SELECT * FROM '.self::$tableName.'
                    WHERE id=:id',
                ['id' => $idZ]));

            if ($data) {
                $data['idZ'] = $data['id'];
                $data['hours'] = unserialize($data['hours']);
                $data['address'] = $data['street'].', '.$data['zip'].', '.$data['city'];
            }
        }

        if (!$data) {
            return [
                'name' => 'Neznámá pobočka',
                'city' => 'Neznámé',
                'place' => 'Neznámé',
                'street' => 'Neznámé',
                'zip' => 'Neznámé',
                'country' => 'Neznámé',
                'idZ' => $idZ,
            ];
        }

        return $data;
    }

    /**
     * @param       $data  admin order data
     * @param Order $order
     *
     * @return bool|string
     */
    public function applyToOrder(&$data, $order)
    {
        parent::applyToOrder($data, $order);

        $info = $this->getInfo();
        if (empty($info['labelRouting'])) {
            $this->data['labelRouting'] = null;

            return 'Není zvolena zásilkovna!';
        }
        $data['delivery_zip'] = $info['zip'];
        $data['delivery_street'] = $info['street'];
        $data['delivery_city'] = $info['city'];
        $data['delivery_country'] = $info['country'];
        $data['delivery_firm'] = $info['place'];

        return true;
    }

    /**
     * @param $cart CartBase
     */
    public function applyToCart(CartBase $cart)
    {
        parent::applyToCart($cart);

        $info = $this->getInfo();

        if (empty($info['labelRouting'])) {
            return;
        }

        if (isset($cart->invoice['name'])) {
            $cart->delivery['name'] = $cart->invoice['name'];
            $cart->delivery['surname'] = $cart->invoice['surname'];
        }

        $cart->delivery['zip'] = $info['zip'];
        $cart->delivery['street'] = $info['street'];
        $cart->delivery['city'] = $info['city'];
        $cart->delivery['country'] = $info['country'];
        $cart->delivery['firm'] = $info['place'];
    }

    public function printDeliveryInfo()
    {
        $info = $this->getInfo();

        return "<strong>{$info['city']}</strong>, {$info['street']}, {$info['place']}, <strong>{$info['zip']}</strong>";
    }

    public function check(Cart $cart)
    {
        if ($weight_limit = ($this->config['weight_limit'] ?? 0)) {
            if ($cart->getTotalWeight() > $weight_limit) {
                // Vahovy limit pro tento typ dopravy byl prekrocen
                throw new DeliveryException(translate_shop('weight_limit', 'delivery'),
                    translate_shop('weight_limit_short', 'delivery'),
                    DeliveryException::ERROR_DELIVERY_DISABLED);
            }
        }

        return parent::check($cart);
    }

    public function checkSelected(Cart $cart, ?Payment $payment = null)
    {
        // check selected combination of delivery and payment

        if (($cart->max_step != 0) && ($payment instanceof Dobirka)) {
            $currencyContext = ServiceContainer::getService(CurrencyContext::class);
            $currency = $currencyContext->getActive();
            if (!empty($this->config['limit'][$currency->getId()])) {
                $limit = toDecimal($this->config['limit'][$currency->getId()]);
                if (!$cart->totalPricePay->lowerThan($limit)) {
                    throw new DeliveryException(sprintf(translate_shop('zasilkovna_dobirka_limit', 'delivery'),
                        $limit->printValue().' '.$currency->getSymbol()), '', DeliveryException::ERROR_DELIVERY_DISABLED);
                }
            }
        }

        if ($cart->hasData('delivery')) {
            if (empty($this->data['labelRouting'])) {
                throw new DeliveryException(translate('branch_missing_zip', 'delivery'));
            }

            $info = $this->getInfo();
            if (empty($info['labelRouting'])) {
                throw new DeliveryException('Neznámá pobočka.');
            }
            $currencyContext = ServiceContainer::getService(CurrencyContext::class);
            $currency = $this->custom_data['balikobot']['currency'] ?? $currencyContext->getActiveId();

            if (
                !empty($this->data['labelRouting'])
                && !in_array($info['country'], $this->getCountryByCurrency($currency))
            ) {
                throw new DeliveryException(translate('branch_currency_not_supported', 'delivery'));
            }
        }

        return parent::checkSelected($cart, $payment);
    }

    public function import()
    {
        $json = file_get_contents(self::$jsonDelivery);
        $data = json_decode_strict($json, true);

        if (count($data) > 0) {
            sqlGetConnection()->transactional(function () use ($data) {
                sqlQuery('UPDATE '.self::$tableName.'  SET visible = "N" ');
                $separatedCol = [
                    'id',
                    'zip',
                    'street',
                    'country',
                    'city',
                    'name',
                    'place',
                    'labelRouting',
                    'directions',
                    'url',
                ];

                $excludeColumns = [
                    'photos',
                ];

                foreach ($data['data'] as $id => $branch) {
                    $data = [];
                    foreach ($branch as $title => $value) {
                        if (in_array($title, $separatedCol)) {
                            if ($title == 'zip') {
                                $data[$title] = str_replace(' ', '', $value);
                            } elseif ($title == 'url') {
                                if (is_array($value)) {
                                    $data[$title] = serialize($value);
                                } else {
                                    $data[$title] = $value;
                                }
                            } elseif ($title == 'country') {
                                $data[$title] = strtoupper($value);
                            } else {
                                if ($value === []) { // Sulini tam obcas misto prazdnyho stringu maji prazdny objekt
                                    $value = '';
                                }
                                $data[$title] = $value;
                            }
                        } elseif ($title == 'openingHours') {
                            //                            foreach ($value['regular'] as $day => $hours) {
                            //                                $formatter = new IntlDateFormatter('cs_CZ', IntlDateFormatter::FULL, IntlDateFormatter::FULL);
                            //                                $formatter->setPattern('EEEE');
                            //                                $p = $formatter->format(new DateTime($day));
                            //
                            //                                $openingHours[mb_convert_case($p, MB_CASE_TITLE, 'UTF-8')] = $hours;
                            //                            }
                            $data['hours'] = serialize($value['compactShort']);
                        } elseif (!in_array($title, $excludeColumns)) {
                            $data['data'][$title] = $value;
                        }
                    }
                    $data['data'] = serialize($data['data']);
                    $data['visible'] = 'Y';

                    $this->replaceSQL(self::$tableName, $data);
                }
            });

            return true;
        }

        return false;
    }

    protected function getCountryByCurrency($currency): array
    {
        switch ($currency) {
            case 'CZK':
                return ['CZ'];
                break;
            case 'EUR':
                return ['SK', 'DE', 'AT', 'FR', 'ES', 'HR', 'IT'];
                break;
            case 'HUF':
                return ['HU'];
                break;
            case 'RON':
                return ['RO'];
                break;
            case 'PLN':
                return ['PL'];
                break;
            default:
                return [];
        }
    }

    public function ZBOXOnly(): bool
    {
        $vendors = $this->getCustomData()['widget_options']['vendors'] ?? [];

        foreach ($vendors as $vendor) {
            if (($vendor['group'] ?? '') != 'zbox') {
                return false;
            }
        }

        return true;
    }
}
