<?php

use KupShop\OrderingBundle\Exception\DeliveryException;
use KupShop\OrderingBundle\Exception\PaymentException;

class Balikovna extends Delivery
{
    use DatabaseCommunication;

    public static $type = Delivery::TYPE_POINT;
    public static $className = 'Česká pošta - Balíkovna';

    protected $heureka_delivery_id = 'BALIKOVNA_DEPOTAPI';
    protected $zbozi_delivery_id = 'CESKA_POSTA_BALIKOVNA';

    protected $templateDescription = 'deliveries/delivery.Balikovna.description.tpl';
    protected $templateInit = 'deliveries/delivery.Balikovna.init.tpl';

    protected $AdminTemplateSettings = 'deliveries/block.delivery.Balikovna.tpl';

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

    protected $track_and_trace = 'https://www.postaonline.cz/trackandtrace/-/zasilka/cislo?parcelNumbers=[PACKAGE_ID]';

    public static $xmlFile = 'http://napostu.ceskaposta.cz/vystupy/balikovny.xml';

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

    public $zip;

    public $config = [
        'weight_limit' => 20,
        'price_limit' => 30000,
        'maxWeight' => 20.0,
        'maxLength' => 70.0, // Maximální rozměr strany položky
        'maxDimensions' => [70.0, 50.0, 50.0],
        // legacy config:
        'max_length' => 70, // Maximální rozměr jedné strany zásilky
        'max_dimensions' => 50, // Maximální rozměry 70 cm x 50cm x 50 cm
    ];

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

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

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

        $zip = trim($data['zip'] ?? '');

        if (!empty($zip)) {
            return $this->data += [
                'zip' => $zip,
            ];
        }

        $point = $data['balikovna_point'] ?? '';
        $point = json_decode($point, true);

        if (empty($point)) {
            return $this->data;
        }

        return $this->data += [
            'zip' => getVal('zip', $point),
            'point_name' => getVal('name', $point),
            'address' => getVal('address', $point),
            'subtype' => getVal('subtype', $point),
        ];
    }

    public function getInfo($zip = null)
    {
        if (is_null($zip) && getVal('point_name', $this->data)) {
            $data = [];
            $data['zip'] = getVal('zip', $this->data);
            $data['name'] = getVal('point_name', $this->data);
            $data['address'] = getVal('address', $this->data);
            $data['subtype'] = getVal('subtype', $this->data);
        } else {
            if (is_null($zip)) {
                $zip = getVal('zip', $this->data);
            }

            $data = sqlFetchAssoc(sqlQuery('SELECT * FROM '.self::$tableName.'
            WHERE zip=:zip',
                ['zip' => $zip]));

            if (!$data) {
                return ['name' => 'Neznámá pobočka'];
            }

            $data['hours'] = unserialize($data['hours']);
        }

        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['zip'])) {
            return 'Není zvolena Balíkovna!';
        }
        $data['delivery_zip'] = $info['zip'];
        $data['delivery_street'] = 'BALÍKOVNA';
        $data['delivery_city'] = $info['name'];
        $data['delivery_country'] = 'CZ';
        $data['delivery_firm'] = '';

        return true;
    }

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

        $info = $this->getInfo();

        if (empty($info['zip'])) {
            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'] = 'BALÍKOVNA';
        $cart->delivery['city'] = $info['name'];
        $cart->delivery['country'] = 'CZ';
        $cart->delivery['firm'] = '';
    }

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

        return "<strong>{$info['name']}</strong> PSČ: <strong>{$info['zip']}</strong>";
    }

    public function check(Cart $cart)
    {
        if ($price_limit = ($this->config['price_limit'] ?? 0)) {
            $price_limit = toDecimal($price_limit);
            if (!$cart->totalPricePay->lowerThan($price_limit)) {
                // Cenovy limit pro tento typ dopravy byl prekrocen
                throw new DeliveryException(sprintf(translate_shop('balikovna_price_limit', 'delivery'), $price_limit->printValue().' Kč.'),
                    translate_shop('price_limit_short', 'delivery'),
                    DeliveryException::ERROR_DELIVERY_DISABLED);
            }
        }

        return parent::check($cart);
    }

    public function checkSelected(Cart $cart, ?Payment $payment = null)
    {
        if (empty($this->data['zip']) && $cart->hasData('delivery')) {
            throw new DeliveryException(translate('branch_missing_zip', 'delivery'));
        }

        if (($payment instanceof Dobirka) && (Settings::getDefault()['deliveries']['Balikovna']['dobirkaBOX'] ?? null)) {
            $subtype = $this->data['subtype'] ?? null;
            if ($subtype == 'BOX') {
                throw new PaymentException('Platba dobírkou není dostupná v případě doručení do Balíkovna-BOXu. 
                                            Zvolte prosím pobočku jiného typu nebo platbu předem.', 'Nedostupná pro Balíkovna-BOX');
            }
        }

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

    protected static function generateOpeningHours($days)
    {
        $hours = [];
        foreach ($days->den as $day) {
            $fromTo = [];
            foreach ($day->od_do as $od_do) {
                $fromTo[] = [strval($od_do->od), strval($od_do->do)];
            }
            $hours[strval($day['name'])] = $fromTo;
        }

        return $hours;
    }

    public function import()
    {
        $xml = simplexml_load_file(self::$xmlFile);
        if ($xml->count() > 0) {
            sqlGetConnection()->transactional(function () use ($xml) {
                sqlQuery('DELETE FROM '.self::$tableName.' WHERE 1');

                foreach ($xml->row as $post) {
                    $data = [
                        'zip' => strval($post->PSC),
                        'name' => strval($post->NAZEV),
                        'city' => strval($post->OBEC),
                        'city_part' => strval($post->C_OBCE),
                        'address' => strval($post->ADRESA),
                        'hours' => serialize(self::generateOpeningHours($post->OTEV_DOBY)),
                    ];
                    sqlQueryBuilder()->insert(self::$tableName)->directValues($data)->execute();
                }
            });

            return true;
        }

        return false;
    }

    public function getDimensionsSum(array $dimensions)
    {
        // Maximální rozměry 70 cm x 50cm x 50 cm

        if ($dimensions[0] > 70) {
            return $dimensions[0];
        }

        if ($dimensions[1] > 50) {
            return $dimensions[1];
        }

        return $dimensions[2];
    }

    public static function getSettingsConfiguration(): array
    {
        return [
            'fields' => [
                'dobirkaBOX' => [
                    'title' => 'Zakázat dobírku pro Balíkovna-BOX',
                    'type' => 'toggle',
                    'tooltip' => 'Nepovolit platbu dobírkou při vybrání doručení do Balíkovna-BOXu',
                ],
            ],
        ];
    }

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