<?php

namespace External\VarioBundle\Synchronizers;

use KupShop\CatalogBundle\Section\SectionTree;
use KupShop\ContentBundle\Util\Block;
use Query\Operator;

class SectionSynchronizer extends BaseSynchronizer
{
    protected static $type = 'otCategory';
    protected static $batch = 100;
    protected static $maxBatches = 30;

    protected $logging = true;

    protected $fields = [
        'CategoryName' => 'name',
        'ParentID' => 'relation',
        'Visible' => 'figure',
        'Order' => 'position',
        'Description' => 'description',
    ];

    /** @var SectionTree */
    private $sectionTree;

    /** @var Block */
    private $blockUtil;

    /**
     * @required
     */
    public function setSectionTree(SectionTree $sectionTree): void
    {
        $this->sectionTree = $sectionTree;
    }

    /**
     * @required
     */
    public function setBlockUtil(Block $blockUtil): void
    {
        $this->blockUtil = $blockUtil;
    }

    public function getEshopID($objectID)
    {
        $object = $objectID;
        if (empty($object->ID)) {
            return null;
        }

        $objectID = $this->helper->trimVarioId($object->ID);

        $id = $this->helper->getMapping('vario_sections', $objectID);
        if (!$id) {
            $id = sqlGetConnection()->transactional(function () use ($objectID) {
                sqlQueryBuilder()
                    ->insert('sections')
                    ->directValues(
                        [
                            'name' => $objectID,
                            'figure' => 'N',
                        ]
                    )->execute();

                return (int) sqlInsertId();
            });

            $this->helper->createMapping('vario_sections', $objectID, $id);
        }

        return $id;
    }

    public function syncDelete($eshopID)
    {
        $this->deleteSQL('sections', ['id' => $eshopID]);
    }

    public function syncName($value, $sectionID)
    {
        $this->updateSQL(
            'sections',
            [
                'name' => $value,
                'figure' => 'Y',
            ],
            ['id' => $sectionID]
        );
    }

    public function syncDescription($value, $sectionID): void
    {
    }

    public function syncFigure($value, $sectionID)
    {
        $this->updateSQL('sections', ['figure' => $value ? 'Y' : 'N'], ['id' => $sectionID]);
    }

    public function syncRelation($value, $sectionID, $column)
    {
        if (empty($value)) {
            $value = null;
        } else {
            $value = $this->helper->trimVarioId($value);
        }

        $this->updateSQL('vario_sections', ['parent' => $value], ['id_section' => $sectionID]);
    }

    public function syncPosition($value, $sectionID)
    {
        $this->updateSQL('vario_sections', ['position' => $value], ['id_section' => $sectionID]);
    }

    protected function postprocess()
    {
        sqlGetConnection()->transactional(function () {
            $qb = sqlQueryBuilder()
                ->select('*')
                ->from('vario_sections');

            foreach ($qb->execute() as $section) {
                $parentId = $this->getParent($section);

                try {
                    $this->deleteSQL('sections_relation', ['id_section' => $section['id_section']]);
                    $this->insertSQL(
                        'sections_relation',
                        [
                            'id_section' => $section['id_section'],
                            'id_topsection' => $parentId,
                            'position' => $section['position'] === null ? 999 : $section['position'],
                        ]
                    );
                } catch (\Exception $e) {
                }
            }
        });

        $this->sectionTree->clearCache();
    }

    private function getParent(array $item): ?int
    {
        $parentId = null;
        if ($item['parent']) {
            if (!($parentId = $this->helper->getMapping('vario_sections', $item['parent']))) {
                $parentId = null;
            }
        }

        return $parentId;
    }

    protected function getObjectID($item)
    {
        if ($item->Job->Action === 'acDelete') {
            return (object) ['ID' => $item->Job->ObjectID];
        }

        return $item->Data;
    }

    protected function getSyncAllObjects()
    {
        return array_map(function ($x) { return ['id_vario' => $x]; }, $this->client->getCategories(true));
    }

    private function updateBlock(int $rootBlockId, string $identifier, string $text, int $position = 2): void
    {
        $blockId = sqlQueryBuilder()
            ->select('id')
            ->from('blocks')
            ->where(Operator::equals([
                'id_root' => $rootBlockId,
                'identifier' => $identifier,
            ]))->execute()->fetchColumn();

        if ($blockId) {
            sqlQueryBuilder()
                ->update('blocks')
                ->directValues([
                    'content' => $text,
                    'json_content' => $this->blockUtil->createLegacyBlockJsonContent($text),
                    'position' => $position,
                ])
                ->where(Operator::equals(['id' => $blockId]))
                ->execute();
        } else {
            sqlQueryBuilder()
                ->insert('blocks')
                ->directValues([
                    'id_root' => $rootBlockId,
                    'id_parent' => $rootBlockId,
                    'identifier' => $identifier,
                    'content' => $text,
                    'json_content' => $this->blockUtil->createLegacyBlockJsonContent($text),
                    'position' => $position,
                ])->execute();
        }
    }
}
