<?php

namespace KupShop\BalikonosBundle\Tests;

use KupShop\BalikonosBundle\Balikobot;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;

class BalikobotTest extends \DatabaseTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        $dbcfg = \Settings::getDefault();

        // Balikobot settings
        $dbcfg->balikobot['delivery_type'][3]['carrier'] = 'cp';
        $dbcfg->balikobot['delivery_type'][3]['carrierService'] = 'DR';
        $dbcfg->balikobot['delivery_type'][3]['message_name'] = 'Česká Pošta';

        // Balikobot config
        $cfg = Config::get();
        $cfg['Modules']['balikonos'] = [
            'test' => true,
            'provider' => 'balikobot',
        ];

        $dbcfg = \Settings::getDefault();
        $dbcfg->balikobot['cod_remaining'] = 'Y';
        $dbcfg->balikobot['users'][] = [
            'name' => 'Test user',
            'user' => 'test20cztest',
            'key' => 'QKCufcWs',
        ];
        $dbcfg->saveToDB();
    }

    public function testBalikobotDataWithoutOrder()
    {
        /** @var Balikobot $service */
        $service = ServiceContainer::getService(Balikobot::class);

        $service->setIDs(
            [
                0 => [
                    'type' => Balikobot::TYPE_RECLAMATION,
                    'order_id' => 'R123',
                    'invoice_email' => 'test@wpj.cz',
                    'invoice_name' => 'Ondrej',
                    'invoice_surname' => 'Benes',
                    'invoice_street' => 'Za komínem 5',
                    'invoice_city' => 'Trutnov',
                    'invoice_zip' => '54101',
                    'invoice_phone' => '+420773131529',
                    'total_price' => 299,
                    'cod_price' => 0,
                    'weights' => 0.5,
                    'id_delivery' => 3,
                ],
            ]
        );

        $data = $service->getOrdersData();

        if (isset($data[0]['balikobot_array']['eid'])) {
            $timestampArr = explode('_', $data[0]['balikobot_array']['eid']);
        }

        $var = [
            0 => [
                'balikobot_array' => [
                    'eid' => 'R123_'.($timestampArr[1] ?? time()),
                    'real_order_id' => 'R123',
                    'vs' => 'R123',
                    'service_type' => 'DR',
                    'price' => 299,
                    'cod_currency' => 'CZK',
                    'rec_phone' => '+420773131529',
                    'rec_name' => 'Ondrej Benes',
                    'rec_firm' => null,
                    'rec_street' => 'Za komínem 5',
                    'rec_city' => 'Trutnov',
                    'rec_email' => 'test@wpj.cz',
                    'rec_zip' => '54101',
                    'rec_country' => 'CZ',
                    'del_evening' => false,
                    'cod_price' => 0,
                    'services' => '1A',
                    'weight' => 0.5,
                    'note' => null,
                    'return_full_errors' => true,
                    'size' => null,
                    'ins_currency' => 'CZK',
                    'return_track' => true,
                    'reference' => 'R123',
                ],
                'weights' => 0.5,
                'invoice_name' => 'Ondrej',
                'invoice_surname' => 'Benes',
                'invoice_firm' => null,
                'invoice_street' => 'Za komínem 5',
                'invoice_city' => 'Trutnov',
                'invoice_zip' => '54101',
                'invoice_country' => null,
                'order_no' => null,
                'total_price' => 299,
                'currency' => 'CZK',
                'id' => '',
                'weight' => 0.5,
                'carrier_code' => 'cp',
                'packages' => null,
                'note' => null,
                'size' => null,
                'id_delivery' => 3,
                'invoice_email' => 'test@wpj.cz',
                'invoice_phone' => '+420773131529',
                'order_id' => 'R123',
                'cod_price' => 0,
                'type' => Balikobot::TYPE_RECLAMATION,
                'invoice_custom_address' => null,
            ],
        ];

        $this->assertEquals($var, $data);
    }

    public function testBalikobotData()
    {
        /** @var Balikobot $service */
        $service = ServiceContainer::getService(Balikobot::class);

        $service->setIDs([1 => ['weights' => 0.5]]);
        $data = $service->getOrdersData();

        if (isset($data[0]['balikobot_array']['eid'])) {
            $timestampArr = explode('_', $data[0]['balikobot_array']['eid']);
        }

        $var = [
            0 => [
                'balikobot_array' => [
                    'eid' => '201300025_'.($timestampArr[1] ?? time()),
                    'real_order_id' => '201300025',
                    'vs' => '201300025',
                    'service_type' => 'DR',
                    'price' => '1692.80',
                    'cod_currency' => 'CZK',
                    'rec_phone' => '+420774123456',
                    'rec_name' => 'Lukáš Klíma',
                    'rec_firm' => 'WPJ s.r.o.',
                    'rec_street' => 'Za komínem 5',
                    'rec_city' => 'Trutnov',
                    'rec_email' => 'klima@wpj.cz',
                    'rec_zip' => '54101',
                    'rec_country' => 'CZ',
                    'del_evening' => false,
                    'cod_price' => '693',
                    'services' => '1A',
                    'weight' => 0.5,
                    'note' => null,
                    'return_full_errors' => true,
                    'size' => null,
                    'ins_currency' => 'CZK',
                    'return_track' => true,
                    'reference' => '201300025',
                    'content_invoice_number' => '201300025',
                    'content_issue_date' => '2013-09-13',
                ],
                'weights' => 0.5,
                'invoice_name' => 'Lukáš',
                'invoice_surname' => 'Klíma',
                'invoice_firm' => 'WPJ s.r.o.',
                'invoice_street' => 'Za komínem 5',
                'invoice_city' => 'Trutnov',
                'invoice_zip' => '54101',
                'invoice_country' => 'CZ',
                'order_no' => '201300025',
                'total_price' => \Decimal::fromString('1692.8000', 4),
                'currency' => 'CZK',
                'id' => 1,
                'weight' => 0.5,
                'carrier_code' => 'cp',
                'packages' => null,
                'note' => null,
                'size' => null,
                'id_delivery' => 3,
                'invoice_email' => 'klima@wpj.cz',
                'invoice_phone' => '+420774123456',
                'type' => Balikobot::TYPE_ORDER,
                'invoice_custom_address' => null,
            ],
        ];

        $this->assertEquals($var, $data);
    }

    public function testBalikobotDeleteDeliverBatch()
    {
        $service = new TestBalikobot();
        $service->setCurlResponses([
            '{"0":{"carrier_id":"DR1504178369M","package_id":53998,"label_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzOxMAZcMBAEAno.","status":"200"},"labels_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzOxMAFcMBAFAns.","status":"200"}',
            '{"labels_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzO1MAZcMBAHAns.","status":200}',
            '{"order_id":4468,"file_url":"https:\/\/csv.balikobot.cz\/cp\/eNorMTI2NdI1MTE3BlwwDXkCQA..","handover_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzM3NAZcMA__AnY.","labels_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzM3NAJcMA_-AnU.","status":200}',
            '{"service_type":"DR","vs":"201300025","cod_price":"693.00","rec_firm":"","rec_zip":"54101","rec_phone":"420774123456","rec_name":"Luk\u00e1\u0161 Kl\u00edma WPJ s.r.o.","rec_street":"Za kom\u00ednem 5","rec_city":"Trutnov","rec_country":"CZ","rec_email":"klima@wpj.cz","rec_contact":"","del_insurance":"0","del_evening":"0","length":null,"width":null,"height":null,"weight":"0.500","services":"1A+L+7+41","price":"1692.80","eshop_id":"201300025_1557985368","carrier_id":"DR1504179109M","package_id":"54084","label_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzM3MAJcMA_8AnQ."}',
        ]);

        $service->setIDs([1 => ['weights' => 0.5]]);
        $service->sendDeliveries();
        $service->printTickets(null, 1, 'default', [1], true);
        $service->deleteDeliverBatch(3);

        $this->assertEquals('OK', $service->orders[0]['error']);

        $order = sqlQuery('SELECT * FROM balikonos WHERE id_order = 1')->fetch();

        $this->assertEquals(2, $order['close']);
        $this->assertNotEmpty($order['data']);

        if (isset($service->orders[0]['balikobot_array']['eid'])) {
            $timestampArr = explode('_', $service->orders[0]['balikobot_array']['eid']);
        }

        $expectedInputs = [
            0 => [
                'data' => [
                    'eid' => '201300025_'.($timestampArr[1] ?? time()),
                    'real_order_id' => '201300025',
                    'vs' => '201300025',
                    'service_type' => 'DR',
                    'price' => '1692.80',
                    'cod_currency' => 'CZK',
                    'rec_phone' => '+420774123456',
                    'rec_name' => 'Lukáš Klíma',
                    'rec_firm' => 'WPJ s.r.o.',
                    'rec_street' => 'Za komínem 5',
                    'rec_city' => 'Trutnov',
                    'rec_email' => 'klima@wpj.cz',
                    'rec_zip' => '54101',
                    'rec_country' => 'CZ',
                    'del_evening' => false,
                    'weight' => 0.5,
                    'size' => null,
                    'note' => null,
                    'return_full_errors' => true,
                    'cod_price' => '693',
                    'services' => '1A',
                    'ins_currency' => 'CZK',
                    'return_track' => true,
                    'reference' => '201300025',
                    'content_invoice_number' => '201300025',
                    'content_issue_date' => '2013-09-13',
                ],
                'api' => 'cp/add',
            ],
            1 => [
                'data' => [
                    'package_ids' => [
                        53998,
                    ],
                ],
                'api' => 'cp/labels',
            ],
            2 => [
                'data' => [
                    'package_ids' => [
                        53998,
                    ],
                ],
                'api' => 'cp/order',
            ],
            3 => [
                'data' => null,
                'api' => 'cp/package/53998',
            ],
        ];

        // assert curl inputs
        foreach ($service->getCurlInputs() as $key => $input) {
            [$data, $api] = $input;

            $data = json_decode($data, true);

            $this->assertEquals($expectedInputs[$key]['data'], $data[0] ?? $data);
            $this->assertEquals($expectedInputs[$key]['api'], $api);
        }
    }

    public function testBalikobot()
    {
        $service = new TestBalikobot();
        $service->setCurlResponses([
            '{"0":{"carrier_id":"DR1504179191M","package_id":54095,"label_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzM3tlwwXDAQCAJ9","status":"200"},"labels_url":"https:\/\/pdf.balikobot.cz\/cp\/eNorMTI2NdI1NzM3tgRcMBAJAn4.","status":"200"}',
        ]);

        $service->setIDs([1 => ['weights' => 0.5]]);
        $service->sendDeliveries();

        $this->assertEquals('OK', $service->orders[0]['error']);

        if (isset($service->orders[0]['balikobot_array']['eid'])) {
            $timestampArr = explode('_', $service->orders[0]['balikobot_array']['eid']);
        }

        $expectedInputs = [
            0 => [
                'data' => [
                    'eid' => '201300025_'.($timestampArr[1] ?? time()),
                    'real_order_id' => '201300025',
                    'vs' => '201300025',
                    'service_type' => 'DR',
                    'price' => '1692.80',
                    'cod_currency' => 'CZK',
                    'rec_phone' => '+420774123456',
                    'rec_name' => 'Lukáš Klíma',
                    'rec_firm' => 'WPJ s.r.o.',
                    'rec_street' => 'Za komínem 5',
                    'rec_city' => 'Trutnov',
                    'rec_email' => 'klima@wpj.cz',
                    'rec_zip' => '54101',
                    'rec_country' => 'CZ',
                    'del_evening' => false,
                    'weight' => 0.5,
                    'size' => null,
                    'note' => null,
                    'return_full_errors' => true,
                    'cod_price' => '693',
                    'services' => '1A',
                    'ins_currency' => 'CZK',
                    'return_track' => true,
                    'reference' => '201300025',
                    'content_invoice_number' => '201300025',
                    'content_issue_date' => '2013-09-13',
                ],
                'api' => 'cp/add',
            ],
        ];

        // assert curl inputs
        foreach ($service->getCurlInputs() as $key => $input) {
            [$data, $api] = $input;

            $this->assertEquals($expectedInputs[$key]['data'], json_decode($data, true)[0]);
            $this->assertEquals($expectedInputs[$key]['api'], $api);
        }
    }

    public function testBalikobotEUR()
    {
        /** @var Balikobot $service */
        $service = ServiceContainer::getService(Balikobot::class);

        $service->setIDs([2 => ['weights' => 0.5]]);
        $data = $service->getOrdersData();

        if (isset($data[0]['balikobot_array']['eid'])) {
            $timestampArr = explode('_', $data[0]['balikobot_array']['eid']);
        }

        $var = [
            0 => [
                'balikobot_array' => [
                    'eid' => '201300030_'.($timestampArr[1] ?? time()),
                    'real_order_id' => '201300030',
                    'vs' => '201300030',
                    'service_type' => 'DR',
                    'price' => '150.00',
                    'cod_currency' => 'EUR',
                    'rec_phone' => '+420774123456',
                    'rec_name' => 'Lukáš Klíma',
                    'rec_firm' => 'WPJ s.r.o.',
                    'rec_street' => 'Za komínem 5',
                    'rec_city' => 'Trutnov',
                    'rec_email' => 'klima@wpj.cz',
                    'rec_zip' => '54101',
                    'rec_country' => 'CZ',
                    'del_evening' => false,
                    'cod_price' => '50.00',
                    'services' => '1A',
                    'weight' => 0.5,
                    'note' => null,
                    'return_full_errors' => true,
                    'size' => null,
                    'ins_currency' => 'EUR',
                    'return_track' => true,
                    'reference' => '201300030',
                    'content_invoice_number' => '201300030',
                    'content_issue_date' => '2013-09-13',
                ],
                'weights' => 0.5,
                'invoice_name' => 'Lukáš',
                'invoice_surname' => 'Klíma',
                'invoice_firm' => 'WPJ s.r.o.',
                'invoice_street' => 'Za komínem 5',
                'invoice_city' => 'Trutnov',
                'invoice_zip' => '54101',
                'invoice_country' => 'CZ',
                'order_no' => '201300030',
                'total_price' => \Decimal::fromString('150.0000', 4),
                'currency' => 'EUR',
                'id' => 2,
                'weight' => 0.5,
                'carrier_code' => 'cp',
                'packages' => null,
                'note' => null,
                'size' => null,
                'id_delivery' => 3,
                'invoice_email' => 'klima@wpj.cz',
                'invoice_phone' => '+420774123456',
                'type' => Balikobot::TYPE_ORDER,
                'invoice_custom_address' => null,
            ],
        ];

        $this->assertEquals($var, $data);
    }

    /**
     * @dataProvider data_CODPriceRound
     */
    public function testCODPriceRound($orderID, $expectedCODPrice)
    {
        /** @var Balikobot $service */
        $service = ServiceContainer::getService(Balikobot::class);

        $service->setIDs([$orderID => []]);
        $data = $service->getOrdersData();

        $this->assertEquals($expectedCODPrice, $data[0]['balikobot_array']['cod_price']);
    }

    public function data_CODPriceRound()
    {
        return [
            [3, 40.30],
            [1, 693],
        ];
    }

    public function getDataSet()
    {
        return $this->getJsonDataSetFromFile();
    }
}

class TestBalikobot extends Balikobot
{
    private $curlResponses = [];
    private $curlInputs = [];

    private $curlResultIndex = 0;

    public function __construct()
    {
        parent::__construct(
            ServiceContainer::getService(CurrencyContext::class)
        );
    }

    public function createCurl($encodedBody, string $apiResourceType, $v2 = false)
    {
        $this->curlInputs[] = [$encodedBody, $apiResourceType];

        return parent::createCurl($encodedBody, $apiResourceType);
    }

    public function curlExecute($curl)
    {
        // return parent::curlExecute($curl);
        return $this->curlResponses[$this->curlResultIndex++];
    }

    public function getCurlInputs(): array
    {
        return $this->curlInputs;
    }

    public function setCurlResponses(array $curlResponses): void
    {
        $this->curlResponses = $curlResponses;
    }
}
