using Hotline.Share.Dtos.Knowledge;
using Hotline.Share.Enums.KnowledgeBase;
using MapsterMapper;
using SqlSugar;
using System.Collections.Generic;
using Hotline.Settings;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;

namespace Hotline.KnowledgeBase
{
    public class KnowledgeTypeDomainService : IKnowledgeTypeDomainService, IScopeDependency
    {
        /// <summary>
        /// 
        /// </summary>
        private readonly IRepository<KnowledgeType> _knowledgeTypeRepository;
        private readonly IKnowledgeRepository _knowledgeRepository;
        private readonly IMapper _mapper;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="knowledgeTypeRepository"></param>
        /// <param name="mapper"></param>
        public KnowledgeTypeDomainService(IRepository<KnowledgeType> knowledgeTypeRepository, IMapper mapper, IKnowledgeRepository knowledgeRepository)
        {
            _knowledgeTypeRepository = knowledgeTypeRepository;
            _mapper = mapper;
            _knowledgeRepository = knowledgeRepository;
        }


        /// <summary>
        /// 知识分类- 新增
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> AddType(AddKnowledgeTypeDto dto, CancellationToken cancellationToken)
        {
            var type = _mapper.Map<KnowledgeType>(dto);
            type.InitId();
            type.IsEnable = true;
            //获取分类名称全称
            string FullName = await GetFullName(type.ParentId);
            //处理全称，如果为第一级直接用全称，否则获取全称后拼接名称
            type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;
            //var id = await _knowledgeTypeRepository.AddAsync(type, cancellationToken);

            if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
            {
                //List<KnowledgeTypeOrg> orgs = _mapper.Map<List<KnowledgeTypeOrg>>(dto.TypeOrgDtos);
                //            orgs.ForEach(x => x.TypeId = type.Id);
                //            await _knowledgeTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);

                type.Orgs = dto.TypeOrgDtos.Select(d => new SystemOrganize { Id = d.OrgId }).ToList();
                await _knowledgeTypeRepository.AddNav(type)
                    .Include(d => d.Orgs)
                    .ExecuteCommandAsync();
            }
            else
            {
                await _knowledgeTypeRepository.AddAsync(type, cancellationToken);
            }
            return type.Id;
        }

        /// <summary>
        /// 知识分类- 编辑
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task UpdateType(UpdateKnowledgeTypeDto dto, CancellationToken cancellationToken)
        {
            //查询原有数据
            var type = await _knowledgeTypeRepository.GetAsync(dto.Id, cancellationToken);
            if (type is null)
                throw UserFriendlyException.SameMessage("编辑失败！");
            bool result = type.Name != dto.Name || type.ParentId != dto.ParentId;
            //是否更改分类名称或者层级
            //转换
            _mapper.Map(dto, type);
            //如果更改了名称或者修改了层级，则修改全称，未更改不修改
            if (result)
            {
                string FullName = await GetFullName(type.ParentId);//获取分类名称全称
                type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;//处理全称，如果为第一级直接用全称，否则获取全称后拼接名称
            }
            ////修改数据
            //await _knowledgeTypeRepository.UpdateAsync(type, cancellationToken);
            //如果修改了名称，对应修改子分类全称
            if (result)
                await UpdateChildNode(type.Id);
            //      await _knowledgeTypeOrgRepository.RemoveAsync(x => x.TypeId == type.Id, false, cancellationToken);
            //if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
            //      {
            //       List<KnowledgeTypeOrg> orgs = _mapper.Map<List<KnowledgeTypeOrg>>(dto.TypeOrgDtos);
            //       orgs.ForEach(x => x.TypeId = type.Id);
            //	await _knowledgeTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);
            //      }

            if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
            {
                type.Orgs = dto.TypeOrgDtos.Select(d => new SystemOrganize { Id = d.OrgId }).ToList();
                await _knowledgeTypeRepository.UpdateNav(type)
                    .Include(d => d.Orgs)
                    .ExecuteCommandAsync();
            }
            else
            {
                await _knowledgeTypeRepository.UpdateAsync(type, cancellationToken);
            }
        }

        /// <summary>
        ///  知识分类-新增、编辑初始化
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="ParentId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<KnowledgeTypeDto> InitType(string Id, string ParentId, CancellationToken cancellationToken)
        {
            KnowledgeTypeDto knowledgeTypeDto = new();
            //查询是否有数据
            if (!string.IsNullOrEmpty(Id))
            {
                var type = await _knowledgeTypeRepository.GetAsync(p => p.Id == Id && p.IsDeleted == false, cancellationToken);
                _mapper.Map(type, knowledgeTypeDto);
            }
            //查询已经启用的分类名称
            var list = await _knowledgeTypeRepository.QueryAsync(p => p.IsEnable == true && p.IsDeleted == false);
            //分类组装树形
            knowledgeTypeDto.TreeLists = GetChildren(list, Guid.Empty.ToString(), ParentId);

            return knowledgeTypeDto;
        }

        /// <summary>
        /// 知识分类-启用、禁用切换
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task ChangeStateType(string Id, CancellationToken cancellationToken)
        {
            //查询数据是否存在
            var type = await _knowledgeTypeRepository.GetAsync(p => p.Id == Id && p.IsDeleted == false, cancellationToken);
            if (type is null)
                throw UserFriendlyException.SameMessage("分类不存在！");
            if (type.IsEnable)//启用
            {
                //查询子级数据
                var getChild = await _knowledgeTypeRepository.Queryable().ToChildListAsync(it => it.ParentId, Id);//.GetChild(Id);
                //禁用子级数据
                if (getChild != null && getChild.Count > 0)
                {
                    foreach (var item in getChild)
                    {
                        item.IsEnable = false;
                    }
                    await _knowledgeTypeRepository.UpdateRangeAsync(getChild, cancellationToken);
                }
            }
            else //禁用
            {
                //查询上级是否是启用状态，如果是禁用状态不能修改
                var CheckParent = await _knowledgeTypeRepository.GetAsync(p => p.Id == type.ParentId && p.IsDeleted == false, cancellationToken);
                if (type.ParentId != Guid.Empty.ToString())
                {
                    if (CheckParent is null)
                        throw UserFriendlyException.SameMessage("分类启用失败！");
                    if (!CheckParent.IsEnable)
                        throw UserFriendlyException.SameMessage("请先启用父级分类！");
                }
                //将状态修改为启用
                type.IsEnable = true;
                await _knowledgeTypeRepository.UpdateAsync(type, cancellationToken);
            }
        }

        /// <summary>
        /// 知识分类-禁用，并且下架知识
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task ChangeStateTypeAndOffShelf(string Id, CancellationToken cancellationToken)
        {
            //查询数据是否存在
            var type = await _knowledgeTypeRepository.GetAsync(p => p.Id == Id, cancellationToken);
            if (type is null)
                throw UserFriendlyException.SameMessage("分类不存在！");
            if (type.IsEnable)//启用状态
            {
                //查询子级数据
                var getChild = await _knowledgeTypeRepository.Queryable().ToChildListAsync(it => it.ParentId, Id);// await _knowledgeTypeRepository.GetChild(Id);
                //禁用子级数据
                if (getChild != null && getChild.Count > 0)
                {
                    foreach (var item in getChild)
                    {
                        item.IsEnable = false;
                        await _knowledgeTypeRepository.UpdateAsync(item, cancellationToken);
                        //下架知识
                        //查询当前分类下的知识(查询条件：此分类下/未删除/已上架)
                        //var knowList = _knowledgeRepository.Queryable().Where(p => SqlFunc.JsonListObjectAny(p.KnowledgeType,"Key", item.Id) && p.Status == EKnowledgeStatus.OnShelf && p.IsDeleted == false).ToList();
                        var knowList = _knowledgeRepository.Queryable().Where(p => p.KnowledgeType.Any(t => t.KnowledgeId == item.Id) && p.Status == EKnowledgeStatus.OnShelf && p.IsDeleted == false).ToList();
                        if (knowList != null && knowList.Count > 0)
                        {
                            //修改知识为下架状态
                            foreach (var itemKnow in knowList)
                            {
                                itemKnow.Status = EKnowledgeStatus.OffShelf;
                                itemKnow.OffShelfTime = DateTime.Now;
                                itemKnow.OnShelfTime = null;
                            }
                            await _knowledgeRepository.UpdateRangeAsync(knowList, cancellationToken);
                        }
                    }
                }
            }
            else
                throw UserFriendlyException.SameMessage("禁用分类失败！");
        }

        /// <summary>
        /// 知识分类-删除
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveType(string Id, CancellationToken cancellationToken)
        {
            //查询数据是否存在
            var sandard = await _knowledgeTypeRepository.GetAsync(p => p.Id == Id && p.IsDeleted == false, cancellationToken);
            if (sandard is null)
                throw UserFriendlyException.SameMessage("分类不存在！");

            //查询是否有子级分类
            var checkChild = await _knowledgeTypeRepository.CountAsync(p => p.ParentId == Id && p.IsDeleted == false, cancellationToken);
            if (checkChild > 0)
                throw UserFriendlyException.SameMessage("存在子级分类！");

            //查询是否有知识分类
            //var checkKnowledge = await _knowledgeRepository.CountAsync(p => SqlFunc.JsonListObjectAny(p.KnowledgeType, "Key", Id), cancellationToken);//&& p.IsDeleted == false
            var checkKnowledge = await _knowledgeRepository.CountAsync(p => p.KnowledgeType.Any(t => t.KnowledgeId == Id), cancellationToken);//&& p.IsDeleted == false
            if (checkKnowledge > 0)
                throw UserFriendlyException.SameMessage("分类存在知识！");

            //删除操作
            await _knowledgeTypeRepository.RemoveAsync(sandard, true, cancellationToken);
        }

        #region 私有方法
        /// <summary>
        /// 查询所有子级
        /// </summary>
        /// <param name="treeDatas">分类数据</param>
        /// <param name="ID">需要查询哪级下面的分类</param>
        /// <param name="checkId">选中的数据ID</param>
        /// <returns></returns>
        private List<TreeListDto> GetChildren(List<KnowledgeType> treeDatas, string ID, string? checkId)
        {
            List<TreeListDto> nodeList = new();
            //根据ID查询子级
            var children = treeDatas.Where(q => q.ParentId == ID);
            foreach (var dr in children)
            {
                //组装数据
                TreeListDto node = new()
                {
                    name = dr.Name,
                    ParentID = dr.ParentId,
                    value = dr.Id,
                    IsEnable = dr.IsEnable
                };
                //是否选中
                if (!string.IsNullOrEmpty(checkId) && checkId != Guid.Empty.ToString() && checkId == dr.Id)
                    node.selected = true;
                //子级数据赋值
                node.children = GetChildren(treeDatas, node.value, checkId);
                //添加数据
                nodeList.Add(node);
            }
            return nodeList;
        }

        /// <summary>
        /// 查询父级名称
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        private async Task<List<string>> GetParentNode(string? Id)
        {
            List<string> list = new();
            //查询父级数据
            var type = await _knowledgeTypeRepository.GetAsync(p => p.Id == Id);
            if (type != null)
            {
                //添加名称
                list.Add(type.Name);
                list.AddRange(await GetParentNode(type.ParentId));
            }
            return list;
        }

        /// <summary>
        /// 查询子级节点数据
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        private async Task<List<KnowledgeType>> GetChildNode(string Id)
        {
            List<KnowledgeType> list = new();
            //查询数据
            var typelist = await _knowledgeTypeRepository.QueryAsync(p => p.ParentId == Id);
            if (typelist != null)
            {
                //处理数据
                foreach (var item in typelist)
                {
                    list.Add(item);
                    list.AddRange(await GetChildNode(item.Id));
                }
            }
            return list;
        }

        /// <summary>
        /// 获取全称
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        private async Task<string> GetFullName(string? Id)
        {
            //获取全部父级名称
            var list = await GetParentNode(Id);
            //倒叙
            list.Reverse();
            //拆分
            return string.Join("-", list.ToArray());
        }

        /// <summary>
        /// 修改子级分类全称
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        private async Task UpdateChildNode(string Id)
        {
            //查询子分类
            var list = await GetChildNode(Id);
            if (list is not null && list.Count > 0)
            {
                foreach (var item in list)
                {
                    //获取全称
                    string FullName = await GetFullName(item.ParentId);
                    item.SpliceName = string.IsNullOrEmpty(FullName) ? item.Name : FullName + "-" + item.Name;
                    //修改全称
                    await _knowledgeTypeRepository.UpdateAsync(item);
                }
            }
        }
        #endregion

    }
}
