<?php

namespace KupShop\ElninoBundle\AdWords\GroupType;

use KupShop\CatalogBundle\Util\CampaignsUtil;
use KupShop\ElninoBundle\Query\Filter as ElninoFilter;
use KupShop\ElninoBundle\Query\Sortiment;
use KupShop\KupShopBundle\Context\CurrencyContext;
use Query\Filter;
use Query\Operator;
use Query\QueryBuilder;

abstract class AbstractGroupType
{
    protected $type;
    /**
     * @var Sortiment
     */
    private $sortimentQuery;
    /**
     * @var CampaignsUtil
     */
    private $campaignsUtil;

    /** @var CurrencyContext */
    protected $currencyContext;

    /**
     * @return \Query\QueryBuilder
     */
    public function getProductsQueryset(&$match)
    {
        $match['type'] = $this->type;

        $qb = sqlQueryBuilder()
            ->select('MIN(IF(p.in_store > 0, p.price, NULL)) as min_price, p.vat')
            ->fromProducts()
            ->joinModelsOnProducts()
            ->joinSeriesOnProducts('absr')
            ->addSelect('SUM(p.in_store) as test')
            ->addSelect('SUM(IF(p.in_store > 0, 1, 0)) as count_in_store')
            ->addSelect('SUM(p.pieces_sold3) as sum_sold')
            ->addSelect('GROUP_CONCAT(DISTINCT IF(p.in_store > 0, p.size, NULL)) as sizes')
            ->addSelect('COUNT(DISTINCT absr.id_serie, COALESCE(p.id_complement_model, 0)) as count_series')
            ->addSelect('GROUP_CONCAT(DISTINCT p.code) as codes')
            ->addSelect('MAX(IF(p.in_store > 0, p.display_discount, NULL)) as max_discount')
            ->andWhere('p.figure = "Y"');

        $qb = $this->applyFilter($qb, $match);

        return $qb;
    }

    /**
     * @param $range \stdClass
     *
     * @return \Range
     */
    protected function parseRange(\stdClass $range)
    {
        return new \Range($range->min ?: null, $range->max ?: null);
    }

    /**
     * @param $qb \Query\QueryBuilder
     */
    public function applyGroupParams($qb, $group_params)
    {
        if (!empty($group_params->price)) {
            $qb->andWhere(Operator::between('p.price', $this->parseRange($group_params->price)));
        }

        if (!empty($group_params->volume)) {
            $qb->andWhere(Operator::between('p.size_value', $this->parseRange($group_params->volume)));
        }

        if (!empty($group_params->sortiment)) {
            if (count($group_params->sortiment) == 1) {
                if ($group_params->sortiment[0] == 'Cosmetics') {
                    $qb->andWhere($this->sortimentQuery->onlyCosmetics());
                }
                if ($group_params->sortiment[0] == 'Perfumes') {
                    $qb->andWhere($this->sortimentQuery->onlyPerfumes());
                }
            }
        }

        if (!empty($group_params->discount)) {
            $qb->andWhere(Operator::between('p.display_discount', $this->parseRange($group_params->discount)));
        }

        return $qb;
    }

    public function applyFilter(QueryBuilder $qb, &$match)
    {
        $parameter = translate_template('kategorie');
        if (!empty($match[$parameter])) {
            $qb->andWhere(Filter::byParameters([28 => ['type' => \Filter::PARAM_LIST, 'values' => $match[$parameter]]]));
        }

        $parameter = translate_template('rada');
        if (!empty($match[$parameter])) {
            $qb->andWhere(ElninoFilter::bySeries($match[$parameter]));
        }

        $parameter = translate_template('vyrobce');
        if (!empty($match[$parameter])) {
            $qb->andWhere(Filter::byProducers($match[$parameter]));
        }

        $parameter = translate_template('cena');
        if (!empty($match[$parameter])) {
            $vat_multiplier = (100 + getVat()) / 100.;
            $qb->andWhere(Operator::between('p.price', new \Range($match[$parameter][0] / $vat_multiplier, $match[$parameter][1] / $vat_multiplier)));
        }

        if (isset($match['campaign'])) {
            $campaign = $this->campaignsUtil->getCampaignByUrl($match['campaign']);
            if ($campaign) {
                $qb->andWhere(Filter::byCampaigns([$campaign]));
            }
        }

        // Pohlavi
        $parameter = translate_template('pohlavi');
        if (isset($match[$parameter])) {
            $qb->andWhere(ElninoFilter::bySex($match[$parameter]));
        }

        return $qb;
    }

    /**
     * @param $qb \Query\QueryBuilder
     *
     * @return array
     */
    public function formatResult($group, $qb, $match)
    {
        $data = $qb->execute()->fetch();

        $sizes = explode(',', $data['sizes']);

        $result = [
            'group_id' => (int) $group->id,
            'stock_count' => $data['count_in_store'] > 0 ? 1 : 0,
            'clickthru_url' => $group->clickthru_url,
            'min_price' => [
                'amount' => (float) roundPrice(toDecimal($data['min_price'])->addVat(getVat($data['vat'])))->printFloatValue(),
                'currency' => $this->currencyContext->getActiveId(),
            ],
            'group_info' => [
                'count_series' => (int) $data['count_series'],
                'url_type' => $match['type'],
                'sale_info' => (int) $data['sum_sold'],
                'variant_info' => (int) $data['count_in_store'],
                'volume_info' => $sizes,
                'discount_info' => (int) $data['max_discount'],
            ],
        ];

        if (isDebug()) {
            $result['sql'] = $qb->getSQL();
            $result['sql_params'] = $qb->getParameters();
            $result['codes'] = explode(',', $data['codes']);
            $result['group'] = $group;
        }

        return $result;
    }

    public function __construct(Sortiment $sortimentQuery, CampaignsUtil $campaignsUtil)
    {
        $this->sortimentQuery = $sortimentQuery;
        $this->campaignsUtil = $campaignsUtil;
    }

    /**
     * @required
     */
    public function setLanguageContext(CurrencyContext $currencyContext): AbstractGroupType
    {
        $this->currencyContext = $currencyContext;

        return $this;
    }
}
