<?php

/*
 * Smarty plugin
 * -------------------------------------------------------------
 * Type:     function
 * Name:     get_stats
 * Purpose:  returns various statistic numbers
 * -------------------------------------------------------------
 */

use KupShop\CatalogBundle\Util\FavoriteProductsUtil;
use KupShop\I18nBundle\Util\PriceConverter;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\CountryContext;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\KupShopBundle\Util\Price\PriceCalculator;
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;

function smarty_function_get_stats($params, &$smarty)
{
    $type = null;
    $result = null;

    extract($params);

    if (empty($type)) {
        trigger_error("Chybějící parametr 'type'");
    }

    switch ($type) {
        case 'products_count':
            $key = join('_', $params);
            $result = getCache($key);
            if (!$result) {
                $from = getTableName('products').' p';
                $where = 'figure="Y"';
                $data = [];

                if (!empty($params['in_store'])) {
                    $where .= ' AND p.in_store > 0 ';
                }

                if (!empty($params['category'])) {
                    $from .= ' LEFT JOIN '.getTableName('products-sections').' ps ON p.id=ps.id_product';
                    $where .= ' AND ps.id_section = :section ';
                    $data['section'] = $params['category'];
                }

                $result = returnSQLResult("SELECT COUNT(*) FROM {$from} WHERE {$where}", $data);

                setCache($key, $result);
            }

            break;

        case 'cart_free_delivery':
        case 'free_delivery':
            $with_empty_purchasestate = $type == 'free_delivery';

            if (!$with_empty_purchasestate) {
                /** @var Cart $cart */
                $cart = ServiceContainer::getService(\KupShop\OrderingBundle\Cart::class);
                if ($cart->hasOnlyVirtualProducts() && !($params['alllow_only_virtual_products'] ?? false)) {
                    return null;
                }
            }

            $purchaseUtil = ServiceContainer::getService(PurchaseUtil::class);
            $freeDeliveryFrom = $purchaseUtil->getFreeDeliveryFrom($with_empty_purchasestate);

            if (Contexts::get(UserContext::class)->isActive() || ($params['registered'] ?? false)) {
                $freeDeliveryFrom = $freeDeliveryFrom['registered'];
            } else {
                $freeDeliveryFrom = $freeDeliveryFrom['unregistered'];
            }

            if ($freeDeliveryFrom) {
                $converter = ServiceContainer::getService(PriceConverter::class);
                $currencyContext = Contexts::get(CurrencyContext::class);
                $result = $converter->convert($freeDeliveryFrom->getCurrency(), $currencyContext->getActive(), $freeDeliveryFrom->getValue());
            }
            break;

        case 'user_spending':
            if (Contexts::get(UserContext::class)->isActive()) {
                $where = 'o.id_user = :user_id';
                $data = [
                    'user_id' => Contexts::get(UserContext::class)->getActiveId(),
                ];

                if (!empty($params['year'])) {
                    $where .= ' AND YEAR(o.date_created) = :year ';
                    $data['year'] = $params['year'];
                }

                if (!empty($params['last_year'])) {
                    $year = intval($params['last_year']);
                    $where .= " AND date_created > DATE_SUB( NOW(), INTERVAL {$year} YEAR) ";
                }
                // Pokud chtějí zobrazovat přesný součet objednávek v dané měně
                if (isset($params['currency'])) {
                    $spendActiveCurrency = sqlQueryBuilder()
                    ->select('SUM(o.total_price) as total')
                    ->from(getTableName('orders'), 'o')
                    ->andWhere(\Query\Operator::equals(['id_user' => $data['user_id'], 'o.currency' => $params['currency']]))
                    ->execute()->fetchOne();

                    $result = toDecimal($spendActiveCurrency);
                } else {
                    $result = applyCurrency(returnSQLResult('SELECT SUM(o.total_price'.(findModule('currencies') ? '* o.currency_rate' : '').') FROM orders AS o WHERE '.$where, $data));
                }
            } else {
                $result = null;
            }
            break;

        case 'user_orders':
            global $ctrl;
            $result = sqlQueryBuilder()
                ->select('COUNT(*) as orders_num')
                ->from('orders', 'o')
                ->where('id_user=:id_user')
                ->setParameter('id_user', $ctrl['id'])
                ->execute()->fetchColumn();
            break;

        case 'user_points':
            global $ctrl;
            if (!$ctrl['id']) {
                $result = null;
                break;
            }

            $last_date = sqlQueryBuilder()
                ->select('date_created')
                ->from('bonus_points', 'b')
                ->where('id_user=:id_user')
                ->andWhere(\Query\Operator::equals(['b.status' => 'active']))
                ->setParameter('id_user', $ctrl['id'])
                ->orderBy('date_created', 'DESC')
                ->setMaxResults(1)
                ->execute()->fetchColumn();

            if (!$last_date) {
                $result = null;
                break;
            }

            $insert_date = (new \DateTime())->setTimestamp(strtotime($last_date));

            if (!empty($expire_date)) {
                $dbcfg = Settings::getDefault();
                $result = $insert_date->modify("+ {$dbcfg->bonus_program['remove_time']} day");
            } else {
                $result = $insert_date;
            }
            break;

        case 'user_unsolved_orders':
            global $ctrl;
            $result = sqlQueryBuilder()
                ->select('COUNT(*) as orders_num')
                ->from('orders', 'o')
                ->where('id_user=:id_user')
                ->andWhere('o.status_storno = 0')
                ->andWhere(\Query\Operator::inIntArray(getStatuses('nothandled'), 'o.status'))
                ->setParameter('id_user', $ctrl['id'])
                ->execute()->fetchColumn();
            break;

        case 'user_favorite_goods':
            $userContext = Contexts::get(UserContext::class);
            $productList = new ProductList();
            $productList->applyDefaultFilterParams();
            $productList->andSpec(function (Query\QueryBuilder $qb) use ($userContext) {
                if ($userContext->getActiveId()) {
                    $qb->join('p', 'products_favorites', 'pf', 'pf.id_product = p.id');
                    $qb->andWhere(\Query\Operator::equals(['pf.id_user' => $userContext->getActiveId()]));
                } else {
                    $qb->andWhere(\Query\Operator::inIntArray(FavoriteProductsUtil::getCookieProducts(), 'p.id'));
                }
            });

            $result = $productList->getProductsCount();
            break;

        case 'user_watchdog':
            $user = User::getCurrentUser();
            $result = sqlQueryBuilder()
                ->select('COUNT(*) as watchdog')
                ->from('products_watchdog', 'pw')
                ->where(\Query\Operator::equals(['id_user' => $user->id]))
                ->execute()->fetchColumn();
            break;

        case 'user_shopping_list':
            $user = User::getCurrentUser();
            $result = sqlQueryBuilder()
                ->select('COUNT(*) as shopping_list')
                ->from('shopping_list', 'sl')
                ->where(\Query\Operator::equals(['id_user' => $user->id]))
                ->execute()->fetchColumn();
            break;

        case 'user_reclamations':
            $user = User::getCurrentUser();
            $result = sqlQueryBuilder()
                ->select('COUNT(*) as reclamations')
                ->from('reclamations', 'r')
                ->join('r', 'order_items', 'oi', 'oi.id=r.id_item')
                ->join('oi', 'orders', 'o', 'oi.id_order=o.id')
                ->where(\Query\Operator::equals(['o.id_user' => $user->id]))
                ->execute()->fetchColumn();
            break;

        case 'elnino_reclamations':
            $user = User::getCurrentUser();
            $result = sqlQueryBuilder()
                ->select('COUNT(*) as reclamations_elnino')
                ->from('reclamations_elnino', 'r')
                ->join('r', 'reclamation_items_elnino', 'ri', 'r.id=ri.id_reclamation')
                ->join('ri', 'order_items', 'oi', 'oi.id=ri.id_item')
                ->join('oi', 'orders', 'o', 'oi.id_order=o.id')
                ->where(\Query\Operator::equals(['o.id_user' => $user->id]))
                ->execute()->fetchColumn();
            break;

        case 'user_returns':
            $user = User::getCurrentUser();
            $result = sqlQueryBuilder()
                ->select('COUNT(*) as returns')
                ->from('returns', 'r')
                ->join('r', 'return_items', 'ri', 'r.id = ri.id_return')
                ->join('ri', 'order_items', 'oi', 'oi.id = ri.id_item')
                ->join('oi', 'orders', 'o', 'oi.id_order=o.id')
                ->where(\Query\Operator::equals(['o.id_user' => $user->id]))
                ->execute()->fetchColumn();
            break;

        case 'product_compare':
            /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
            $session = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService('session');
            $result = count($session->get('productCompare', []));
            break;

        case 'delivery_dates':
            $country = Contexts::get(CountryContext::class);
            $cache_key = "delivery_dates_{$country->getActiveId()}";

            $result = getCache($cache_key);

            if ($result) {
                break;
            }

            $deliveries = Delivery::getAll();

            $dateMinInPerson = null;
            $dateMinDelivery = null;
            $list = [];

            foreach ($deliveries as $id => $delivery) {
                $date = $delivery->getDeliveryDate();
                if (!$date) {
                    continue;
                }

                $list[$id] = [
                    'name' => $delivery->name,
                    'delivery_date' => $date,
                ];

                if ($delivery->isInPerson()) {
                    if (is_null($dateMinInPerson) || $dateMinInPerson > $date) {
                        $dateMinInPerson = $date;
                    }
                } elseif (is_null($dateMinDelivery) || $dateMinDelivery > $date) {
                    $dateMinDelivery = $date;
                }
            }

            $result = [
                'list' => $list,
                'min' => [
                    'in_person' => $dateMinInPerson,
                    'delivery' => $dateMinDelivery,
                ],
            ];

            setCache($cache_key, $result, 600);

            break;
        case 'max_dimensions':
            if (empty($cart)) {
                trigger_error('Chybí košík v parametru cart!');
            }

            $result = $cart->getPurchaseState()->getDeliveryRestrictionParams()->getMaxDimensions();

            break;

        case 'sum_of_dimensions':
            if (empty($cart)) {
                trigger_error('Chybí košík v parametru cart!');
            }

            $result = $cart->getPurchaseState()->getDeliveryRestrictionParams()->getMaxSumOfEachDimension();

            break;

        case 'cheapest_delivery':
            $countryContext = Contexts::get(CountryContext::class);
            $contextManager = ServiceContainer::getService(ContextManager::class);

            $country = $params['country'] ?? $countryContext->getActiveId();

            $result = $contextManager->activateContexts([CountryContext::class => $country], function () use ($params, $country) {
                /** @var Cart $cart */
                $cart = ServiceContainer::getService(\KupShop\OrderingBundle\Cart::class);
                if ($cart->hasOnlyVirtualProducts() && !($params['alllow_only_virtual_products'] ?? false)) {
                    return null;
                }

                $cacheName = 'cheapestDelivery_'.$country;
                if (!empty($params['key'])) {
                    $cacheName .= $params['key'];
                }

                if (User::getCurrentUser() || ($params['registered'] ?? false)) {
                    $cacheName .= '_reg';
                }

                if (!isset($params['registered'])) {
                    $params['registered'] = null;
                }

                $cache = getCache($cacheName, $found);
                if (!$found) {
                    $cache = null;
                    $types = DeliveryType::getAll();
                    $currencyContext = ServiceContainer::getService(CurrencyContext::class);
                    $defaultCurrency = $currencyContext->getDefault();

                    $min = null;
                    $vat = getVat();
                    $deliveries = [];
                    foreach ($types as $type) {
                        if ($type->delivery_class == 'OsobniOdber') {
                            continue;
                        }
                        if ($type->accept(new Price(toDecimal(0), $defaultCurrency, 0), false)) {
                            if ($type->getDelivery()->getPrice()) {
                                $price = $type->getDelivery()->getPrice();
                                $vat = $price->getVat();
                                $price = PriceCalculator::convert($price, $defaultCurrency);
                                $deliveries[] = $price->getValue();
                            }
                        }
                    }

                    if (!empty($deliveries)) {
                        $min = min($deliveries);
                    }

                    if ($min !== null) {
                        $cache = new Price(toDecimal($min), $defaultCurrency, $vat);
                    }

                    setCache($cacheName, $cache);
                }

                if ($cache != false) {
                    $result = $cache;
                } else {
                    $result = null;
                }

                return $result;
            });
            break;
        case 'reviews_count':
            $result = 0;
            if (findModule(\Modules::REVIEWS)) {
                $result = sqlQueryBuilder()
                    ->select('COUNT(*) as reviews_count')
                    ->from('reviews', 'r')
                    ->execute()->fetchColumn();
            }
            break;
        case 'average_rating':
            $result = 0;
            if (findModule(\Modules::REVIEWS)) {
                $result = sqlQueryBuilder()
                    ->select('AVG(r.rating) as average_rating')
                    ->from('reviews', 'r')
                    ->execute()->fetchColumn();
            }
            break;
        default:
            trigger_error("Neexistující 'type': {$type}");
    }

    if (!empty($params['assign'])) {
        $smarty->assign($params['assign'], $result);
    } else {
        return $result;
    }
}
