<?php

namespace Mnv\Models;

use Mnv\Core\Config;
use Mnv\Core\Model;
use Mnv\Core\Test\Logger;
use Mnv\Http\Request;

/**
 * Class Sections
 * @package Mnv\Models
 */
class Sections extends Model
{

    /** @var string */
    protected string $table = 'sections';

    /** @var string  */
    protected string $table_image = 'section_images';

    /** @var string  */
    protected string $primaryKey = 'sectionId';

    protected string $orderBy = 'sortOrder ASC';

    /** @var array|string[]  */
    public array $all_columns = array(
        array("id" => "sectionId",			"content" => "ID",           "default" => true, "class" => "text-center text-nowrap", 'width' => '30', 'font' => 'fw-bold'),
        array("id" => "publishedOn",	    "content" => 'Дата',         "default" => true, "class" => "text-center text-nowrap", 'width' => '80', 'font' => 'fw-semibold'),
        array("id" => "title", 		        "content" => "Название",     "default" => true, "class" => "text-start", 'font' => 'fw-bold'),
        array("id" => "sectionId",			"content" => "Раздел",       "default" => true, "class" => "text-start", 'font' => 'fw-semibold'),
        array("id" => "status", 	        "content" => "Статус",       "default" => true,"class" => "text-center", 'font' => ''),
        array("id" => "summary", 			"content" => 'Описание',     "default" => true, "class" => "text-start", 'font' => ''),
        array("id" => "image", 			    "content" => 'Картинка',     "default" => false, "class" => "text-start", 'font' => ''),
    );

    /** @var string  */
    protected string $columns = 'sectionId, parentId, sortOrder, name, alias, topMenu, fileName, url, status, typeContent, type';

    /** @var int|null  */
    public ?int $parentId = 0;

    /** @var  */
    public $images;

    /** @var */
    public $param;
    public $sectionIds = [];

    public $typeContents = [
        0 => 'Выберите тип контента',
        'courses' => 'Курсы'
    ];

    public function __construct(Request $request)
    {

        $this->id           = $request->get('id');
        $this->data         = $request->get('section');
        $this->parentId     = $request->get('parentId', 0);
        $this->param        = $request->get('param', '');
        $this->sectionIds   = $request->get('sectionIds', '');

    }

    protected function sorting()
    {
        connect()->where('parentId', $this->parentId);
    }

    /** Получение всех разделов */
    public function all($limit, $page)
    {
        /** фильтрация / сортировка */
        $this->sorting();
        return  parent::all($limit, $page);

    }

    /** Получение кол-во разделов */
    public function total(): void
    {
        /** фильтрация / сортировка */
        $this->sorting();
        parent::total();
    }

    /**
     * Проверка fileName на совпадение главной страницы
     *
     * @param string $fileName
     * @return string|null
     */
    public function isFileNamePage(string $fileName): ?string
    {
        if (!empty($this->id)) {
            connect()->where($this->primaryKey, '<>', $this->id);
        }

        if ($fileName = connect()->table($this->table)->select('fileName')->where('LOWER(fileName)', strtolower($fileName))->getValue()) {
            return $fileName;
        }

        return null;
    }
    /**
     * Проверка на совпадение `fileName` и получение `fileName`
     *
     * @param string|null $fileName
     * @return string|null
     */
    public function checkFileName(?string $fileName): ?string
    {
        if (!empty($this->id)) connect()->where($this->primaryKey,'<>', $this->id);

        if ($fileName = connect($this->table)->select('fileName')->where('parentId', $this->parentId)->where('LOWER(fileName)', strtolower($fileName))->getValue()) {
            return $fileName;
        }



        return null;
    }

    public function getParentId(): int
    {
        if (!empty($this->parentId) && !connect($this->table)->count('*', 'count')->where('parentId', $this->parentId)->getValue()) {
            $this->parentId = connect($this->table)->select('parentId')->where($this->primaryKey, $this->parentId)->getValue();
            return $this->parentId;
        }
        return 0;
    }

//    /**
//     * Проверка, существует ли у раздела подразделы или статьи
//     * @param $sectionId
//     * @param $type
//     * @return bool
//     */
//    public function isSectionType($sectionId, $type)
//    {
//        if ($type == 'plain') {
//            if (connect()->table($this->table)->select($this->primaryKey)->where('parentId', $sectionId)->getValue()) {
//                return false;
//            }
//            if (connect()->table(self::$_table_articles)->select($this->primaryKey)->where($this->primaryKey,'=', $sectionId)->getValue()) return false;
//        }
//        return true;
//    }
//    /**
//     * TODO работает / но проверить еще раз
//     * Проверка тип подраздела у основного раздела
//     * @param $parentId
//     * @return int|null
//     */
//    public function parentTypeContent($parentId)
//    {
//        if ($parentTypeContent = connect()->table($this->table)->select('typeContent, type')->where($this->primaryKey,'=', $parentId)->get()) {
//            return $parentTypeContent;
//        }
//
//        return null;
//    }

    public function prepare(array $data, int $managerId): bool
    {

        $data['modifiedBy'] = $managerId;
        $data['modifiedOn'] = gmdate('Y-m-d H:i:s');

        if (empty($this->id)) {

            $data['addedBy']    = $managerId;
            $data['addedOn']    = gmdate('Y-m-d H:i:s');
            $data['sortOrder']  = connect($this->table)->max('sortOrder')->where('parentId', $data['parentId'])->getValue() + 1;

            if ($this->id = $this->insert($data)) {
                Logger::init()->info("Добавлен новый раздел «" . $data['name'] . "»", $managerId)->save();
                return true;
            }
        } else {

            if ($this->update($data)) {
                Logger::init()->info("Раздел «" . $data['name'] . "» отредактирован", $managerId)->save();
                return true;
            }
        }

        return false;
    }


    /**
     * Проверить существует ли у этого раздела подразделы и контент
     * @param int $sectionId
     */
    /**
     * @return false
     */
    public function remove(): bool
    {
        if (!empty($this->id) && $this->data = $this->get()) {
            /* проверки, если раздел имеет подразделы */
            $this->data['hasSubsections'] = connect($this->table)->count('*', 'count')->where('parentId', $this->id)->getValue();
            /* проверки, если раздел имеет статьи */
            $this->data['hasArticles'] = connect('articles')->count('*', 'count')->where($this->primaryKey, $this->id)->getValue();

            return true;
        }

        return false;
    }
    /**
     * Удаление, удаление или перемещение подразделов и контент
     *
     * @param $param
     * @return bool
     */
    public function deleteConfirmed($param): bool
    {
        $this->data = $this->get();
        if ($this->data) {
            /** обработка контента */
            if (isset($param['moveArticlesTo'])) {
                if ($param['moveArticlesTo'] == 'delete') {
                    /** удаление контент, удаляемого раздела */
                    $this->delete_contents(['sectionId' => $this->id]);
                } else {
                    /** перемещение контент, удаляемого раздела */
                    $this->move_content($this->data['sectionId'], $param);
                }
            }

            /** обработка подразделов */
            if (isset($param['moveSubsectionsTo'])) {
                if ($param['moveSubsectionsTo'] == 'delete') {
                    /** удаление раздела и его контент */
                    $this->delete_sections($this->data['sectionId']);
                } else {
                    /** переместить подразделы  */
                    $this->reorder_section($this->data['sectionId'], $param);
                }
            }

            /** Работает удаление изображения вместе с удалением раздела удаляет из базы данных */
            connect()->table('section_images')->where($this->primaryKey, $this->id)->delete();

            /** удаление раздела */
            connect()->table($this->table)->where($this->primaryKey, $this->id)->delete();
            $this->writeSortOrders($this->parentId);

            return true;
        }

        return false;
    }

    /**
     * Перемещение подраздела(ов) в существующий раздел
     *
     * @param int $sectionId
     * @param $param
     * @return void
     */
    private function reorder_section(int $sectionId, $param): void
    {
        if ($destSectionId = connect($this->table)->select('sectionId')->where($this->primaryKey, $param['moveSubsectionsTo'])->getValue()) {
            $maxSortOrder = connect($this->table)->max('sortOrder')->where('parentId', $destSectionId)->getValue();

            connect($this->table)->where('parentId',  $sectionId)->update([
                'sortOrder' => (int)($maxSortOrder + 1),
                'parentId' => $destSectionId
            ]);

            $this->writeSortOrders($destSectionId);

            return;
        }

        if ($hasSubsections =  connect($this->table)->where('parentId', $sectionId)->getAll('array')) {
            foreach ($hasSubsections as $hasSubsection) {
                connect($this->table)->where('parentId', $hasSubsection['parentId'])->update([
                    'sortOrder' => $hasSubsection['sectionId'],
                    'parentId' => 0
                ]);
            }
        }
    }

    /**
     * Удаление разлела и его контент
     * @param int $sectionId
     * @return void
     */
    private function delete_sections(int $sectionId): void
    {
        global $SECTIONS;

        if (!empty($SECTIONS[$sectionId]['allChildren'])) {
            connect($this->table)->in($this->primaryKey, $SECTIONS[$sectionId]['allChildren'])->delete();
            connect('section_images')->in($this->primaryKey, $SECTIONS[$sectionId]['allChildren'])->delete();

            $this->delete_contents($SECTIONS[$sectionId]['allChildren']);
        }
    }

    /**
     * Сортировка разделов
     *
     * @param $ids
     * @param $sectionIds
     * @return bool
     */
    public function reorder($ids, $sectionIds): bool
    {
        foreach ($sectionIds as $i => $sectionId) {
            connect($this->table)->where($this->primaryKey, $ids[$i])->update(['sortOrder' => $sectionId]);
        }
        return true;
    }

    public function getSortOrder($parentId)
    {
        return connect($this->table)->max('sortOrder')->where('parentId', $parentId)->getValue() + 1;
    }

    /**
     * Сортировка при изменение раздела
     *
     * @param int $parentId
     */
    public function writeSortOrders(int $parentId = 0): void
    {
        $sections = connect($this->table)->select('sectionId, sortOrder')->where('parentId', $parentId)->orderBy('sortOrder')->getAll('array');
        $sortOrder = 0;
        foreach ($sections as $section) {
            $sortOrder++;
            if ((int)$section['sortOrder'] !== $sortOrder) {
                connect($this->table)->where($this->primaryKey, $section['sectionId'])->update(['sortOrder' => $sortOrder]);
            }
        }
    }
    /**
     * Удаление контента и комментарии контента
     *
     * @param $sectionIds
     */
    private function delete_contents($sectionIds): void
    {
        $articles = connect('articles')->select('articleId')->in($this->primaryKey, $sectionIds)->getAll('array');

        foreach ($articles as $article) {
            connect('articles')->where('articleId', $article['articleId'])->delete();
            connect('comments')->where('articleId', $article['articleId'])->delete();
        }
    }

    /**
     * Перемещение контента
     *
     * @param int $sectionId
     * @param $param
     */
    private function move_content(int $sectionId, $param): void
    {
        global $SECTIONS, $databaseConfig;

        connect()->query("UPDATE `" . $databaseConfig['prefix'] . 'articles' . "` 
            SET `url` = CONCAT('". $SECTIONS[$param['moveArticlesTo']]['path'] . "', '/', `fileName`, '.". Config::getValue('file_extension')."'), `sectionId` = $param[moveArticlesTo] 
            WHERE `sectionId` = '$sectionId'")->exec();
    }

    /**
     * Добавить / удалить с главного меню
     */
    public function menuSection(): bool
    {
        $topMenu = (int)connect($this->table)->select('topMenu')->where($this->primaryKey,  $this->id)->getValue();
        $sectionUpdate['topMenu'] = ($topMenu === 0) ? 1 : 0;

        if ($this->updateSectionParams($sectionUpdate)) {
            $this->result = array('data' => true, 'check' => $sectionUpdate['topMenu']);

            return true;
        }

        $this->result = array('data' => false, 'check' => false);

        return false;
    }

    /**
     * Скрыть / показать раздел
     */
    public function status(): bool
    {
        if (!empty($this->id)) {
            $oldStatus = connect($this->table)->select('status')->where($this->primaryKey, $this->id)->getValue();
            $sectionUpdate['status'] = ($oldStatus == 'V') ? 'H' : 'V';

            if ($this->updateSectionParams($sectionUpdate)) {
                $this->status = $sectionUpdate['status'];
                return  true;
            }
        }
        return false;
    }


    /**
     * @param $sectionUpdate
     * @return bool
     */
    private function updateSectionParams($sectionUpdate): bool
    {
        if (connect($this->table)->where($this->primaryKey, $this->id)->update($sectionUpdate)) {
            return true;
        }
        return false;
    }





}