<?php

namespace Mnv\Core;

if (!defined('MNV_CMS')) {
    die('Hacking attempt!');
}

use Mnv\Core\Auth\Administration;
use Mnv\Core\Auth\Exceptions\UnknownIdException;

use Mnv\Models\Comments;
use Mnv\Models\Users\UserGroups;
use Mnv\Models\Users\UserTypes;

/**
 * Class AdminMnv
 * @package Mnv\Core
 */
abstract class AdminMnv extends Mnv
{
    /** @var $managers */
    protected $manager;

    /** @var array|mixed */
    private $menu = array();

    public string $adminUrl = '/admin';

    public $totalPendingComments = 0;
    public $pendingComments;


    /** Mnv constructor. */
    public function __construct()
    {
        global $LANGUAGES;

        parent::__construct();

        try {
            $auth = new Administration(UserInfo::get_ip(), true, 60 * 5);
            try {
                $file = fs_file_get_contents(GLOBAL_ROOT . "/admin/menu/menu.json", "r");
                try {
                    $this->menu = json_decode($file, true, 512, JSON_THROW_ON_ERROR);
                } catch (\JsonException $e) {
                    $this->smarty->assign('error',  $e->getMessage());
                }
            } catch (\Exception $e) {
                $this->smarty->assign('error',  $e->getMessage());
            }

            if (!empty(SITE_LANG)) {
                $this->adminUrl = '/admin/' . SITE_LANG;
            }

            try {
                if ($auth->check() && $auth->doesUserHaveRole($auth->getUserId(), UserGroups::arrayGroup())) {
//                    $this->manager = $auth->adminManager(0);
                    $this->manager = $auth->adminManager($auth->getUserId());

                    /** получить количество ожидающих комментариев и сами комментарии для   */
                    if (Config::getValue('comments_enabled')) {
                        $this->pendingComments = Comments::getPendingComments();
                        $this->totalPendingComments = Comments::totalPendingComments();
                    }

                    /** определение языка по умолчанию */
                    if (!is_null($LANGUAGES)) {
                        foreach ($LANGUAGES as $codename => $tmpLang) {
                            $LANGUAGES[$codename] = $tmpLang;
                            $LANGUAGES[$codename]['languageTransName'] = lang('languageList:'. $codename);
                            if ($tmpLang['isDefault'])
                                $this->smarty->assign('DEFAULT_LANG', $codename);
                        }
                    }
                } else {
                    $auth->logOut();
                }
            } catch (UnknownIdException $e) {
                $auth->logOut();
            }

            if (!$auth->isLoggedIn() || !$auth->hasAnyRole(UserGroups::arrayGroup())) {
                redirect($this->adminUrl . '/auth');
            }

            $this->smarty->assign('module', $this->module);
            $this->smarty->assign('menu', $this->getMenu($this->menu));

            /** Максимальный размер загружаемого файла */
            $this->smarty->assign('upload_max_filesize',  $this->upload_max_filesize());
            /** default admin url */
            $this->smarty->assign('adminUrl',  $this->adminUrl);
            $this->smarty->assign('adminManager', $this->manager);
            $this->smarty->assign('totalPendingComments', $this->totalPendingComments);
            $this->smarty->assign('pendingComments', $this->pendingComments);
            /** statuses */
            $this->smarty->assign('statuses', lang('general:statuses'));



        }
        catch (Database\Throwable\IntegrityConstraintViolationException | Auth\Errors\AuthError $e) {
            $this->smarty->assign('error',  $e->getMessage());
        }

//        print_r(connect()->queryCount()."\n");
    }


    protected function upload_max_filesize(): string
    {
        $max_upload = str_replace( array ('M', 'm' ), '', @ini_get( 'upload_max_filesize' ) );
        return formatsize( $max_upload * 1024 * 1024 );
    }


    /**
     * Access rights
     *
     * @param string|null $module
     * @return bool
     */
    protected function permissions(?string $module): bool
    {
        if (empty($module)) return false;

        if (empty($this->manager['permissions'])) return false;

        return in_array($module, $this->manager['permissions'], true) && in_array($this->manager['accessLevel'], UserGroups::arrayGroup(), true);
    }



    /**
     * Group access rights
     *
     * @return array
     */
    protected function accessRights(): array
    {
        $result = array();
        foreach ($this->menu as $key => $item) {
            $result[$key] = $item;
            $child = array();
            if (isset($item['children'])) {
                foreach ($result[$key]['children'] as $childrenKey => $children) {
                    $child[$childrenKey] = $children;
                }

                unset($result[$key]['children']);

                $result[$key]['children'] = $child;
            }
        }

        return $result;
    }

    /** Формирование меню и получение меню админ панели */
    private function getMenu(array $menu): array
    {
        // проверяем на пустоту прав, так как у пользователя сайта нет разрешение на доступ к админ панели
        if (!empty($this->manager['permissions'])) {
            foreach ($menu as $key => &$item) {
                if (isset($item['children'])) {
                    $item['children'] = $this->generateChildrenMenu($item['children']);
                    if ($this->manager['userType'] == UserTypes::DEVELOPER) {
                        if (in_array('managers', $item['activeItems'], true)) {
                            $developer[] = ['name' => 'Разработчики', 'fileName' => 'developers'];
                            $menu[$key]['children'] = array_merge($developer, $item['children']);
                            $menu[$key]['activeItems'] = array_merge($item['activeItems'], ['developers']);
                        }
                        if (in_array('contents', $item['activeItems'], true)) {
                            $settings_content[] = ['name' => 'Настройки контента', 'fileName' => 'typecontents'];
                            $menu[$key]['children'] = array_merge($settings_content, $item['children']);
                            $menu[$key]['activeItems'] = array_merge($item['activeItems'], ['typecontents']);
                        }
                    }
                    if (empty($item['children'])) {
                        unset($menu[$key]);
                    }
                }
            }
            // добавление документации для разработчиков
            if ($this->manager['userType'] == UserTypes::DEVELOPER) {
                $lastKey = array_key_last($menu) + 1;
                $menu[$lastKey]['activeItems'] = ["collection", "database"];
                $menu[$lastKey]['name'] = 'Документация';
                $menu[$lastKey]['icon'] = 'ph-question';
                $menu[$lastKey]['children'] = [
                    ['name' => 'Collection', 'fileName' => 'collection'],
                    ['name' => 'Database', 'fileName' => 'database']
                ];
            }

        }  else {
            foreach ($menu as $key => $item) {
                if (isset($item['children'])) {
                    $menu[$key]['children'] = $this->generateChildrenMenu($item['children']);
                }
            }
        }

        return $menu;
    }

    /**
     * @param $children
     * @return mixed
     */
    private function generateChildrenMenu($children)
    {
        if (!empty($this->manager['permissions'])) {
            foreach ($children as $k => $child) {
                if ($this->access($child['fileName'], $this->manager['permissions'])) {
                    continue;
                }

                unset($children[$k]);
            }
        } else {
            foreach ($children as $k => $child) {
                $children[$k] = $child;
            }
        }

        return $children;
    }

    /**
     * Проверяем разрешение на доступ к контроллеру
     *
     * @param string|null $fileName
     * @param array $permissions
     * @return bool
     */
    private function access(?string $fileName, array $permissions): bool
    {
        if (empty($fileName)) {
            return false;
        }

        if (is_array($permissions)) {
            return in_array($fileName, $permissions, true);
        }


        return false;
    }

}