<?php

namespace app\controller\manager;

use app\repository\CmsRepository;
use app\model\Log;
use app\model\Menu as MenuModel;

use app\validate\MenuValidate;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\facade\Db;
use think\response\Json;
use think\response\View;

/**
 * 菜单管理
 *
 * Class Menu
 * @package app\controller\manager
 */
class Menu extends Base
{

    /**
     * 删除
     *
     * @return Json
     */
    public function del(): Json
    {
        if ($this->request->isPost()) {
            $ids = input('post.ids/a', []);
            if (empty($ids)) {
                $ids[] = input('post.id/d');
            }
            $repo = CmsRepository::getInstance();
            if ($repo->hasChildrenMenuByIds($ids)) {
                return $this->json(4002, '待删除数据存在子数据');
            }
            $repo->delMenuByIds($ids);
            Log::write('menuDel', 'del', '删除了菜单，涉及到的ID为：'.implode(',', $ids));
            return $this->json();
        }
        return $this->json(4001, '非法请求!');
    }

    /**
     * 规则
     *
     * @return string[]
     */
    private function rule(): array
    {
        return [
            'pid|父级菜单'    => 'require|number',
            'title|标题'    => 'require|max:100',
            'name|路由标识'   => 'require',
            'remark|备注信息' => 'max:255',
        ];
    }


    /**
     * 编辑
     *
     * @return Json|View
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @throws Exception
     */
    public function edit()
    {
        $id = input('id/d', 0);

        if (!$info = MenuModel::findById($id)) {
            return $this->json(4001, '记录不存在');
        }

        if ($this->request->isPost()) {
            $item     = input('post.');
            $validate = $this->validateByApi($item, $this->rule());
            if ($validate !== true) {
                return $validate;
            }

            try {
                $oldPath      = $info['path'];
                $item['path'] = MenuModel::getPath($item['pid']);
                $info->save($item);

                //刷新所有路径
                $oldPath = $oldPath.','.$id;
                $newPath = $item['path'].','.$id;
                if ($oldPath != $newPath) {
                    MenuModel::refreshPath();
                }
                return $this->json();
            } catch (ValidateException $e) {
                return $this->json(4001, $e->getError());
            }
        }

        $disabled               = MenuModel::getAllChildrenIds($id);
        $disabled[]             = $id;
        $this->data['menuList'] = $this->menuJson([$info['pid']], $disabled);
        $this->data['item']     = $info;

        return $this->view();
    }

    /**
     * 单个字段编辑
     *
     * @return Json
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function modify(): Json
    {
        if ($this->request->isPost()) {
            $item     = input('post.');
            $validate = new MenuValidate();
            if (!$validate->scene('menu_modify')->check($item)) {
                return $this->json(4002, $validate->getError());
            }

            if (!$info = MenuModel::findById($item['id'])) {
                return $this->json(4001, '记录不存在');
            }

            $update = [$item['field'] => $item['value']];

            try {
                $info->save($update);
                return $this->json();
            } catch (ValidateException $e) {
                return $this->json(4001, $e->getError());
            }
        }
        return $this->json(4000, '非法请求');
    }

    /**
     * 添加
     *
     * @return Json|View
     * @throws Exception
     */
    public function add()
    {
        $id = input('id/d', 0);

        if ($this->request->isPost()) {
            $item     = input('post.');
            $validate = $this->validateByApi($item, $this->rule());
            if ($validate !== true) {
                return $validate;
            }
            try {
                $item['path'] = MenuModel::getPath($item['pid']);
                MenuModel::create($item);
                return $this->json();
            } catch (ValidateException $e) {
                return $this->json(4001, $e->getError());
            }
        }

        $selected               = $id > 0 ? [$id] : [];
        $this->data['menuList'] = $this->menuJson($selected);

        return $this->view();
    }

    /**
     * 常规权限生成
     *
     * @return Json|View
     * @throws Exception
     */
    public function generate()
    {
        $id = input('id/d', 0);

        if ($this->request->isPost()) {
            $id = input('id/d', 0);
            if (!$item = MenuModel::findById($id)) {
                return $this->json(4002, '记录不存在');
            }

            if ($item['type'] != MenuModel::TYPE_MENU) {
                return $this->json(4003, '仅菜单类型可操作');
            }

            Db::startTrans();
            try {
                //自动生成常规操作
                MenuModel::generate($id, $item['name'], $item['path']);
                Db::commit();
                return $this->json();
            } catch (ValidateException $e) {
                Db::rollback();
                return $this->json(4001, $e->getError());
            }
        }

        $selected               = $id > 0 ? [$id] : [];
        $this->data['menuList'] = $this->menuJson($selected);

        return $this->view();
    }

    /**
     * 列表
     *
     * @return View|Json
     */
    public function index()
    {
        if ($this->request->isPost()) {
            $menus = CmsRepository::getInstance()->getMenuList();
            $menus->each(function ($item) {
                if ($item['type'] == 'menu') {
                    $item->open = false;
                }
            });
            $res = [
                'code'  => 0,
                'msg'   => 'success',
                'count' => $menus->count(),
                'data'  => $menus->toArray(),
            ];
            return json($res);
        }
        return $this->view();
    }

    /**
     * xmSelect插件 json数据
     *
     * @param  array  $selected
     * @param  array  $disabled
     * @return false|string
     */
    private function menuJson(array $selected = [], array $disabled = [])
    {
        $categoryList[] = ['title' => '顶级菜单', 'id' => 0, 'prefix' => '', 'disabled' => false, 'open' => true, 'selected' => in_array(0, $selected)];
        $menus          = CmsRepository::getInstance()->getMenuList();
        $menus          = $menus->toArray();
        foreach ($menus as $k => $m) {
            $menus[$k]['selected'] = in_array($m['id'], $selected);
            $menus[$k]['disabled'] = in_array($m['id'], $disabled);
        }
        $menus        = CmsRepository::getInstance()->buildMenuChild(0, $menus);
        $categoryList = array_merge($categoryList, CmsRepository::getInstance()->handleSelectedList($menus));
        return json_encode($categoryList, JSON_UNESCAPED_UNICODE);
    }
}