<?php

namespace KupShop\GraphQLBundle\Tests\ApiPos;

use KupShop\GraphQLBundle\Tests\GraphQLTestCase;
use KupShop\KupShopBundle\Context\PosContext;
use KupShop\KupShopBundle\Util\Contexts;

class GraphQLPosTest extends GraphQLTestCase
{
    public function getDataSet()
    {
        return $this->getJsonDataSetFromFile();
    }

    public function testPos()
    {
        // load all pos
        $data = $this->pointsOfSale();
        $this->assertEquals($data['response'], $this->posRequest($data['request'], 0));

        // load additional data
        $data = $this->posAdditionalData(1);
        $this->assertEquals($data['response'], $this->posRequest($data['request'], 1));

        // load fast access products
        $data = $this->posFastAccessProducts();
        $this->assertEquals($data['response'], $this->posRequest($data['request'], 1));
    }

    public function testDeposit()
    {
        // make insertion
        $data = $this->posMakeInsertion();
        $this->assertEquals($data['response'], $this->posRequest($data['request'], 1));

        // make selection
        $data = $this->posMakeSelection();
        $this->assertEquals($data['response'], $this->posRequest($data['request'], 1));

        // load pos stats
        $data = $this->posStats();
        $this->assertEquals($data['response'], $this->posRequest($data['request'], 1));
    }

    public function testOrder()
    {
        // Nejedná se o test se skladem a warehousem
        $this->removeModule(\Modules::WAREHOUSE, null);
        $this->removeModule(\Modules::STORES, null);

        // Kontrola, že ještě není nasetovaný context
        $posContext = Contexts::get(PosContext::class);
        $this->assertEquals(null, $posContext->getActiveId());

        // Přepočítání košíku poklodny
        $data = $this->posUpdateAndRecalculate();
        $this->assertEquals($data['response'], $this->posRequest($data['request'], 1));

        // Kontrola pos contextu
        $this->assertEquals(1, $posContext->getActiveId());
        $entity = $posContext->getActive();
        $this->assertEquals(1, $entity->getId());
        $this->assertEquals('Pokladna 1', $entity->getName());
        $this->assertEquals(1, $entity->getCashDeliveryType());
        $this->assertEquals(3, $entity->getCustomDeliveryType());

        // Vytvoření objednávky skrze API (uložení, tedy bez platby)
        $data = $this->posUpdateAndRecalculate('null', 'UNDEFINED', '0', 'true', 'true');
        $orderResponse = $this->posRequest($data['request'], 1);
        $idOrder = intval($orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['idOrder']);
        $this->assertEquals(-1, $orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['status']);
        $this->assertFalse($orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['isPaid']);
        $this->assertEquals('1800', $orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['remainingPayment']);
        $dbOrder = sqlQueryBuilder()
            ->select('*')
            ->from('orders')
            ->andWhere('orders.id = :id')
            ->setParameter('id', $idOrder)
            ->execute()
            ->fetchAssociative();
        $this->assertEquals('Hotově - Osobní odběr', $dbOrder['delivery_type']);
        $this->assertEquals(1, $dbOrder['id_delivery']);

        // Načtení objednávky do pokladny
        $data = $this->getCreatedOrder($idOrder);
        $loadedOrder = $this->posRequest($data['request'], 1);
        $this->assertEquals('vancl@wpj.cz', $loadedOrder['data']['order']['orderUser']['email']);
        $this->assertEquals('07414', $loadedOrder['data']['order']['items'][0]['code']);
        $this->assertEquals('544402044', $loadedOrder['data']['order']['items'][1]['code']);

        // Uložení objednávky s platbou (vytvoření neaktivní platby)
        $data = $this->posUpdateAndRecalculate($idOrder, 'CASH', '1800', 'true', 'true');
        $orderResponse = $this->posRequest($data['request'], 1);
        $uuidPayment = $orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['uuidPayment'];
        $this->assertTrue($orderResponse['data']['posOrderUpdateAndRecalculate']['saved']);
        $this->assertCount(2, $orderResponse['data']['posOrderUpdateAndRecalculate']['items']);
        $this->assertEquals('1800.0000', $orderResponse['data']['posOrderUpdateAndRecalculate']['priceWithVat']);
        $this->assertEquals('1800', $orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['remainingPayment']);

        // Potvrzení platby
        $data = $this->confirmPaymentMutation($idOrder, $uuidPayment, 'CASH', '1800');
        $paidOrder = $this->posRequest($data['request'], 1);
        $this->assertEquals($idOrder, $paidOrder['data']['confirmPayment']['orderInfo']['idOrder']);
        $this->assertTrue($paidOrder['data']['confirmPayment']['saved']);
        $this->assertTrue($paidOrder['data']['confirmPayment']['orderInfo']['isPaid']);
        $this->assertEquals('0', $paidOrder['data']['confirmPayment']['orderInfo']['remainingPayment']);

        // Kontroluji, že se nezminl způsob doručení od vytvoření
        $dbOrder = sqlQueryBuilder()
            ->select('*')
            ->from('orders')
            ->andWhere('orders.id = :id')
            ->setParameter('id', $idOrder)
            ->execute()
            ->fetchAssociative();
        $this->assertEquals('Hotově - Osobní odběr', $dbOrder['delivery_type']);
        $this->assertEquals(1, $dbOrder['id_delivery']);

        // Změna statusu objednávky
        $data = $this->posFinishOrder($idOrder);
        $response = $this->posRequest($data['request'], 1);
        $this->assertEquals($idOrder, $response['data']['posOrderFinish']['idOrder']);
        $this->assertEquals('2', $response['data']['posOrderFinish']['status']);
        $this->assertEmpty($response['data']['posOrderFinish']['exception']);

        // Načtení dokončené objednávky
        $data = $this->getPaidOrder($idOrder);
        $loadedOrder = $this->posRequest($data['request'], 1);
        $this->assertEquals('vancl@wpj.cz', $loadedOrder['data']['order']['orderUser']['email']);
        $this->assertTrue($loadedOrder['data']['order']['isPaid']);
    }

    public function testDeliverySwitchOnCustomPayment(): void
    {
        // Nejedná se o test se skladem a warehousem
        $this->removeModule(\Modules::WAREHOUSE, null);
        $this->removeModule(\Modules::STORES, null);

        // create order - kontrola vytvoření objednávky a nastavení první dopravy
        $data = $this->posUpdateAndRecalculate('null', 'CUSTOM', '1800', 'true', 'true');
        $orderResponse = $this->posRequest($data['request'], 1);
        $idOrder = intval($orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['idOrder']);
        $uuidPayment = $orderResponse['data']['posOrderUpdateAndRecalculate']['orderInfo']['uuidPayment'];
        $this->assertNull($uuidPayment); // Nesmí vytvořit platbu

        $dbOrder = sqlQueryBuilder()
            ->select('*')
            ->from('orders')
            ->andWhere('orders.id = :id')
            ->setParameter('id', $idOrder)
            ->execute()
            ->fetchAssociative();

        $this->assertTrue($orderResponse['data']['posOrderUpdateAndRecalculate']['saved']);
        $this->assertEquals('1800.0000', $orderResponse['data']['posOrderUpdateAndRecalculate']['priceWithVat']);
        $this->assertEquals('Pokladna - Custom - Osobní odběr', $dbOrder['delivery_type']);
        $this->assertEquals(3, $dbOrder['id_delivery']);

        // pay order - kontrola změny dopravy na zaplacení (nesmí být zaplacená, musí se změnit doprava na tu co je nastavená na entitě pokladny)
        $data = $this->confirmPaymentMutation($idOrder, 'UNDEFINED', 'CUSTOM');
        $paidOrder = $this->posRequest($data['request'], 1);
        $dbOrder = sqlQueryBuilder()
            ->select('*')
            ->from('orders')
            ->andWhere('orders.id = :id')
            ->setParameter('id', $idOrder)
            ->execute()
            ->fetchAssociative();
        $this->assertTrue($paidOrder['data']['confirmPayment']['saved']);
        $this->assertFalse($paidOrder['data']['confirmPayment']['orderInfo']['isPaid']);
        $this->assertEquals('1800', $paidOrder['data']['confirmPayment']['orderInfo']['remainingPayment']);
        $this->assertEquals('Pokladna - Custom - Osobní odběr', $dbOrder['delivery_type']);
        $this->assertEquals(3, $dbOrder['id_delivery']);
    }

    private function adminRequest($request)
    {
        return json_decode($this->doAdminRequest($request, [], true)->getContent(), true);
    }

    private function posRequest($request, $idPos)
    {
        $posContext = Contexts::get(PosContext::class);

        return json_decode(
            $this->doAdminRequest(
                $request,
                [],
                true,
                '/admin/pos/graphql/',
                [
                    'HTTP_Wpj-Id-Pos-Entity' => $idPos,
                    'HTTP_Wpj-Version-Pos' => $posContext->getApiVersion(),
                ]
            )->getContent(),
            true
        );
    }

    private function pointsOfSale()
    {
        return [
            'request' => '
                {
                  pointsOfSale{
                    items{
                      name,
                      id
                    }
                  }
                }',
            'response' => [
                'data' => [
                    'pointsOfSale' => [
                        'items' => [
                            [
                                'id' => 1,
                                'name' => 'Pokladna 1',
                            ],
                            [
                                'id' => 2,
                                'name' => 'Pokladna 2',
                            ],
                            [
                                'id' => 3,
                                'name' => 'EURO pokladna',
                            ],
                        ],
                    ],
                ],
            ],
        ];
    }

    private function posMakeInsertion()
    {
        return [
            'request' => 'mutation {
                posMakeInsertion(price: "1000", note: "Test")
             }',
            'response' => [
                'data' => [
                    'posMakeInsertion' => 200,
                ],
            ],
        ];
    }

    private function posMakeSelection()
    {
        return [
            'request' => 'mutation {
                posMakeSelection(price: "800", note: "Test")
             }',
            'response' => [
                'data' => [
                    'posMakeSelection' => 200,
                ],
            ],
        ];
    }

    private function posStats()
    {
        return [
            'request' => '
                {
                   posStats {
                    card{
                      stats {
                        price,
                        vat
                      }
                    },
                    cash{
                      stats {
                        price,
                        vat
                      }
                    },
                    invoice{
                      stats {
                        price,
                        vat
                      }
                    },
                    summary{
                      insertion,
                      selection,
                      compensation,
                      rounding
                      discounts,
                      sales,
                      actuallyInPos
                    }
                  }
                }',
            'response' => [
                'data' => [
                    'posStats' => [
                        'card' => [
                            'stats' => [
                                0 => [
                                    'price' => '0',
                                    'vat' => '21',
                                ],
                                1 => [
                                    'price' => '0',
                                    'vat' => '15',
                                ],
                                2 => [
                                    'price' => '0',
                                    'vat' => '10',
                                ],
                                3 => [
                                    'price' => '0',
                                    'vat' => '0',
                                ],
                            ],
                        ],
                        'cash' => [
                            'stats' => [
                                0 => [
                                    'price' => '0',
                                    'vat' => '21',
                                ],
                                1 => [
                                    'price' => '0',
                                    'vat' => '15',
                                ],
                                2 => [
                                    'price' => '0',
                                    'vat' => '10',
                                ],
                                3 => [
                                    'price' => '0',
                                    'vat' => '0',
                                ],
                            ],
                        ],
                        'invoice' => [
                            'stats' => [
                                0 => [
                                    'price' => '0',
                                    'vat' => '21',
                                ],
                                1 => [
                                    'price' => '0',
                                    'vat' => '15',
                                ],
                                2 => [
                                    'price' => '0',
                                    'vat' => '10',
                                ],
                                3 => [
                                    'price' => '0',
                                    'vat' => '0',
                                ],
                            ],
                        ],
                        'summary' => [
                            'insertion' => '1000.0000',
                            'selection' => '-800.0000',
                            'compensation' => '0.0000',
                            'rounding' => '0',
                            'discounts' => '0',
                            'sales' => '0',
                            'actuallyInPos' => '200.0000',
                        ],
                    ],
                ],
            ],
        ];
    }

    private function getCreatedOrder($id)
    {
        return [
            'request' => PosQueryUtils::loadOrder($id),
            'response' => [
                'data' => [
                    'order' => [
                        'id' => 274495,
                        'code' => '0362201',
                        'email' => '',
                        'userId' => null,
                        'isPaid' => false,
                        'invoiceAddress' => [
                            'name' => '',
                            'surname' => '',
                            'firm' => '',
                        ],
                        'totalPrice' => [
                            'withVat' => 1800,
                            'withoutVat' => 1487.6,
                        ],
                        'paidPrice' => 0,
                        'items' => [
                            0 => [
                                'id' => 3474971,
                                'code' => '07414',
                                'productId' => 7749,
                                'variationId' => null,
                                'pieces' => 1,
                                'piecePrice' => [
                                    'withVat' => 90,
                                    'withoutVat' => 74.38016529,
                                ],
                                'vat' => 21,
                                'name' => 'Adaptér autobaterie 12/24V',
                                'product' => [
                                    'photos' => [],
                                ],
                            ],
                            1 => [
                                'id' => 3474972,
                                'code' => '544402044',
                                'productId' => 50405,
                                'variationId' => null,
                                'pieces' => 1,
                                'piecePrice' => [
                                    'withVat' => 1710,
                                    'withoutVat' => 1413.2231405,
                                ],
                                'vat' => 21,
                                'name' => 'Autobaterie Varta BlueDynamic 12V 44Ah',
                                'product' => [
                                    'photos' => [],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
    }

    private function getPaidOrder($id)
    {
        return [
            'request' => PosQueryUtils::loadOrder($id),
            'response' => [
                'data' => [
                    'order' => [
                        'id' => 274495,
                        'code' => '0362201',
                        'email' => '',
                        'userId' => null,
                        'isPaid' => true,
                        'invoiceAddress' => [
                            'name' => '',
                            'surname' => '',
                            'firm' => '',
                        ],
                        'totalPrice' => [
                            'withVat' => 1800,
                            'withoutVat' => 1487.6,
                        ],
                        'paidPrice' => 1800,
                        'items' => [
                            0 => [
                                'id' => 3474971,
                                'code' => '07414',
                                'productId' => 7749,
                                'variationId' => null,
                                'pieces' => 1,
                                'piecePrice' => [
                                    'withVat' => 90,
                                    'withoutVat' => 74.38016529,
                                ],
                                'vat' => 21,
                                'name' => 'Adaptér autobaterie 12/24V',
                                'product' => [
                                    'photos' => [],
                                ],
                            ],
                            1 => [
                                'id' => 3474972,
                                'code' => '544402044',
                                'productId' => 50405,
                                'variationId' => null,
                                'pieces' => 1,
                                'piecePrice' => [
                                    'withVat' => 1710,
                                    'withoutVat' => 1413.2231405,
                                ],
                                'vat' => 21,
                                'name' => 'Autobaterie Varta BlueDynamic 12V 44Ah',
                                'product' => [
                                    'photos' => [],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
    }

    private function confirmPaymentMutation($id, $uuidPayment, $method = 'CARD', $price = '1800'): array
    {
        return [
            'request' => PosQueryUtils::confirmPayment($id, $uuidPayment, $method, $price),
            'response' => [
                'data' => [
                    'confirmPayment' => [
                        'statusCode' => 200,
                        'statusMessage' => 'Ok',
                        'idOrder' => '274495',
                        'isPaid' => true,
                        'remainingPayment' => '0',
                        'noOrder' => '0362201',
                    ],
                ],
            ],
        ];
    }

    private function posFinishOrder($id): array
    {
        return [
            'request' => PosQueryUtils::finishOrder($id),
            'response' => [
                'data' => [
                    'posOrderFinish' => [
                        'statusCode' => 200,
                        'statusMessage' => 'OK',
                    ],
                ],
            ],
        ];
    }

    private function posFastAccessProducts()
    {
        return [
            'request' => '{
             posFastAccessProducts {
               items{
                 id,
                 variationId,
                 code,
                 title,
                 photo{
                   source
                 },
                 price{
                   withoutVat,
                   vat
                 }
               }
             }
           }',
            'response' => [
                'data' => [
                    'posFastAccessProducts' => [
                        'items' => [
                            0 => [
                                'id' => 44052,
                                'variationId' => null,
                                'code' => 'UL885',
                                'title' => 'Bunda Silvini Anteo MJ1743 - Black/Red',
                                'photo' => null,
                                'price' => [
                                    'withoutVat' => 2471.0744,
                                    'vat' => 21,
                                ],
                            ],
                            1 => [
                                'id' => 43865,
                                'variationId' => null,
                                'code' => 'WJ1717',
                                'title' => 'Bunda Silvini Asprino WJ1717 - Black/Charcoal',
                                'photo' => null,
                                'price' => [
                                    'withoutVat' => 3297.5207,
                                    'vat' => 21,
                                ],
                            ],
                            2 => [
                                'id' => 43866,
                                'variationId' => null,
                                'code' => null,
                                'title' => 'Bunda Silvini Asprino WJ1717 - Lime/Punch',
                                'photo' => null,
                                'price' => [
                                    'withoutVat' => 3297.5207,
                                    'vat' => 21,
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
    }

    private function posAdditionalData($idPos): array
    {
        return [
            'request' => PosQueryUtils::posAdditionalData($idPos),
            'response' => [
                'data' => [
                    'posAdditionalData' => [
                        'vats' => [
                            'items' => [
                                0 => [
                                    'description' => 'Běžná 21% daň',
                                    'vat' => '21',
                                    'default' => 'Y',
                                ],
                                1 => [
                                    'description' => 'Snížená 15% daň',
                                    'vat' => '15',
                                    'default' => 'N',
                                ],
                                2 => [
                                    'description' => '10%',
                                    'vat' => '10',
                                    'default' => 'N',
                                ],
                                3 => [
                                    'description' => '15%',
                                    'vat' => '15',
                                    'default' => 'N',
                                ],
                                4 => [
                                    'description' => '0%',
                                    'vat' => '0',
                                    'default' => 'N',
                                ],
                                5 => [
                                    'description' => '21%',
                                    'vat' => '21',
                                    'default' => 'Y',
                                ],
                                6 => [
                                    'description' => '20%',
                                    'vat' => '20',
                                    'default' => 'Y',
                                ],
                                7 => [
                                    'description' => '10%',
                                    'vat' => '10',
                                    'default' => 'N',
                                ],
                                8 => [
                                    'description' => '0%',
                                    'vat' => '0',
                                    'default' => 'N',
                                ],
                            ],
                        ],
                        'shopCurrencySymbol' => 'Kč',
                        'shopCurrency' => 'CZK',
                    ],
                ],
            ],
        ];
    }

    private function posUpdateAndRecalculate($idOrder = 'null', string $paymentMethod = 'UNDEFINED', string $paidPrice = '0', string $savePurchase = 'false', string $purchase = 'false'): array
    {
        $items = '[{uuid: "aaa", idProduct:7749,title:"Adaptér autobaterie 12/24V",pieces:1,vat:"21",priceWithoutVat:"74.3802"},{uuid: "bbb",idProduct:50405,title:"Autobaterie Varta BlueDynamic 12V 44Ah",pieces:1,vat:"21",priceWithoutVat:"1413.2231"}]';
        $user = '{id: 2634, email: "vancl@wpj.cz", name: "David Vancl"}';

        return [
            'request' => PosQueryUtils::posUpdateAndRecalculate($idOrder, $items, $user, $paymentMethod, $paidPrice, $savePurchase, $purchase),
            'response' => [
                'data' => [
                    'posOrderUpdateAndRecalculate' => [
                        'items' => [
                            0 => [
                                'idProduct' => '7749',
                                'idVariation' => null,
                                'piecePrice' => '74.3802',
                                'title' => 'Adaptér autobaterie 12/24V',
                                'pieces' => '1',
                                'vat' => '21.0000',
                                'uuid' => 'aaa',
                                'id' => '0',
                                'variationTitle' => null,
                                'ean' => '8591686074147',
                                'stockIn' => '6',
                                'serialNumberRequire' => false,
                                'stores' => null,
                                'warehouse' => null,
                                'serialNumbers' => [
                                    'items' => [],
                                ],
                            ],
                            1 => [
                                'idProduct' => '50405',
                                'idVariation' => null,
                                'piecePrice' => '1413.2231',
                                'title' => 'Autobaterie Varta BlueDynamic 12V 44Ah',
                                'pieces' => '1',
                                'vat' => '21.0000',
                                'uuid' => 'bbb',
                                'id' => '1',
                                'variationTitle' => null,
                                'ean' => '4016987119495',
                                'stockIn' => '12',
                                'serialNumberRequire' => false,
                                'stores' => null,
                                'warehouse' => null,
                                'serialNumbers' => [
                                    'items' => [],
                                ],
                            ],
                        ],
                        'loadedCoupons' => [],
                        'loadedProducts' => [],
                        'priceWithVat' => '1800.0000',
                        'priceWithoutVat' => '1487.6033',
                        'saved' => false,
                        'orderInfo' => null,
                        'discounts' => [],
                        'charges' => [],
                        'exception' => null,
                    ],
                ],
            ],
        ];
    }
}
