using Hh.Mes.Common.log;
using Hh.Mes.Pojo.System;
using Hh.Mes.POJO.Entity;
using Hh.Mes.POJO.EnumEntitys;
using Hh.Mes.POJO.Response;
using Hh.Mes.POJO.ViewModel;
using Hh.Mes.Service.Repository;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Hh.Mes.Service.WebService.Base
{
    /// <summary>
    /// 模块服务
    /// </summary>
    public class SysModuleService : RepositorySqlSugar<SysModule>
    {
        public readonly List<CheckBoxItem> DefaultBtns;
        public SysModuleService()
        {
            DefaultBtns = new List<CheckBoxItem>
            {
                new CheckBoxItem
                {
                    Text="新增",
                    Value="btnAdd",
                    BtnClass="layui-btn-mini",
                    Icon="&#xe654;",
                    Sort=10
                },
                new CheckBoxItem
                {
                    Text="复制新增",
                    Value="btnCopyAdd",
                    BtnClass="layui-btn-mini",
                    Icon="&#xe630;",
                    Sort=20
                },
                new CheckBoxItem
                {
                    Text="编辑",
                    Value="btnEdit",
                    BtnClass="layui-btn-warm",
                    Icon="&#xe642;",
                    Sort=30
                },
                new CheckBoxItem
                {
                    Text="删除",
                    Value="btnDelete",
                    BtnClass="layui-btn-danger",
                    Icon="&#xe640;",
                    Sort =40
                },
                new CheckBoxItem
                {
                    Text="打印",
                    Value="btnPrint",
                    BtnClass="layui-btn-mini",
                    Icon="&#xe66d;",
                    Sort=60
                },
                new CheckBoxItem
                {
                    Text="导出",
                    Value="btnExport",
                    BtnClass="layui-btn-mini",
                    Icon="&#xe601;",
                    Sort=50
                },
            };
        }
        #region 模块操作

        /// <summary>
        /// 增加一个模块
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public dynamic Ins(SysModule model,string user="")
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response<SysModule>();
                //填充分支ID、父节点名称
                ChangeModuleCascade(model);
                var result = Context.Insertable(model).ExecuteReturnIdentity();
                if (result <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                ClearCurrentUserRedis(sysWebUser.Account);
                model.Id = result;
                response.Result = model;
                response.Message = "业务数据操作成功,请刷新首页或者退出登入后再登入!";
                return response;
            });
        }

        /// <summary>
        /// 修改一个模块
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public dynamic Upd(SysModule model)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                //填充分支ID、父节点名称
                ChangeModuleCascade(model,"update");
                var result = Context.Updateable(model).ExecuteCommand();
                if (result <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                ClearOnlineUserRedis();
                response.Result = model;
                response.Message = "业务数据操作成功,请刷新首页或者退出登入后再登入!";
                return response;
            });
        }

        /// <summary>
        /// 删除多个模块
        /// </summary>
        /// <param name="ids"></param>
        public dynamic DelById(int[] ids)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                List<int> moduleIdList = new List<int>();
                //因为可能选中的是父级的模块,那么删除的时候,就要把子模块全部删除,所以要找出所有子模块
                var cascadeIds = Context.Queryable<SysModule>().Where(t => ids.Contains(t.Id)).Select(t => t.CascadeId).ToList();
                foreach (var cascadeId in cascadeIds)
                {
                    var tempModuleIds = Context.Queryable<SysModule>().Where(t => t.CascadeId.StartsWith(cascadeId)).Select(t => t.Id).ToList();
                    moduleIdList.AddRange(tempModuleIds);
                }
                moduleIdList = moduleIdList.Distinct().ToList();

                //删除菜单
                Context.Deleteable<SysModuleElement>(t => moduleIdList.Contains(t.ModuleId.Value)).AddQueue();
                //删除模块
                Context.Deleteable<SysModule>(t => moduleIdList.Contains(t.Id)).AddQueue();
                if (ExecuteQueues(Context) <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                ClearOnlineUserRedis();
                response.Message = "业务数据操作成功,请刷新首页或者退出登入后再登入!";
                return response;
            });
        }
        #endregion

        #region 菜单操作

        /// <summary>
        /// 增加一个菜单
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public dynamic AddMenu(SysModuleElement model,string user)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                model.Class = model.Class == null ? "" : model.Class;
                model.Icon = model.Icon == null ? "" : model.Icon;
                model.CreateBy = sysWebUser?.Account;
                model.CreateTime = DateTime.Now;
                model.UpdateBy = sysWebUser?.Account;
                model.UpdateTime = DateTime.Now;
                var result = Context.Insertable(model).ExecuteCommand();
                if (result <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                ClearCurrentUserRedis(user);
                return response;
            });
        }

        /// <summary>
        /// 增加一组菜单
        /// </summary>
        /// <param name="modelList"></param>
        /// <returns></returns>
        public dynamic AddMenu(List<SysModuleElement> modelList,string user)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                foreach (var model in modelList)
                {
                    model.Class = model.Class == null ? "" : model.Class;
                    model.Icon = model.Icon == null ? "" : model.Icon;
                    model.UpdateBy = sysWebUser?.Account;
                    model.UpdateTime = DateTime.Now;
                    model.CreateBy = sysWebUser?.Account;
                    model.CreateTime = DateTime.Now;
                }
                var result = Context.Insertable(modelList).ExecuteCommand();
                if (result <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                ClearCurrentUserRedis(user);
                return response;
            });
        }

        /// <summary>
        /// 修改一个菜单
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public dynamic UpdateMenu(SysModuleElement model)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                model.Class = model.Class == null ? "" : model.Class;
                model.Icon = model.Icon == null ? "" : model.Icon;
                model.UpdateBy = sysWebUser?.Account;
                model.UpdateTime = DateTime.Now;
                var result = Context.Updateable(model).ExecuteCommand();
                if (result <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                ClearOnlineUserRedis();
                return response;
            });
        }

        /// <summary>
        /// 删除多个菜单
        /// </summary>
        /// <param name="ids"></param>
        public dynamic DelMenu(int[] ids)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                var result = Context.Deleteable<SysModuleElement>(t => ids.Contains(t.Id)).ExecuteCommand();
                if (result <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                ClearOnlineUserRedis();
                return response;
            });
        }
        #endregion

        #region 加载 用户、角色对应的模块、菜单

        /// <summary>
        /// 加载特定用户的模块
        /// TODO:这里会加载用户及用户角色的所有模块,“为用户分配模块”功能会给人一种混乱的感觉,但可以接受
        /// </summary>
        /// <param name="userId">The user unique identifier.</param>
        public dynamic LoadForUser(int userId)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                //取出用户对应的所有角色
                var roleIds = Context.Queryable<SysRelevance>()
                                     .Where(t => t.RelKey == Define.USERROLE && t.FirstId == userId)
                                     .Select(t => t.SecondId)
                                     .ToList();
                //取出 用户对应的模块、用户的角色对应的模块
                var moduleIds = Context.Queryable<SysRelevance>()
                                       .Where(t => t.RelKey == Define.USERMODULE && t.FirstId == userId ||
                                                   t.RelKey == Define.ROLEMODULE && roleIds.Contains(t.FirstId.Value))
                                       .Select(t => t.SecondId)
                                       .ToList();
                //去重
                moduleIds = moduleIds.Distinct().ToList();
                //根据模块ID找出模块
                var result = Context.Queryable<SysModule>()
                                    .Where(t => moduleIds.Contains(t.Id))
                                    .OrderBy(t => t.SortNo)
                                    .ToList();
                return result;
            });

        }

        /// <summary>
        /// 根据某用户ID获取可访问某模块的菜单项
        /// </summary>
        /// <param name="moduleId">模块id</param>
        /// <param name="userId">用户id</param>
        /// <returns></returns>
        public dynamic LoadMenusForUser(int moduleId, int userId)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                //取出用户对应的所有角色
                var roleIds = Context.Queryable<SysRelevance>()
                                     .Where(t => t.RelKey == Define.USERROLE && t.FirstId == userId)
                                     .Select(t => t.SecondId)
                                     .ToList();
                //取出 用户对应的菜单、用户角色对应的菜单
                var elementIds = Context.Queryable<SysRelevance>()
                                        .Where(t => t.RelKey == Define.USERELEMENT && t.FirstId == userId ||
                                                    t.RelKey == Define.ROLEELEMENT && roleIds.Contains(t.FirstId.Value))
                                        .Select(t => t.SecondId)
                                        .ToList();
                //根据模块ID找出菜单
                var result = Context.Queryable<SysModuleElement>()
                                    .Where(t => elementIds.Contains(t.Id) && t.ModuleId == moduleId)
                                    .ToList();
                return result;
            });
        }

        /// <summary>
        /// 加载特定角色的模块
        /// </summary>
        /// <param name="roleId">The role unique identifier.</param>
        public dynamic LoadForRole(int roleId)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                //取出角色对应的所有模块
                var elementIds = Context.Queryable<SysRelevance>()
                                        .Where(t => t.RelKey == Define.ROLEMODULE && t.FirstId == roleId)
                                        .Select(t => t.SecondId)
                                        .ToList();
                //根据模块ID找出模块
                var result = Context.Queryable<SysModule>()
                                         .Where(t => elementIds.Contains(t.Id))
                                         .OrderBy(u => u.SortNo)
                                         .ToList();
                return result;
            });
        }

        /// <summary>
        /// 加载特定角色的菜单
        /// </summary>
        /// <param name="moduleId"></param>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public dynamic LoadMenusForRole(int moduleId, int roleId)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                //取出角色对应的所有菜单
                var elementIds = Context.Queryable<SysRelevance>()
                                        .Where(t => t.RelKey == Define.ROLEELEMENT && t.FirstId == roleId)
                                        .Select(t => t.SecondId)
                                        .ToList();
                //根据模块ID找出菜单
                var result = Context.Queryable<SysModuleElement>()
                                         .Where(t => elementIds.Contains(t.Id) && t.ModuleId == moduleId)
                                         .ToList();
                return result;
            });
        }
        #endregion 

        /// <summary>
        /// 填充模块实体的节点(生成类似XXX.XXX.X.XX)、父节点名
        /// </summary>
        /// <param name="sysDept">部门</param>
        public void ChangeModuleCascade(SysModule sysModule,string flag="add")
        {
            int currentCascadeId = 1;
            //当前结点的级联节点最后一位,也就是平级的所有模块
            var query = Context.Queryable<SysModule>().Where(t => t.Id != sysModule.Id);
            //因为这里个SqlSugar的bug,如果传入的参数为null,那么生成的sql不是 xx is null 而是xx = '',所以要这么写
            if (sysModule.ParentId == null)
            {
                query.Where(t => t.ParentId == null);
            }
            else
            {
                query.Where(t => t.ParentId == sysModule.ParentId);
            }
            var sameLevels = query.ToList();
            foreach (var obj in sameLevels)
            {
                int objCascadeId = int.Parse(obj.CascadeId.TrimEnd('.').Split('.').Last());
                if (currentCascadeId <= objCascadeId) currentCascadeId = objCascadeId + 1;
            }

            if (sysModule.ParentId != null)
            {
                var parentOrg = Context.Queryable<SysModule>().First(t => t.Id == sysModule.ParentId);
                if (parentOrg != null)
                {
                    sysModule.CascadeId = parentOrg.CascadeId + currentCascadeId + ".";
                    sysModule.ParentName = parentOrg.Name;
                }
                else
                {
                    throw new Exception("未能找到该组织的父节点信息");
                }
            }
            else
            {
                sysModule.CascadeId = ".0." + currentCascadeId + ".";
                sysModule.ParentName = "根节点";
            }
            if (flag == "add")
            {
                sysModule.CreateTime = DateTime.Now;
                sysModule.CreateBy = sysWebUser.Account;
            }
            else {
                sysModule.UpdateTime = DateTime.Now;
                sysModule.UpdateBy = sysWebUser.Account;
            }
        }

        public void SaveChanageCommonBtn(int moduleId, List<string> area1, List<string> area2, List<string> area3, List<SysModuleView> modulesView)
        {
            var defaultBtnDoms = DefaultBtns.Select(x => x.Value).ToList();
            var module = modulesView.SingleOrDefault(u => u.Id == moduleId)?.Elements.Where(x => defaultBtnDoms.Contains(x.DomId)).ToList();
            var newData = new Dictionary<int, List<string>>
                {
                    { 1, area1 },
                    { 2, area2 },
                    { 3, area3 }
                };
            foreach (var item in newData)
            {
                var deleteArea = module.Where(x => !item.Value.Contains(x.DomId) && x.AreaMenus == item.Key.ToString()).Select(x => x.Id).ToList();
                DelMenu(deleteArea.ConvertAll(x => Convert.ToInt32(x)).ToArray());
                var addArea1DomIds = item.Value.Where(x => !module.Where(m => m.AreaMenus == item.Key.ToString()).Select(y => y.DomId).Contains(x)).ToList();
                var addArea1Btns = ConvertMenuBtnModel(DefaultBtns.Where(x => addArea1DomIds.Contains(x.Value)).ToList(), item.Key.ToString(), moduleId);
                AddMenu(addArea1Btns, base.sysWebUser.Account);
            }
        }

        private List<SysModuleElement> ConvertMenuBtnModel(List<CheckBoxItem> items, string area, int moduleId)
        {
            int.TryParse(area, out int areaNum);
            if (areaNum <= 0)
            {
                areaNum = 1;
            }
            var elements = items.Select(x => new SysModuleElement
            {
                AreaMenus = area,
                Name = x.Text,
                Icon = x.Icon,
                Class = x.BtnClass,
                DomId = x.Value,
                ModuleId = moduleId,
                Remark = x.Text,
                Sort = areaNum * 10 + x.Sort,
            }).ToList();
            return elements;
        }
    }
}