<?php

namespace KupShop\GTMBundle\ServerSideGTMEvent;

use KupShop\GTMBundle\Utils\DataLoaders\PurchaseState;
use KupShop\GTMBundle\Utils\PriceComputer;
use KupShop\OrderingBundle\Event\OrderEvent;
use KupShop\OrderingBundle\Util\Order\DeliveryInfo;
use KupShop\OrderingBundle\Util\Order\OrderInfo;
use Symfony\Contracts\EventDispatcher\Event;
use Symfony\Contracts\Service\Attribute\Required;

class OrderComplete extends AbstractServerSideGTMEvent
{
    private PriceComputer $priceComputer;
    private DeliveryInfo $deliveryInfo;
    private PurchaseState $purchaseState;

    public function getPayload(Event $event): array
    {
        if (!($event instanceof OrderEvent)) {
            return [];
        }

        $dbcfg = \Settings::getDefault();
        $order = $event->getOrder();
        $items = [];
        $index = 1;
        foreach ($order->fetchItems() as $item) {
            if (!isset($item['product'])) {
                continue;
            }

            /** @var \Product|\Variation $product */
            $product = $item['product'];
            $product->fetchProducer();
            $product->fetchVariations();

            $newItem = $this->productLoader->loadProductObject($product);
            $newItem['index'] = $index++;
            $newItem['quantity'] = $item['pieces'];

            $prices = $this->purchaseState->getPrices($item);
            $newItem['price'] = $prices['price'];
            $newItem['price_with_vat'] = $prices['priceWithVat'];
            $newItem['price_without_vat'] = $prices['priceWithoutVat'];
            $newItem['price_vat'] = $prices['priceVat'];
            $newItem['vat_rate'] = $prices['vatRate'];
            $newItem['discount'] = $product->discount->asFloat();
            if (($soldOut = $this->purchaseState->getSoldOut($product)) !== null) {
                $newItem['soldOut'] = $soldOut;
            }
            $items[] = $newItem;
        }

        $deliveryType = $order->getDeliveryType();
        $shippingPrice = $this->getDeliveryPrice($order);
        $shippinPrice = $this->priceComputer->getPrice($shippingPrice ?? toDecimal(0));

        if (($dbcfg->analytics['google_tag_manager']['withoutDelivery'] ?? 'N') == 'Y') {
            // Tohle je kvuli tomu, ze podle nastaveni nevime jestli ma byt bez nebo s dph, proto nechame rozhodnout funkce uvnitr a pak to akorat proste odectu
            $tp = toDecimal($this->priceComputer->getPrice($order->getTotalPrice()));
            $shipp = toDecimal($shippinPrice);
            $totalPrice = $tp->sub($shipp);
        } else {
            $totalPrice = $order->getTotalPrice();
        }

        $commonData = $this->getCommonData($event);
        if ($coupons = OrderInfo::getUsedCoupons($order)) {
            $coupons = join(',', $coupons);
        }
        $params = $commonData + [
            'currency' => $order->currency,
            'transaction_id' => $order->order_no,
            'value' => $this->priceComputer->getPrice($totalPrice),
            'vat' => $this->priceComputer->getPrice($order->total_price_array['value_vat'], null, false),
            'delivery_type' => $deliveryType->getDelivery()->getClassName(),
            'payment_type' => $deliveryType->getPayment()->getClassName(),
            'payment' => $this->purchaseState->getPaymentObject($order),
            'items' => $items,
            'shipping' => $this->priceComputer->getPrice($order->getDeliveryPrice()),
            'discounts' => $this->purchaseState->getDiscounts($order->getPurchaseState(true)),
            'coupon' => $coupons ?: '',
            'charges' => $this->purchaseState->getCharges($order),
            'cjevent' => $order->getData('cjevent'),
        ];

        return [
            'user_id' => $commonData['user_id'],
            'client_id' => $commonData['client_id'],
            'ga3_session_id' => $this->getGA3SessionId(),
            'events' => [
                [
                    'name' => 'purchase',
                    'params' => $params,
                ],
            ],
        ];
    }

    protected function getCommonData(Event $event): array
    {
        /** @var \Order $order */
        $order = $event->getOrder();

        return array_merge(parent::getCommonData($event), [
            'user_id' => $order->getData('cart_id'),
            'client_id' => $order->getData('client_id') ?: $order->getData('cart_id').'_noCookie',
            'currency' => $order->getCurrency(),
            'ip_override' => $order->getData('ip_address'),
            'language' => $order->getLanguage(),
            'page_path' => path('kupshop_content_orders_order', ['id' => $order->id]),
            'page_title' => str_replace('%ORDERNO', $order->order_no, translate_shop('title', 'orderView')),
            'page_referrer' => $order->getData('referer'),
            'user_agent' => $order->getData('user_agent'),
        ]);
    }

    public function getDeliveryPrice(\Order $order)
    {
        $delivery_item = $this->deliveryInfo->getDeliveryItem($order);

        return $delivery_item ? $order->fetchItems()[$delivery_item]['total_price'] : null;
    }

    #[Required]
    public function setPriceComputer(PriceComputer $priceComputer): void
    {
        $this->priceComputer = $priceComputer;
    }

    #[Required]
    public function setDeliveryInfo(DeliveryInfo $deliveryInfo): void
    {
        $this->deliveryInfo = $deliveryInfo;
    }

    #[Required]
    public function setPurchaseState(PurchaseState $purchaseState): void
    {
        $this->purchaseState = $purchaseState;
    }
}
