<?php

declare(strict_types=1);

namespace External\HannahBundle\Maileon\Export;

use KupShop\OrderingBundle\Entity\Order\OrderItem;
use KupShop\OrderingBundle\OrderList\OrderList;
use Query\Operator;
use Query\QueryBuilder;

class OrderExport extends AbstractExport
{
    protected static $type = 'order';
    protected static $uploadDirectory = '/';
    protected static $uploadFilename = 'orders.csv';

    /** @var OrderList */
    private $orderList;

    /**
     * @required
     */
    public function setOrderList(OrderList $orderList): void
    {
        $this->orderList = $orderList;
    }

    protected function getHeader(): array
    {
        return [
            'email',
            'cislo_objednavky',
            'mena',
            'jazyk',
            'datum',
            'nazev_polozky',
            'znacka',
            'idpolozky',
            'heurekaid',
            'pocet_ks',
            'kategorie1',
            'kategorie2',
            'cena_polozky',
            'cena_celkem',
            'cena_dopravy',
            'doprava',
            'platba',
            'id_prodejny',
        ];
    }

    protected function getData(string $language, ?\DateTime $lastSync): iterable
    {
        $orderList = clone $this->orderList;

        $orders = $orderList
            ->andSpec(function (QueryBuilder $qb) use ($language) {
                return Operator::andX(
                    // filtruju podle jazyka, protoze delam export objednavek pro kazdy jazyk zvlast
                    Operator::equals(['o.id_language' => $language]),
                    // beru objednavky za poslednich 48 hodin
                    'o.date_created > (NOW() - INTERVAL 48 HOUR)'
                );
            })
            ->limit(1000)
            ->orderBy('o.id', 'DESC')
            ->fetchItems()
            ->getOrders();

        /** @var \Order $order */
        foreach ($orders as $order) {
            $deliveryPrice = $order->getDeliveryPrice();

            $deliveryId = '';
            $paymentId = '';
            $sellerId = '';

            $orderData = $order->getDataAll();
            if ($tmpSellerId = ($orderData['delivery_data']['seller_id'] ?? false)) {
                $sellerId = (int) $tmpSellerId;
            }

            if ($deliveryType = $order->getDeliveryType()) {
                $deliveryId = (int) $deliveryType->id_delivery;
                $paymentId = (int) $deliveryType->id_payment;
            }

            /** @var OrderItem $item */
            foreach ($order->fetchItems() as $item) {
                $sections = [];
                if ($item->getProduct()) {
                    $sections = $this->getProductSections($item->getProduct());
                }

                yield [
                    'email' => $order->invoice_email,
                    'cislo_objednavky' => $order->order_no,
                    'mena' => $order->getCurrency(),
                    'jazyk' => $order->getLanguage(),
                    'datum' => $order->date_created->format('Y-m-d H:i:s'),
                    'nazev_polozky' => $item->getDescr(),
                    'znacka' => $item->getProducer(),
                    'idpolozky' => $item->getId(),
                    'heurekaid' => $item->getCode(),
                    'pocet_ks' => $item->getPieces(),
                    'kategorie1' => $sections[0] ?? '',
                    'kategorie2' => $sections[1] ?? '',
                    'cena_polozky' => $item->getPiecePrice()->getPriceWithVat()->asFloat(),
                    'cena_celkem' => $item->getTotalPrice()->getPriceWithVat()->asFloat(),
                    'cena_dopravy' => $deliveryPrice['value_with_vat']->asFloat(),
                    'doprava' => $deliveryId,
                    'platba' => $paymentId,
                    'id_prodejny' => $sellerId,
                ];
            }
        }

        return [];
    }

    private function getProductSections(\Product $product): array
    {
        $sections = $product->fetchSections();

        // manualni sekce
        $manualSections = array_filter($sections, fn ($x) => !$x->isVirtual());
        // virtualni sekce
        $virtualSections = array_filter($sections, fn ($x) => $x->isVirtual());

        // seradim si sekce podle priorit
        uasort($manualSections, fn ($a, $b) => $a['priority'] <=> $b['priority']);
        uasort($virtualSections, fn ($a, $b) => $a['priority'] <=> $b['priority']);

        // prioritizuju manualni sekce
        $result = array_values($manualSections);

        // pokud je ale nedostatek manualnich sekce a mam virtualni sekci, tak vysledek doplnim o virtualni sekci
        if (count($result) < 2 && !empty($virtualSections)) {
            $result[] = reset($virtualSections);
        }

        return array_map(fn ($x) => $x->getName(), $result);
    }
}
