using IRaCIS.Application.Contracts;
using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace IRaCIS.Application.Services
{
    [ApiExplorerSettings(GroupName = "Management")]
    public class MenuService : BaseService, IMenuService
    {
        private readonly IRepository<Menu> menuRepository;
        private readonly IRepository<UserTypeMenu> _userTypeMenuRepository;

        public MenuService(IRepository<Menu> menuRepository, IRepository<UserTypeMenu> userTypeMenuRepository)
        {
            this.menuRepository = menuRepository;
            this._userTypeMenuRepository = userTypeMenuRepository;
        }

        /// <summary>
        /// 添加菜单  New
        /// </summary>
        /// <param name="menuAddOrUpdateModel"></param>
        /// <returns></returns>
        public async Task<IResponseOutput> AddOrUpdateMenu(MenuCommand menuAddOrUpdateModel)
        {
            var exp = new EntityVerifyExp<Menu>()
            {
                VerifyExp = u => u.ParentId == menuAddOrUpdateModel.ParentId && u.MenuName == menuAddOrUpdateModel.MenuName,
                VerifyMsg = "该父节点下已经存在同名的子节点。"
            };

            var menu = await _repository.InsertOrUpdateAsync<Menu, MenuCommand>(menuAddOrUpdateModel, true, exp);

            return ResponseOutput.Ok(menu.Id.ToString());

            #region 废弃前

            //if (menuAddOrUpdateModel.Id == null)
            //{
            //    bool exist = _menuFunctionRepository.Any(u => u.ParentId == menuAddOrUpdateModel.ParentId && u.MenuName == menuAddOrUpdateModel.MenuName);
            //    if (exist)
            //    {
            //        return ResponseOutput.NotOk("A son node with the same name already existed under this parent node.");
            //    }

            //    if (!string.IsNullOrWhiteSpace(menuAddOrUpdateModel.FunctionName))
            //    {
            //        menuAddOrUpdateModel.IsFunction = true;
            //    }

            //    var result = _menuFunctionRepository.Add(_mapper.Map<MenuFunction>(menuAddOrUpdateModel));

            //    if (_menuFunctionRepository.SaveChanges())
            //    {
            //        return ResponseOutput.Ok(result.Id.ToString());
            //    }
            //    return ResponseOutput.NotOk();
            //}
            //else
            //{
            //    var menuUpdateModel = menuAddOrUpdateModel;
            //    bool exist = _menuFunctionRepository.Any(u => u.ParentId == menuUpdateModel.ParentId &&
            //    u.MenuName == menuUpdateModel.MenuName && u.Id != menuUpdateModel.Id);
            //    if (exist)
            //    {
            //        return ResponseOutput.NotOk("A son node with the same name already existed under this parent node.");
            //    }
            //    var updateModel = _mapper.Map<MenuFunction>(menuUpdateModel);

            //    if (!string.IsNullOrWhiteSpace(updateModel.FunctionName))
            //    {
            //        updateModel.IsFunction = true;
            //    }
            //    _menuFunctionRepository.Update(updateModel);

            //    var success = _menuFunctionRepository.SaveChanges();
            //    return ResponseOutput.Result(success);
            //}
            #endregion

        }

        /// <summary>
        /// 删除菜单  已验证 父节点不允许删除  New
        /// </summary>
        /// <param name="menuId"></param>
        /// <returns></returns>
        [HttpDelete("{menuId:guid}")]
        public async Task<IResponseOutput> DeleteMenu(Guid menuId)
        {
            if (await menuRepository.AnyAsync(t => t.ParentId == menuId))
            {
                return ResponseOutput.NotOk("该节点存在子节点，请在删除子节点后，再删除该节点。");
            }

            var success =await menuRepository.BatchDeleteNoTrackingAsync(u => u.Id == menuId);

            return ResponseOutput.Result(success);
        }


        /// <summary>
        /// 所有的菜单树 包括禁用的  New 
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<List<MenuTreeNode>> GetMenuTree()
        {
            var allMenuList = (await menuRepository.ProjectTo<MenuTreeNode>(_mapper.ConfigurationProvider).ToListAsync()).IfNullThrowException();

            var list = allMenuList.ToTree((root, child) => child.ParentId == Guid.Empty,
             (root, child) => child.ParentId == root.MenuId,
             (child, datalist) =>
             {
                 child.Children ??= new List<MenuTreeNode>();
                 child.Children.AddRange(datalist);
             }, item => item.ShowOrder);

            return list;
        }

        /// <summary>
        ///  菜单列表   参数都是可传的 根据需要传递  New
        /// </summary>
        /// <param name="menuQueyDTO"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<MenuDTO>> GetMenuList(MenuQueyDTO menuQueyDTO)
        {
            return await menuRepository
                  .WhereIf(menuQueyDTO.ParentId != null, t => t.ParentId == menuQueyDTO.ParentId)
                  .WhereIf(menuQueyDTO.IsEnable != null, t => t.IsEnable == menuQueyDTO.IsEnable)
                  .WhereIf(menuQueyDTO.IsCache != null, t => t.IsCache == menuQueyDTO.IsCache)
                  .WhereIf(menuQueyDTO.IsDisplay != null, t => t.IsDisplay == menuQueyDTO.IsDisplay)
                  .WhereIf(menuQueyDTO.IsExternalLink != null, t => t.IsExternalLink == menuQueyDTO.IsExternalLink)
                  .WhereIf(menuQueyDTO.IsInTabDisplay != null, t => t.IsInTabDisplay == menuQueyDTO.IsInTabDisplay)
                  .WhereIf(menuQueyDTO.MenuType != null, t => t.MenuType == menuQueyDTO.MenuType)

                  .ProjectTo<MenuDTO>(_mapper.ConfigurationProvider).OrderBy(t=>t.ShowOrder).ToListAsync();
        }


        /// <summary>
        /// 获取某用户类型（角色） 菜单树 勾选情况   New
        /// </summary>
        /// <param name="userTypeId"></param>
        /// <returns></returns>
        [HttpGet("{userTypeId:guid}")]
        public async Task<List<MenuTreeNodeSelect>> GetUserTypeMenuTree(Guid userTypeId)
        {
            var menuFunctionlist = (await menuRepository
                   .ProjectTo<MenuTreeNodeSelect>(_mapper.ConfigurationProvider, new { userTypeId = userTypeId }).ToListAsync()).IfNullThrowException();


            var list = menuFunctionlist.ToTree((root, child) => child.ParentId == Guid.Empty,
            (root, child) => child.ParentId == root.MenuId,
            (child, datalist) =>
            {
                child.Children ??= new List<MenuTreeNodeSelect>();
                child.Children.AddRange(datalist);
            }, item => item.ShowOrder);

            return list;

        }

        [AllowAnonymous]
        public async Task<List<MenuTreeNode>> GetUserMenuTree()
        {

            var menuFunctionlist = await _userTypeMenuRepository
                .Where(t => t.UserTypeId == _userInfo.UserTypeId && (t.Menu.MenuType == "M" || t.Menu.MenuType == "C") && t.Menu.IsEnable)
                .ProjectTo<MenuTreeNode>(_mapper.ConfigurationProvider).ToListAsync();

            var list = menuFunctionlist.ToTree((root, child) => child.ParentId == Guid.Empty,
            (root, child) => child.ParentId == root.MenuId,
            (child, datalist) =>
            {
                child.Children ??= new List<MenuTreeNode>();
                child.Children.AddRange(datalist);
            }, item => item.ShowOrder);

            return list;
        }

        [AllowAnonymous]
        public async Task<List<string>> GetUserPermissions()
        {

            var list = await _userTypeMenuRepository
                   .Where(t => t.UserTypeId == _userInfo.UserTypeId && t.Menu.MenuType == "F")
                   .Select(t => t.Menu.PermissionStr).ToListAsync();

            //var str = await _repository.Where<UserType>(t => t.Id == _userInfo.UserTypeId).Select(t => t.PermissionStr).FirstOrDefaultAsync();


            list.Add(_userInfo.PermissionStr);

            return list;

        }



        #region  废弃 生成树废弃前




        //public List<MenuTreeNode> GetMenuFunction()
        //{
        //    var allMenuList = _menuFunctionRepository.ProjectTo<MenuFunctionDTO>(_mapper.ConfigurationProvider).ToList();

        //    return GetTreeList(Guid.Empty, allMenuList);
        //}

        ///// <summary>
        ///// 根据父节点ID递归生成树
        ///// </summary>
        ///// <param name="parentId"></param>
        ///// <param name="allMenuList"></param>
        ///// <returns></returns>
        //[NonDynamicMethod]
        //public List<MenuTreeNode> GetTreeList(Guid? parentId, List<MenuFunctionDTO> allMenuList)
        //{
        //    //树节点集合  每个节点包含一个菜单项  和一个子菜单集合
        //    List<MenuTreeNode> treeList = new List<MenuTreeNode>();

        //    // 根据父菜单节点获取子菜单节点  并且进行排序
        //    List<MenuFunctionDTO> menuList = allMenuList.Where(x => x.ParentId == parentId).OrderBy(t => t.ShowOrder).ToList();

        //    foreach (var menuItem in menuList)
        //    {
        //        MenuTreeNode treeItem = new MenuTreeNode()
        //        {
        //            Id = menuItem.Id,
        //            ParentId = menuItem.ParentId,
        //            RouteName = menuItem.RouteName,
        //            MenuName = menuItem.MenuName,
        //            Path = menuItem.Path,
        //            Hidden = menuItem.Hidden,
        //            Component = menuItem.Component,
        //            FunctionName = menuItem.FunctionName,
        //            IsFunction = menuItem.IsFunction,
        //            MetaActiveMenu = menuItem.MetaActiveMenu,
        //            MetaBreadcrumb = menuItem.MetaBreadcrumb,
        //            MetaIcon = menuItem.MetaIcon,
        //            MetaTitle = menuItem.MetaTitle,
        //            Redirect = menuItem.Redirect,
        //            ShowOrder = menuItem.ShowOrder,
        //            Note = menuItem.Note,
        //            Status = menuItem.Status,

        //            Children = GetTreeList(menuItem.Id, allMenuList)
        //        };

        //        treeList.Add(treeItem);
        //    }
        //    return treeList;
        //}


        ///// <summary>
        ///// 获取某角色 菜单树 勾选情况 和 功能勾选情况
        ///// </summary>
        ///// <param name="roleId"></param>
        ///// <returns></returns>
        //[HttpGet("{roleId:guid}")]
        //public List<MenuTreeNodeSelect> GetRoleMenuFunction(Guid roleId)
        //{



        //    var menuFuncQuery = from function in _menuFunctionRepository.Where(u => !u.IsFunction)
        //                        join roleMenuFunctionItem in _roleMenuFunctionRepository.AsQueryable()
        //                        .Where(t => t.UserTypeId == roleId)
        //                        on function.Id equals roleMenuFunctionItem.MenuFunctionId into t
        //                        from roleFunction in t.DefaultIfEmpty()
        //                        select new MenuTreeNodeSelect()
        //                        {
        //                            IsSelect = roleFunction != null,
        //                            ShowOrder = function.ShowOrder,
        //                            MenuName = function.MenuName,
        //                            Note = function.Note,
        //                            FunctionName = function.FunctionName,
        //                            ParentId = function.ParentId,
        //                            Id = function.Id,
        //                        };
        //    var list = menuFuncQuery.ToList();

        //    return GetSelectTreeList(Guid.Empty, list);
        //}

        //[NonDynamicMethod]
        //private List<MenuTreeNodeSelect> GetSelectTreeList(Guid parentId, List<MenuTreeNodeSelect> allMenuList)
        //{
        //    List<MenuTreeNodeSelect> TreeList = new List<MenuTreeNodeSelect>();
        //    List<MenuTreeNodeSelect> menuList = allMenuList.Where(x => x.ParentId == parentId).OrderBy(t => t.ShowOrder).ToList();

        //    foreach (var menuItem in menuList)
        //    {
        //        MenuTreeNodeSelect treeItem = new MenuTreeNodeSelect()
        //        {
        //            Id = menuItem.Id,
        //            ParentId = menuItem.ParentId,
        //            RouteName = menuItem.RouteName,
        //            MenuName = menuItem.MenuName,
        //            Note = menuItem.Note,
        //            IsSelect = menuItem.IsSelect,
        //            ShowOrder = menuItem.ShowOrder,
        //            Children = GetSelectTreeList(menuItem.Id, allMenuList)
        //        };

        //        TreeList.Add(treeItem);
        //    }
        //    return TreeList;
        //}

        //[NonDynamicMethod]
        //private List<MenuTreeNode> GetTreeList(Guid? parentId, List<MenuTreeNode> allMenuList)
        //{
        //    List<MenuTreeNode> TreeList = new List<MenuTreeNode>();
        //    List<MenuTreeNode> menuList = allMenuList.Where(x => x.ParentId == parentId).OrderBy(t => t.ShowOrder).ToList();

        //    foreach (var menuItem in menuList)
        //    {
        //        MenuTreeNode treeItem = new MenuTreeNode()
        //        {
        //            Id = menuItem.Id,
        //            ParentId = menuItem.ParentId,
        //            RouteName = menuItem.RouteName,
        //            MenuName = menuItem.MenuName,
        //            Path = menuItem.Path,
        //            Hidden = menuItem.Hidden,
        //            Component = menuItem.Component,
        //            FunctionName = menuItem.FunctionName,
        //            IsFunction = menuItem.IsFunction,
        //            MetaActiveMenu = menuItem.MetaActiveMenu,
        //            MetaBreadcrumb = menuItem.MetaBreadcrumb,
        //            MetaIcon = menuItem.MetaIcon,
        //            MetaTitle = menuItem.MetaTitle,
        //            Redirect = menuItem.Redirect,
        //            ShowOrder = menuItem.ShowOrder,
        //            Note = menuItem.Note,
        //            Status = menuItem.Status,

        //            Children = GetTreeList(menuItem.Id, allMenuList)
        //        };

        //        TreeList.Add(treeItem);
        //    }
        //    return TreeList;
        //}

        #endregion



    }
}
