<?php

use KupShop\AdminBundle\AdminBlocksTrait;
use KupShop\AdminBundle\Util\AdminSectionTree;
use KupShop\AdminBundle\Util\BlocksHistory;
use KupShop\CatalogBundle\Util\SectionUtil;
use KupShop\ContentBundle\Util\BlocksTrait;
use KupShop\ContentBundle\Util\SliderUtil;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\System\UniqueUrlUtil;
use KupShop\RewriteBundle\Util\Rewrite;
use Query\Operator;

$main_class = 'sections';

class Sections extends Window
{
    use BlocksTrait;
    use AdminBlocksTrait;

    private AdminSectionTree $adminSectionTree;
    protected $show_on_web = 'category';

    protected $defaults = [
        'behaviour' => 2,
        'orderby' => 'title',
        'orderdir' => 'ASC',
        'figure' => 'Y',
        'show_in_search' => 'Y',
        'lead_figure' => 'N',
        'lead_products' => '',
        'lead_products_figure' => 'N',
        'producers_indexing' => 'N',
        'producers_to_title' => 'N',
        'data' => null,
        'virtual' => 'N',
    ];

    /** @var BlocksHistory */
    private $blocksHistory;
    private SectionUtil $sectionUtil;
    private ?SliderUtil $sliders = null;

    public function __construct()
    {
        $this->blocksHistory = ServiceContainer::getService(BlocksHistory::class);
        $this->adminSectionTree = ServiceContainer::getService(AdminSectionTree::class);
        $this->sectionUtil = ServiceContainer::getService(SectionUtil::class);

        if (findModule(\Modules::SLIDERS)) {
            $this->sliders = ServiceContainer::getService(SliderUtil::class);
        }
    }

    public function get_vars()
    {
        $vars = parent::get_vars();

        $pageVars = getVal('body', $vars);
        $acn = $this->getAction();
        $ID = $this->getID();
        if ($acn == 'edit' && $ID == 0) {
            $pageVars['data'] = $this->getObject();
        }

        if ($acn == 'remove') {
            $pageVars['tree'] = $this->adminSectionTree->getCategories();
        }

        $categoryView = ServiceContainer::getService(\KupShop\CatalogBundle\View\CategoryView::class);
        $pageVars['sortOptions'] = $categoryView->getSortOptions();

        if ($acn == 'remove' && !empty($ID)) {
            $this->setTemplate('window/sectionErase.tpl');

            $SQL = sqlQuery('SELECT * FROM '.getTableName('sections')." WHERE id='{$ID}' ");
            foreach ($SQL as $row) {
                $pageVars['data'] = $row;
            }

            $pageVars['isTopBranch'] = returnSQLResult('SELECT COUNT(*) FROM '.getTableName('sections_relation')." WHERE id_topsection='{$ID}' ");
            $pageVars['deleteSubsections'] = getVal('deleteSubsections');
            $pageVars['acn'] = 'erase';
        } else {
            $pageVars['data']['lead_products_figure'] = (isset($pageVars['data']['lead_products']) && $pageVars['data']['lead_products'] != '') ? 'Y' : 'N';

            // Parameters
            $qb = sqlQueryBuilder()
                ->select('*')
                ->from('parameters_sections')
                ->where(Operator::equals(['id_section' => $ID, 'filter' => 'Y']))
                ->orderBy('weight', 'ASC');

            $parameters = [];
            foreach ($qb->execute() as $row) {
                $parameters[$row['id_parameter']] = [
                    'checked' => 1,
                    'weight' => $row['weight'],
                ];

                if (findModule(Modules::INDEXED_FILTER)) {
                    $parameters[$row['id_parameter']] += [
                        'index_checked' => ($row['indexing'] == 'Y') ? true : false,
                        'toTitle_checked' => ($row['to_title'] == 'Y') ? true : false,
                    ];
                }
            }

            $SQL = sqlQuery('SELECT id, name, name_frontend, unit 
                           FROM '.getTableName('parameters').'
                           ORDER BY name ASC ');
            foreach ($SQL as $row) {
                $parameters[$row['id']] = array_merge(getVal($row['id'], $parameters, []), $row);
            }

            $pageVars['parameters'] = $parameters;

            // Variants
            $SQL = sqlQuery('SELECT *
                     FROM '.getTableName('products_variations_sections')."
                     WHERE id_section='".$ID."'
                     ORDER BY weight ASC");

            $variants = [];
            while ($row = sqlFetchArray($SQL)) {
                $variants[$row['id_label']] = [
                    'checked' => 1,
                    'weight' => $row['weight'],
                ];

                if (findModule(Modules::INDEXED_FILTER)) {
                    $variants[$row['id_label']] += [
                        'index_checked' => ($row['indexing'] == 'Y') ? true : false,
                        'toTitle_checked' => ($row['to_title'] == 'Y') ? true : false,
                    ];
                }

                if (findModule(Modules::CONVERTORS)) {
                    $variants[$row['id_label']] += [
                        'convertor' => $row['convertor'],
                    ];
                }
            }

            $SQL = sqlQuery('SELECT id, label
                           FROM '.getTableName('products_variations_choices_labels').'
                           WHERE 1');
            foreach ($SQL as $row) {
                $variants[$row['id']] = array_merge(getVal($row['id'], $variants, []), $row);
            }

            $pageVars['variants'] = $variants;

            // Sections
            $SQL = sqlQuery('SELECT id_topsection
                           FROM '.getTableName('sections_relation')."
                           WHERE id_section='{$ID}'");
            $sections = getVal('sections', null, []);
            foreach ($SQL as $row) {
                $sections[] = $row['id_topsection'];
            }

            $pageVars['sections'] = array_filter($sections);

            $data = &$pageVars['data'];

            if (!empty($data['photo'])) {
                $data['photo'] = getImage($this->getID(), $data['photo'], '../section/', 6, '', strtotime($data['date_updated']));
            }

            if (!empty($data['flags'])) {
                $data['flags'] = explodeFlags($data['flags']);
            }

            $data['behaviour'] = (isset($data['behaviour']) && $data['behaviour'] == 2) ? 'Y' : 'N';

            if (!empty($pageVars['data']['feed_heureka'])) {
                $pageVars['data']['feed_heureka_text'] = returnSQLResult("SELECT CONCAT(name, ' - ', category_text) FROM kupshop_shared.feed_heureka WHERE id=:id", ['id' => $pageVars['data']['feed_heureka']]);
                if (!$pageVars['data']['feed_heureka_text']) {
                    $pageVars['data']['feed_heureka'] = null;
                }
            }

            if (!empty($pageVars['data']['feed_heureka_sk'])) {
                $pageVars['data']['feed_heureka_sk_text'] = returnSQLResult("SELECT CONCAT(name, ' - ', category_text) FROM kupshop_shared.feed_heureka_sk WHERE id=:id", ['id' => $pageVars['data']['feed_heureka_sk']]);
                if (!$pageVars['data']['feed_heureka_sk_text']) {
                    $pageVars['data']['feed_heureka_sk'] = null;
                }
            }

            if (!empty($pageVars['data']['feed_google'])) {
                $pageVars['data']['feed_google_text'] = returnSQLResult("SELECT CONCAT(name, ' - ', category_text) as feed_text FROM kupshop_shared.feed_google WHERE id=:id", ['id' => $pageVars['data']['feed_google']]);

                if (!$pageVars['data']['feed_google_text']) {
                    $pageVars['data']['feed_google'] = null;
                }
            }

            if (!empty($pageVars['data']['feed_seznam'])) {
                $pageVars['data']['feed_seznam_text'] = returnSQLResult("SELECT CONCAT(name, ' - ', category_text) FROM kupshop_shared.feed_seznam WHERE id=:id", ['id' => $pageVars['data']['feed_seznam']]);
                if (!$pageVars['data']['feed_seznam_text']) {
                    $pageVars['data']['feed_seznam'] = null;
                }
            }
            if (!empty($pageVars['data']['feed_glami'])) {
                $pageVars['data']['feed_glami_text'] = returnSQLResult("SELECT CONCAT(name, ' - ', category_text) FROM kupshop_shared.feed_glami WHERE id=:id", ['id' => $pageVars['data']['feed_glami']]);
                if (!$pageVars['data']['feed_glami_text']) {
                    $pageVars['data']['feed_glami'] = null;
                }
            }
        }

        if (isset($pageVars['data']['id_block'])) {
            $pageVars['data']['blocks'] = $this->getBlocks($pageVars['data']['id_block']);
            $pageVars['data']['blocks_history'] = $this->blocksHistory->getBlocksHistory($pageVars['data']['id_block']);
        }

        if (!empty($ID)) {
            $pageVars['sectionURL'] = path('kupshop_content_redirect_redirect', $this->getShowOnWeb());
        }

        $pageVars['data']['photos'] = sqlQueryBuilder()->select('id_photo')->from('photos_sections_relation')
            ->where(Operator::equals(['id_section' => $this->getID()]))
            ->orderBy('position')->execute()->fetchAll();

        if ($this->sliders) {
            $sliders = $this->sliders->getSliderPositions(static function (Query\QueryBuilder $qb) use ($ID) {
                $qb->andWhere(Operator::equals(['id_section' => $ID]));
            });

            $pageVars['data']['sliders'] = $sliders[$ID] ?? null;
        }

        $this->unserializeCustomData($pageVars['data']);

        $vars['body'] = $pageVars;

        return $vars;
    }

    public function getData()
    {
        global $cfg;
        $data = parent::getData();

        if (getVal('Submit')) {
            $data['name'] = trim($data['name']);
            $data['name_short'] = $this->prepareNull($data['name_short']);
            if (findModule('sections_lead')) {
                $data['lead_text'] = trim($data['lead_text']);
                $data['lead_figure'] = ($data['lead_figure'] == 'Y') ? 'Y' : 'N';
                $data['lead_products'] = '';
                if ($data['lead_figure'] == 'Y' && getVal('lead_products_figure', $data) == 'Y') {
                    $data['lead_products'] = join('|', getVal('lead_products_show', $data, []));
                }
            }
            $data['behaviour'] = ($data['behaviour'] == 'Y') ? 2 : 1;

            if (isset($data['lead_products_figure'])) {
                $data['lead_products_figure'] = ($data['lead_products_figure'] == 'Y') ? 'Y' : 'N';
            }

            $data['meta_title'] = (empty($data['meta_title']) ? null : $data['meta_title']);
            $data['meta_description'] = (empty($data['meta_description']) ? null : $data['meta_description']);
            $data['meta_keywords'] = (empty($data['meta_keywords']) ? null : $data['meta_keywords']);
            $data['feed_heureka'] = (empty($data['feed_heureka']) ? null : $data['feed_heureka']);
            $data['feed_google'] = (empty($data['feed_google']) ? null : $data['feed_google']);
            $data['id_slider'] = (empty($data['id_slider']) ? null : $data['id_slider']);
            $data['url'] = trim($data['url'] ?? '', '/');
            $data['date_updated'] = (new DateTime())->format('Y-m-d H:i:s');
            $data['virtual'] = $data['virtual'] ?? 'N';

            if (!empty($cfg['Sections']['Flags'])) {
                $flags = [];
                foreach ($cfg['Sections']['Flags'] as $flag => $name) {
                    if (getVal("flags{$flag}", $data) == 'ON') {
                        $flags[] = $flag;
                    }
                }

                $data['flags'] = join(',', $flags);
            }

            $this->serializeCustomData($data);
        }

        return $data;
    }

    public function handleUpdate()
    {
        $data = $this->getData();
        $originalObject = $this->getObject();

        $uniqueUrlUtil = ServiceContainer::getService(UniqueUrlUtil::class);
        if (!empty($data['url']) && $uniqueTxt = $uniqueUrlUtil->validateUniqueUrl(UniqueUrlUtil::SECTIONS, $this->getID(), $data['url'])) {
            $this->returnError($uniqueTxt);
        }

        $SQL = parent::handleUpdate();

        $ID = $this->getID();

        if ($SQL) {
            if (findModule(Modules::PRODUCTS_SECTIONS, 'virtual_to_db')
                && (($data['virtual'] ?? false) === 'Y' || $originalObject['virtual'] !== ($data['virtual'] ?? 'N'))) {
                $this->sectionUtil->generateVirtualSections([$ID]);
            }

            // section url changed
            if ($originalObject['url'] !== null && $data['url'] != $originalObject['url']
                && findModule(Modules::DB_REWRITE)) {
                $rewrite = ServiceContainer::getService(Rewrite::class);
                $rewrite->addRewrite($originalObject['url'], Rewrite::TYPE_CATEGORY, $ID);
            }

            if ($this->getAction() == 'edit') {
                // historii je treba ulozit jeste pred ulozenim bloku
                $this->blocksHistory->saveBlocksHistory(getVal('blocks', $data, []));
            }

            $this->saveBlocks($data, $ID, 'sections');
            $this->updateBlocksPhotosPositions($ID, 'sections', 'id_section');

            if (!function_exists('mb_strcmp')) {
                function mb_strcmp($s1, $s2)
                {
                    return strcasecmp(
                        iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s1),
                        iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s2));
                }
            }

            if (!empty($_FILES['picture']['name'])) {
                $img = new Photos('section');
                $img->newImage($ID);
                $img->uploadImage($_FILES['picture'], strtolower(substr(strrchr($_FILES['picture']['name'], '.'), 0)));

                if ($img->checkFileType()) {
                    $img->insertImageIntoDB();
                } else {
                    $this->returnError(getTextString('producers', 'errorBadPhoto'));
                }

                // Clear section thumbnail
                $img->clearThumbnails([6]);

                unset($img);
            }

            // ############################################
            // # ZARAZENI DO SEKCI
            if (isset($_POST['sections'])) {
                $positions = sqlFetchAll(sqlQuery('SELECT id_topsection, position
                            FROM '.getTableName('sections_relation').'
                            WHERE id_section=:id_section',
                    ['id_section' => $ID]), 'id_topsection');

                $currentTopSection = reset($positions)['id_topsection'] ?? null;
                $childrenIds = $currentTopSection ? $this->sectionUtil->getDescendantCategories($ID) : [];

                sqlStartTransaction();

                sqlQuery('DELETE FROM '.getTableName('sections_relation')."
                                    WHERE id_section='{$ID}' ");

                foreach ($_POST['sections'] as $id_topsection) {
                    if (in_array($id_topsection, $childrenIds)) {
                        $this->returnError('Nelze zvolit jako nadřazenou sekci některou z podsekcí!');
                    }

                    if ($id_topsection) {
                        $select = 'id_topsection=:id_topsection';
                    } else {
                        $select = 'id_topsection IS NULL';
                    }
                    $selectData = [
                        'id_topsection' => ($id_topsection && $id_topsection != $ID) ? $id_topsection : null,
                        'id_section' => $ID,
                    ];

                    $position = getVal($id_topsection ?: '', $positions)['position'];

                    if (is_null($position)) {
                        $position = returnSqlResult('SELECT COUNT(*) FROM '.getTableName('sections_relation')." WHERE {$select}", $selectData);
                    }

                    $selectData['position'] = $position;
                    sqlQuery('INSERT INTO '.getTableName('sections_relation').'
                     SET id_section=:id_section, position=:position, id_topsection=:id_topsection', $selectData);
                }

                sqlFinishTransaction();
            }
            // ############################################
            // # ZARAZENI PARAMETRU DO VYHLEDAVANI
            $params = getVal('param', $data, []);
            if ($params) {
                $insertData = [];
                $deleteSectionParameters = [];
                foreach ($params as $id_parameter => $param) {
                    $insertValues = [
                        'id_parameter' => $id_parameter,
                        'id_section' => $ID,
                        'weight' => $param['weight'],
                        'filter' => ($param['use'] ?? 'N') === 'Y' ? 'Y' : 'N',
                    ];

                    if (findModule(Modules::INDEXED_FILTER)) {
                        $insertValues['indexing'] = $param['index'];
                        $insertValues['to_title'] = $param['to_title'];
                    }

                    if ($insertValues['filter'] === 'N') {
                        $deleteSectionParameters[] = $id_parameter;
                        continue;
                    }

                    $insertData[] = $insertValues;
                }

                $duplicateKeys = [
                    'weight',
                    'filter',
                ];

                if (findModule(Modules::INDEXED_FILTER)) {
                    $duplicateKeys[] = 'indexing';
                    $duplicateKeys[] = 'to_title';
                }

                if (!empty($insertData)) {
                    $insertQb = sqlQueryBuilder()
                        ->insert('parameters_sections')
                        ->onDuplicateKeyUpdate($duplicateKeys);

                    foreach ($insertData as $values) {
                        $insertQb->multiDirectValues($values);
                    }

                    $insertQb->execute();
                }

                if (!empty($deleteSectionParameters)) {
                    sqlQueryBuilder()
                        ->delete('parameters_sections')
                        ->andWhere(Operator::equals(['id_section' => $ID]))
                        ->andWhere(Operator::inIntArray($deleteSectionParameters, 'id_parameter'))
                        ->execute();
                }
            }
            // ############################################
            // # ZARAZENI JMENOVEK VARIANT DO VYHLEDAVANI
            $variants = getVal('variants', $data, []);
            if ($variants) {
                sqlQuery('DELETE FROM '.getTableName('products_variations_sections')."
                      WHERE id_section='".$ID."' ");

                foreach ($variants as $id_label => $variant) {
                    if (!empty($variant['use'])) {
                        $insertValues = [
                            'id_label' => $id_label,
                            'id_section' => $ID,
                            'weight' => $variant['weight'],
                        ];

                        if (findModule(Modules::INDEXED_FILTER)) {
                            $insertValues['indexing'] = $variant['index'];
                            $insertValues['to_title'] = $variant['to_title'];
                        }

                        if (!empty($variant['convertor'])) {
                            $insertValues['convertor'] = $variant['convertor'];
                        }

                        $this->insertSQL('products_variations_sections', $insertValues);
                    }
                }
            }
            // ############################################

            if (findModule(Modules::INDEXED_FILTER)) {
                \KupShop\IndexedFilterBundle\Util\FilterUrlDefaultValue::upgrade_filter_url('sections');
            }

            if ($this->sliders && ($sliders = getVal('sliders', $data, []))) {
                $this->saveSliders($sliders);
            }

            MenuSectionTree::invalidateCache();
        }

        return $SQL;
    }

    public function handleDelete()
    {
        if (!findRight('SEC_ERASE')) {
            redirect('launch.php?s=error.php&id=1');
        }

        $subsectionIDs = $this->getSubsectionIDs();
        $this->deleteSection($this->getID());
        if (getVal('deleteSubsections')) {
            foreach ($subsectionIDs as $subsectionID) {
                $this->deleteSection($subsectionID);
            }
        }

        parent::handleDelete();
    }

    private function deleteSection($IDsec)
    {
        $IDsecSel = getVal('IDsecSel');

        $data = $this->selectSQL('sections', ['id' => $IDsec])->fetch();
        writeDownActivity(sprintf(getTextString('sections', 'activityDeleted'), $data['name']));

        if ($IDsecSel > 0) {
            sqlQuery("UPDATE IGNORE products_in_sections SET id_section='{$IDsecSel}' WHERE id_section='{$IDsec}' ");
        } elseif ($IDsecSel == 0) {
            sqlQuery('DELETE FROM '.getTableName('products-sections')." WHERE id_section='{$IDsec}' ");
        }

        // ########################################################################
        $img = new Photos('section');
        $img->newImage($IDsec);
        $img->deletePhoto();
        unset($img);
        // ########################################################################

        sqlQuery('DELETE FROM '.getTableName('sections_relation')." WHERE id_section='".$IDsec."' ");

        $this->removeBlocks($data['id_block']);

        $this->deleteSQL('sections', ['id' => $IDsec]);

        MenuSectionTree::invalidateCache();

        return true;
    }

    private function getSubsectionIDs()
    {
        if (!($section = $this->adminSectionTree->getCategoryById($this->getID()))) {
            return [];
        }

        return $this->getSectionChildrenRecursive($section);
    }

    private function getSectionChildrenRecursive(KupShop\CatalogBundle\Entity\Section $section, ?array &$ids = null)
    {
        foreach ($section->getChildren() as $child) {
            $ids[] = $child->getId();

            $this->getSectionChildrenRecursive($child, $ids);
        }

        return $ids;
    }

    public function handleErasephoto()
    {
        $IDsec = getVal('ID');
        // sqlQuery("DELETE FROM ".getTableName("photos")." WHERE id='$IDsec'");

        // ########################################################################
        $img = new Photos('section');
        $img->newImage($IDsec);
        $img->deletePhoto();
        unset($img);
        // ########################################################################

        $this->returnOK('Logo bylo smazáno');
    }

    protected function saveSliders(array $sliders): void
    {
        $ID = (int) $this->getID();

        $slidersData = [];
        foreach ($sliders as $position => $sliderId) {
            if ($sliderId > 0) {
                $slidersData[] = [
                    'id_section' => $ID,
                    'id_slider' => $sliderId,
                    'position' => $position,
                ];
            }
        }

        sqlGetConnection()->transactional(function () use ($slidersData, $ID) {
            $this->sliders->clearSliderSections(idSection: $ID);
            $this->sliders->saveSliderPositions($slidersData, ['id_section']);
        });
    }
}
