<?php
/**
 * Created by PhpStorm.
 * User: qiuzijian
 * Date: 2021-04-15
 * Time: 11:08
 */

namespace Modules\Admin\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Modules\Admin\Entities\Menu;

class MenusService{
    /**
     * 添加菜单
     * @param        $menuInfo
     * @param string $key
     * @return string
     */
    public function addMenu($menuInfo, $key = 'id')
    {
        return $this->addOrEditMenu($menuInfo, $key);
    }

    /**
     * 获取菜单列表
     * @param string $show
     * @param string $category
     * @return array|mixed|string
     */
    public function getMenusList($show = '', $category = 'admin')
    {
        // 判断并获取缓存
        if (empty($show)) {
            if (Cache::has($category . 'MenusList')) {
                return Cache::get($category . 'MenusList');
            }
        } else {
            if (Cache::has($category . 'MenusShowList')) {
                return Cache::get($category . 'MenusShowList');
            }
        }

        return $this->sortMenuAndCache($show, $category);
    }

    /**
     * 排序子菜单并缓存
     * ---------------------------------
     * array_column($array,$name)
     * $array => 要查询的数组
     * $name  => 在数组中要返回的字段值
     *----------------------------------
     * array_multisort($array1,$rule,$array2)
     * $array1 => 规定数组(规定以这个数组来排序)
     * $rule   => 规定排列顺序。
     * 可能的值：
     *   SORT_ASC - 默认。按升序排列 (A-Z)。
     *   SORT_DESC - 按降序排列 (Z-A)。
     * $array2 => 要规定的数组。(要排序的数组)
     */
    public function sortMenuAndCache($show = '', $category = 'admin')
    {
        $menus = Menu::where('category', $category);
        if (!empty($show)) {
            $menus = $menus->where('show', $show);
        }
        $menus = $menus->orderBy('sort', 'desc')->get()->toArray();
        if ($menus) {
            $menuList = $this->sortMenu($menus);
            foreach ($menuList as $key => $value) {
                if ($value['child']) {
                    $sort = array_column($value['child'], 'sort');
                    array_multisort($sort, SORT_DESC, $value['child']);
                }
            }

            //缓存菜单数据
            if (!empty($show)) {
                Cache::forever($category . 'MenusShowList', $menuList);
            } else {
                Cache::forever($category . 'MenusList', $menuList);
            }
            return $menuList;
        }
        return [];
    }

    /**
     * 递归菜单数据
     * @param     $menus
     * @param int $pid
     * @return array|string
     */
    public function sortMenu($menus, $pid = 0)
    {
        $arr = [];
        if (empty($menus)) {
            return '';
        }
        $num = 0;
        foreach ($menus as $key => $value) {
            if ($value['parent_id'] == $pid) {
                $arr[$num]          = $value;
                $arr[$num]['child'] = self::sortMenu($menus, $value['id']);
                $num                += 1;
            }
        }
        return $arr;
    }

    /**
     * 递归删除菜单
     * @param $menuId
     * @return bool
     */
    public function delMenu($menuId, $category = 'admin')
    {
        $menu     = Menu::find($menuId);
        $subMenus = Menu::where('parent_id', $menuId)->get()->toArray();
        if (count($subMenus) > 0) {  // 如果有子菜单将子菜单删除
            foreach ($subMenus as $subMenu) {
                self::delMenu($subMenu['id']);
            }
        }
//        $permission = Permission::where('name', $menu['slug'])
//                                ->where('route', $menu['path'])
//                                ->where('guard_name', 'admin')->first();
//
//        if ($permission) {
//            $permission->delete();
//        }
        if ($menu) {
            $menu->delete();
        }
        $this->sortMenuAndCache(1, $category);
        $this->sortMenuAndCache('', $category);
        return true;
    }

    /**
     * 获取单个菜单信息
     * @param $menuId
     * @return bool
     */
    public function getMenuInfo($menuId)
    {
        if (!isset($menuId)) {
            return false;
        }
        return Menu::find($menuId);
    }

    /**
     * 编辑菜单
     * @param $menuInfo
     * @return bool
     */
    public function editMenu($menuInfo)
    {
        if (!isset($menuInfo['id'])) {
            return false;
        }
        if ($menuInfo['id'] == $menuInfo['parent_id']) {
            return false;
        }
        return $this->addOrEditMenu($menuInfo);
    }

    protected function addOrEditMenu($menuInfo, $key = 'id')
    {
        // 判断层级
        if ($menuInfo['parent_id'] == 0) {
            $menuInfo['tier'] = 1;
            $degree           = '';
        } else {
            $menuParent       = Menu::find($menuInfo['parent_id']);
            $menuInfo['tier'] = $menuParent->tier + 1;
            $degree           = $menuParent->degree . '|';
        }

        // 判断分类
        if (!isset($menuInfo['category'])) {
            $menuInfo['category'] = 'admin';
        }
        if (!isset($menuInfo['can_del'])) {
            $menuInfo['can_del'] = 1;
        }

        // 增加部门标识（如果为空则自动生成拼音）
        if (!isset($menuInfo['slug']) || empty($menuInfo['slug'])) {
            $cn = "/[\x{4e00}-\x{9fa5}a-zA-Z0-9\/]/u"; // 提取字母中文以及'/'
            preg_match_all($cn, $menuInfo['path'], $pathResult);
            $pathResult       = implode('', $pathResult[0]);
            $menuInfo['slug'] = lcfirst(implode(array_map(function ($item) {
                return ucfirst($item);
            }, pinyin($pathResult))));
        }

        // 更新前数据
        if (isset($menuInfo[$key]) && !empty($menuInfo[$key])) {
            $oldMenu = Menu::where($key, $menuInfo[$key])->first();
            if ($oldMenu) {
                $permissionName = $oldMenu['slug'];
            }
        } else {
            $menuHas = Menu::where('slug', $menuInfo['slug'])->first();
            if ($menuHas) {
                return 'has';
            }
            $permissionName = $menuInfo['slug'];
        }

        $menu         = Menu::updateOrCreate([$key => $menuInfo[$key] ?? ''], $menuInfo);
        $menu->degree = $degree . $menu->id;
        // 保存数据
        $menu->save();

        // 修改子树中数据，未改变层级不进行调整
        if (isset($menuInfo[$key]) && isset($oldMenu['degree']) && $oldMenu['degree'] != $menu['degree']) {  // 如果改变父级，联动改变其下属所有子集

            // 层级
            $diffTier = $oldMenu['tier'] - $menuInfo['tier'];
            // 查找子数据数组（array）
            $childMenus = Menu::where('degree', 'like', $oldMenu['degree'] . '|%')->get();
            foreach ($childMenus as $childMenu) {
                // 第一条子数据
                // 修改树路径：修改的树|更新的树|子树
                $degree = str_replace($oldMenu['degree'] . '|', $menu['degree'] . '|', $childMenu['degree']);
                // 获取详情
                $_menu = Menu::where('id', $childMenu['id'])->first();
                // 路劲数据
                $_menu->degree = $degree;
                // 层级
                $_menu->tier = $_menu->tier - $diffTier;
                // 保存
                $_menu->save();
            }
        }

        // 权限
        $permissionInfo['title']      = $menuInfo['title'];
        $permissionInfo['name']       = $menuInfo['slug'];
        $permissionInfo['route']      = $menuInfo['path'];
        $permissionInfo['guard_name'] = $menuInfo['category'];
//        Permission::updateOrCreate(['name' => $permissionName ?? ''], $permissionInfo);

        $this->sortMenuAndCache(1, $menuInfo['category']);
        $this->sortMenuAndCache('', $menuInfo['category']);

        return $menu;
    }
}