<?php

namespace KupShop\PohodaBundle\Utils\Exporters;

use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\KupShopBundle\Context\CountryContext;
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\PohodaBundle\Utils\Importers\ProductsImporter;
use KupShop\PohodaBundle\Utils\PohodaBase;
use KupShop\PohodaBundle\Utils\Tools\PohodaProductExporter;
use Query\Operator;
use Symfony\Contracts\Service\Attribute\Required;

class ProductExporter
{
    use \DatabaseCommunication;
    use PohodaBase;

    private $IDs;

    /**
     * @var PohodaProductExporter
     */
    private $productExporter;

    /**
     * @var LanguageContext
     */
    private $languageContext;

    /**
     * @var DomainContext
     */
    private $domainContext;

    /**
     * @var CountryContext
     */
    private $countryContext;

    #[Required]
    public ProductsImporter $productsImporter;

    public function getData()
    {
        $variationIDs = [];
        $productIDs = [];

        foreach ($this->getProducts() as $row) {
            $productIDs[] = $row['id_product'];
            $variationIDs[$row['id_variation']] = true;
        }

        if ($productIDs) {
            $this->productExporter->setVariationIDs($variationIDs);

            return $this->productExporter->getXML($productIDs, false);
        }

        return false;
    }

    public function processData($xml = null)
    {
        // Nastavuje se kvůli volání z adminu jiný mutace
        $previousActiveLanguage = $this->languageContext->getActiveId();
        $previousActiveCountry = $this->countryContext->getActiveId();
        $this->languageContext->activate($this->languageContext->getDefaultId());
        $this->countryContext->activate('CZ');

        $this->pohodaConnector->prepareSyncTime();
        $xml = $xml ?: $this->getData();

        if ($xml) {
            $productsRequest = $this->transformHelper->baseTransform($xml, $this->transformHelper->loadXslt('createProducts.xsl'));
            $request = $this->replace($productsRequest->saveXML());
            $this->addRequestLog('Product Export, Domain: '.$this->domainContext->getActiveId(), $request);
            $response = $this->pohodaConnector->sendRequest($request);
            if ($response) {
                $this->processResponse($response);
            }
        }

        // Zpátky vrátím jazyk a zemi na původní hodnoty
        $this->languageContext->activate($previousActiveLanguage);
        $this->countryContext->activate($previousActiveCountry);

        $this->pohodaConnector->setLastSyncTime('productsCreatorOut');
        $this->setIDs(null);
    }

    public function processResponse($xmlStringResponse)
    {
        $alreadyImportedProducts = ['products' => [], 'variations' => []];

        $xml = simplexml_load_string($xmlStringResponse);
        $this->pohodaConnector->checkValidResponse($xml);
        foreach ($xml->xpath('rsp:responsePackItem') as $responsePackItem) {
            try {
                $this->addResponseLog('Product Export', $responsePackItem->asXML());
            } catch (\Throwable $exception) {
            }

            $attr = $responsePackItem->attributes();
            $IDs = explode('_', $attr['id']);
            if (!$responsePackItem->xpath('stk:stockItemResponse/rdc:importDetails/rdc:detail/rdc:errno[text() = 109]')) {
                if ($attr['id'] && $attr['state'] == 'ok') {
                    sqlQueryBuilder()
                        ->update(($IDs[1] ?? false) ? 'products_variations' : 'products')
                        ->set('pohoda_sync_date', 'NOW()')
                        ->where(Operator::equals(['id' => (($IDs[1] ?? false) ? $IDs[1] : $IDs[0])]))
                        ->execute();
                }
            } else {
                if ($IDs[1] ?? false) {
                    $alreadyImportedProducts['variations'][] = $IDs[1];
                } else {
                    $alreadyImportedProducts['products'][] = $IDs[0];
                }
            }
        }

        $codesToSync = [];
        if ($alreadyImportedProducts['variations'] ?? false) {
            $codesToSync = sqlQueryBuilder()->select('pv.code')
                ->from('products_variations', 'pv')
                ->where(Operator::inIntArray($alreadyImportedProducts['variations'], 'pv.id'))
                ->execute()->fetchFirstColumn();
        }

        if ($alreadyImportedProducts['products'] ?? false) {
            $codesToSync += sqlQueryBuilder()
                ->select('code')
                ->from('products')
                ->where(Operator::inIntArray($alreadyImportedProducts['products'], 'id'))
                ->execute()->fetchFirstColumn();
        }

        if ($codesToSync) {
            $this->productsImporter->setIDs($codesToSync);
            $this->productsImporter->processData();

            addActivityLog(ActivityLog::SEVERITY_WARNING,
                ActivityLog::TYPE_SYNC,
                'Dopárování již existujících produktů v Pohodě.',
                [
                    'ids' => $alreadyImportedProducts,
                    'responseObject' => (array) $xmlStringResponse,
                ]);
        }
    }

    public function getProducts($spec = null)
    {
        if (!$this->isFullSync()) {
            $qb = sqlQueryBuilder()
                ->select('oi.id_product, oi.id_variation')
                ->from('orders', 'o')
                ->leftJoin('o', 'order_items', 'oi', 'o.id = oi.id_order')
                ->leftJoin('oi', 'products', 'p', 'p.id = oi.id_product')
                ->leftJoin('oi', 'products_variations', 'pv', 'pv.id = oi.id_variation');

            if ($spec) {
                $qb->andWhere($spec);
            }

            if (!is_null($this->IDs)) {
                $qb->andWhere(Operator::inIntArray($this->IDs, 'id'));
            } else {
                if (!empty($this->pohodaConnector->getCurrent()['productsCreatorOut']['last_sync'])) {
                    $datetime = new \DateTime();
                    $datetime->setTimestamp(strtotime($this->pohodaConnector->getCurrent()['productsCreatorOut']['last_sync']));
                    $qb->andWhere('oi.date >="'.$this->prepareDateTime($datetime).'"');
                } else {
                    $qb->andWhere('oi.date >= NOW() - INTERVAL 7 DAY');
                }
            }

            $qb->andWhere('status_storno = 0 AND oi.id_product IS NOT NULL');
            $qb->andWhere('(oi.id_variation IS NOT NULL AND pv.pohoda_sync_date IS NULL) OR p.pohoda_sync_date IS NULL');

            return $qb->execute()->fetchAll();
        }
    }

    public function setIDs($IDs)
    {
        $this->IDs = $IDs;
    }

    /**
     * @required
     */
    public function setProductExporter(PohodaProductExporter $productExporter)
    {
        $this->productExporter = $productExporter;
    }

    /**
     * @required
     */
    public function setLanguageContext(LanguageContext $languageContext): void
    {
        $this->languageContext = $languageContext;
    }

    /**
     * @required
     */
    public function setDomainContext(DomainContext $domainContext): void
    {
        $this->domainContext = $domainContext;
    }

    /**
     * @required
     */
    public function setCountryContext(CountryContext $countryContext): void
    {
        $this->countryContext = $countryContext;
    }
}
