<?php

namespace External\SprintBundle\Synchronizers;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Query\QueryBuilder;
use External\MSSQLBundle\Synchronizers\BaseSynchronizer;
use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\KupShopBundle\Util\Database\QueryHint;
use Query\Operator;

class StockSynchronizer extends BaseSynchronizer
{
    protected static $type = 'stock';

    protected static $tableName = 'hvw_WPJ_ZmenaDatProduktu';
    protected static $tableAlias = 'p';
    protected array $timeLog = [];
    protected array $products = [];
    protected array $productsStock = [];
    protected array $variations = [];
    protected array $variationsStock = [];
    protected static $selectFields = [
        'p.ID' => 'id',
        'p.code' => 'code',
        'p.in_store' => 'in_store',
    ];
    protected static $tableDateColumn = 'PorizenoZmeneno';
    protected array $products_variations = [];

    protected function process(?int $lastSyncTime = null): void
    {
        $this->timeLog = [];

        QueryHint::routeToMaster();
        try {
            $this->processProducts($lastSyncTime);
            $this->connection->close();

            ProductSynchronizer::hideOutOfStockProducts();
            $this->connection->close();
        } catch (\Exception|\Error|\Throwable $e) {
            echo $e->getMessage();
            addActivityLog(
                severity: ActivityLog::SEVERITY_WARNING,
                type: ActivityLog::TYPE_SYNC,
                message: 'Chyba synchronizace skladu:',
                data: [$e?->getMessage()]
            );
        }
        $this->connection->close();
        addActivityLog(ActivityLog::SEVERITY_SUCCESS,
            ActivityLog::TYPE_SYNC,
            'Synchronizace skladu',
            $this->timeLog);
        QueryHint::routeToMaster(false);
    }

    private function processProducts(?int $lastSyncTime = null): void
    {
        ini_set('memory_limit', '2048M');
        $this->setCacheData();

        $this->timeLog[] = ['time' => date('d-m-Y-H-i-s'), 'message' => 'Načteny data pro reklamní předmět'];
        $qb = $this->getQueryBuilder(null)->andWhere('p.id NOT IN (138954, 154707, 154724, 154725, 154726, 402710, 402715, 402720, 402725)');
        if (!empty($this->config['brand_column_name'])) {
            $qb->andWhere("{$this->config['brand_column_name']}=1");
        } elseif (!empty($this->config['brand_ids'])) {
            $qb->andWhere('producer IN (:list)')->setParameter(':list', $this->config['brand_ids'], Connection::PARAM_INT_ARRAY);
        }
        $qb->andWhere('p.price>0');
        $qb->andWhere('p.code!=\'\'');
        $qb->andWhere('producer IS NOT NULL');
        $this->timeLog[] = ['time' => date('d-m-Y-H-i-s'), 'message' => 'Načteny data pro produkty'];

        $this->processProduct($qb);
        $this->connection->close();

        \Variations::recalcInStore();
        $this->timeLog[] = ['time' => date('d-m-Y-H-i-s'), 'message' => 'Synchronizace produktů dokončena'];
    }

    private function setCacheData()
    {
        $this->products = sqlQueryBuilder()->select('code', 'id')->from('products')->execute()->fetchAllKeyValue();
        $this->productsStock = sqlQueryBuilder()->select('id', 'in_store')->from('products')->execute()->fetchAllKeyValue();
        $this->variations = sqlQueryBuilder()->select('code', 'id')->from('products_variations')->execute()->fetchAllKeyValue();
        $this->variationsStock = sqlQueryBuilder()->select('id', 'in_store')->from('products_variations')->execute()->fetchAllKeyValue();
    }

    private function processProduct(QueryBuilder $qb)
    {
        $count = 0;
        foreach ($qb->orderBy('PorizenoZmeneno')->execute() as $product) {
            $updateProducts[] = $product;
        }
        $this->connection->close();
        echo date('H:i:s', time()).' Počet produktů k synchronizaci '.count($updateProducts).'<br />';
        foreach ($updateProducts as $product) {
            $count++;
            if ($count % 500 == 0) {
                $this->timeLog[] = ['time' => date('d-m-Y-H-i-s'), 'message' => 'Probíhá synchronizace skladu', 'count' => $count];
                echo date('H:i:s', time()).' '.$count.'<br />';
            }
            if ($idVariation = $this->variations[$product['code']] ?? false) {
                if (($this->variationsStock[$idVariation] ?? false) && $this->variationsStock[$idVariation] != $product['in_store']) {
                    sqlQueryBuilder()->update('products_variations')->directValues(['in_store' => $product['in_store']])
                        ->andWhere(Operator::equals(['id' => $idVariation]))
                        ->andWhere(Operator::not(Operator::equals(['in_store' => $product['in_store']])))
                        ->execute();
                }
            } elseif ($idProduct = $this->products[$product['code']] ?? false) {
                if (($this->productsStock[$idProduct] ?? false) && $this->productsStock[$idProduct] != $product['in_store']) {
                    sqlQueryBuilder()->update('products')->directValues(['in_store' => $product['in_store']])
                        ->andWhere(Operator::equals(['id' => $idProduct]))
                        ->andWhere(Operator::not(Operator::equals(['in_store' => $product['in_store']])))
                        ->execute();
                }
            }
        }
    }
}
