<?php

namespace KupShop\OrderDiscountBundle\EventListener;

use KupShop\KupShopBundle\Config;
use KupShop\OrderDiscountBundle\Util\DiscountManager;
use KupShop\OrderingBundle\Event\OrderEvent;
use KupShop\OrderingBundle\Util\ISIC\AliveCard;
use Query\Operator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class OrderListener implements EventSubscriberInterface
{
    /** @required */
    public AliveCard $aliveCard;

    /** @required */
    public DiscountManager $discountManager;

    public static function getSubscribedEvents(): array
    {
        return [
            OrderEvent::ORDER_FINISHED => [
                ['checkUsedCoupons', 300],
                ['sendIsicTransaction', 200],
            ],
        ];
    }

    public function checkUsedCoupons(OrderEvent $event): void
    {
        $order = $event->getOrder();

        $discounts = $order->getData('discounts') ?: [];
        $used_coupons = $discounts['used_coupons'] ?? [];

        // ensure that the generated codes actually used in this order are present in used_coupons
        $discounts_coupons = sqlQueryBuilder()->select('code')
            ->from('discounts_coupons')
            ->where(Operator::equals(['id_order_used' => $order->id]))
            ->execute()->fetchFirstColumn();
        $used_coupons = array_merge($used_coupons, $discounts_coupons);

        if (empty($used_coupons)) {
            return;
        }

        $used_coupons = array_unique($used_coupons);

        // check that the generated codes in used_coupons were actually used in this order
        $discounts_coupons = sqlQueryBuilder()->select('*')
            ->from('discounts_coupons')
            ->where(Operator::inStringArray($used_coupons, 'code'))
            ->execute()->fetchAllAssociative();
        foreach ($discounts_coupons as $coupon) {
            if ($coupon['id_order_used'] != $order->id) {
                $used_coupons = array_diff($used_coupons, [$coupon['code']]);
            }
        }

        // check that common coupons (not generated codes) in used_coupons were actually used in this order
        if ($common_coupons = array_diff($used_coupons, array_column($discounts_coupons, 'code'))) {
            $usedDiscounts = $order->getPurchaseState()->getUsedDiscounts();
            foreach ($common_coupons as $coupon) {
                $order_discounts = [];
                $this->discountManager->couponNumberExists($coupon, $order_discounts);
                $used = array_intersect($usedDiscounts, array_column($order_discounts, 'id'));
                if (!$used) {
                    $used_coupons = array_diff($used_coupons, [$coupon]);
                }
            }
        }

        $discounts['used_coupons'] = $used_coupons;

        $order->setData('discounts', $discounts);
    }

    public function sendIsicTransaction(OrderEvent $event): void
    {
        if (!empty(Config::get()['Modules']['isic'])) {
            $order = $event->getOrder();

            if ($discounts = $order->getData('discounts')) {
                if (($discounts['isic']['success'] ?? false) && ($discounts['isic']['verificationId'] ?? false)) {
                    if ($result = $this->aliveCard->sendTransaction($discounts['isic']['verificationId'],
                        $order->getTotalPrice()->getPriceWithVat())) {
                        $order->setData('isic_verification', $result);
                    }
                }
            }
        }
    }
}
