<?php

namespace KupShop\OrderDiscountBundle\Actions;

use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\OrderDiscountBundle\Actions\Frontend\GiftHandler;
use KupShop\OrderDiscountBundle\Actions\Frontend\HandlerInterface;
use KupShop\OrderDiscountBundle\Entity\OrderDiscount;
use KupShop\OrderDiscountBundle\Util\DiscountUtil;
use KupShop\OrderingBundle\Entity\Purchase\ProductPurchaseItem;
use KupShop\OrderingBundle\Entity\Purchase\PurchaseState;
use KupShop\OrderingBundle\Util\Order\OrderItemInfo;
use Query\Operator;

class GiftAction extends AbstractAction
{
    protected static $type = 'gift';
    protected static $position = 10;
    protected $adminTemplate = 'actions/gift.tpl';

    private $giftHandler;
    private $discountUtil;

    public function __construct(GiftHandler $giftHandler, DiscountUtil $discountUtil)
    {
        $this->giftHandler = $giftHandler;
        $this->discountUtil = $discountUtil;
    }

    public function applyResult(PurchaseState &$purchaseState, OrderDiscount $orderDiscount, array $data)
    {
        $gift = $data['handled']['gift'] ?? $this->getPreselected($data);
        if ($gift) {
            $giftCustomData = $purchaseState->getCustomData('gift') ?: [];
            $giftCustomData[$orderDiscount->getId()][] = $gift;
            $purchaseState->setCustomData(['gift' => $giftCustomData]);
            if ($gift['selected']) {
                $product = new \Product();
                $product->createFromDB($gift['id_product']);
                $price = \DecimalConstants::zero();
                $data['discount'] = floatval($data['price'] ?? 0);
                if (!empty($data['discount'])) {
                    $price = $this->discountUtil->calculateDiscountPrice($price, $data);
                    if (!$price) {
                        $price = \DecimalConstants::zero();
                    }
                }

                $price = new Price($price->removeVat($product->vat), Contexts::get(CurrencyContext::class)->getActive(), $product->vat);

                $note = ['item_type' => OrderItemInfo::TYPE_GIFT];
                $purchaseState->addDiscount(
                    new ProductPurchaseItem($gift['id_product'], $gift['id_variation'] ?? null, $data['gift_pieces'] ?? 1, $price, $note, $orderDiscount->getId())
                );
                if ($message = $data['messages']['success'] ?? '') {
                    $this->messages['success'] = $message;
                }
            }
        } else {
            if ($message = $data['messages']['warning'] ?? '') {
                $this->messages['warning'] = $message;
            }
        }
    }

    public function getPreselected(array $data): ?array
    {
        if ($data['preselect_first'] ?? null) {
            $gifts = $this->getFrontendHandler()->getAvailableGifts($data);

            if ($gifts && ($gift = $gifts->first())) {
                return [
                    'selected' => true,
                    'id_product' => $gift->id,
                ];
            }
        }

        return null;
    }

    public function getFrontendHandler(): ?HandlerInterface
    {
        return $this->giftHandler;
    }

    protected function getVars($vars)
    {
        $vars['gifts'] = [];
        $gifts = ($vars['data']['gifts'] ?? null);
        if ($gifts) {
            $gifts = array_map(function ($v) {
                if (!is_array($v)) {
                    $v = ['id_product' => $v];
                }

                return $v;
            }, $gifts);
            if (!$gifts) {
                return $vars;
            }
            $gifts_products = sqlQueryBuilder()
                ->select('p.id, p.title, p.code, p.in_store, ph.id as id_photo')->fromProducts()
                ->leftJoin('p', 'photos_products_relation', 'ppr', 'ppr.id_product=p.id AND ppr.show_in_lead="Y"')
                ->leftJoin('ppr', 'photos', 'ph', 'ph.id=ppr.id_photo')
                ->where(Operator::inIntArray(array_column($gifts, 'id_product'), 'p.id'))
                ->groupBy('p.id');
            if (findModule(\Modules::PRODUCTS_VARIATIONS)) {
                $code = findModule(\Modules::PRODUCTS_VARIATIONS, \Modules::SUB_CODE) ? "COALESCE(pv.code, '')" : "''";
                $field = "GROUP_CONCAT(CONCAT(pv.id, '~', pv.title, '~', {$code}, '~', pv.in_store) SEPARATOR '|') variations";
                $gifts_products->joinVariationsOnProducts()->addSelect($field);
            }
            $gifts_products = sqlFetchAll($gifts_products, 'id');

            foreach ($gifts as $gift) {
                $id_product = $gift['id_product'];
                if ($gifts_product = $gifts_products[$id_product] ?? null) {
                    $gifts_product['id_product'] = $id_product;
                    $gifts_product['image'] = getImage($gifts_product['id_photo'], null, null, 4);
                    if ($gifts_product['variations']) {
                        $selected = $gift['id_variation'] ?? [];
                        $variations = explode('|', $gifts_product['variations']);
                        foreach ($variations as &$variation) {
                            $variation = explode('~', $variation);
                            $variation = array_combine(['value', 'label', 'code', 'in_store'], $variation);
                            $variation['selected'] = in_array($variation['value'], $selected);
                        }
                        $gifts_product['variations'] = $variations;
                    }
                    $vars['gifts'][] = $gifts_product;
                }
            }
        }

        return $vars;
    }

    public function handleData($data)
    {
        $data = parent::handleData($data);

        $gifts = [];
        foreach ($data['gifts'] ?? [] as $gift) {
            if (($gift['delete'] ?? null) == 'on') {
                continue;
            }
            $gifts[] = $gift;
        }
        $data['gifts'] = $gifts;

        return $data;
    }
}
