using System.Linq;
using System.Threading.Tasks;
using Abp.Domain.Repositories;
using Abp.EntityFrameworkCore.Repositories;
using Abp.UI;
using Microsoft.EntityFrameworkCore;
using YGNT.QuestionLibrary.Core.KnowledgePoints.Cache;
using Z.EntityFramework.Plus;

namespace YGNT.QuestionLibrary.Core.KnowledgePoints.Domain
{
    public class KnowledgePointManager : IKnowledgePointManager
    {
        private readonly IRepository<KnowledgePointTreePath, long> _treePathRepository;
        private readonly IRepository<KnowledgePoint, long> _knowledgePointRepository;
        private readonly IKnowledgePointTreePathManager _treePathManager;
        private readonly IKnowledgePointCache _knowledgePointCache;


        public KnowledgePointManager(IRepository<KnowledgePointTreePath, long> treePathRepository, IKnowledgePointTreePathManager treePathManager, IRepository<KnowledgePoint, long> knowledgePointRepository, IKnowledgePointCache knowledgePointCache)
        {
            _treePathRepository = treePathRepository;
            _treePathManager = treePathManager;
            _knowledgePointRepository = knowledgePointRepository;
            _knowledgePointCache = knowledgePointCache;
        }

        /// <summary>
        /// 移动知识点节点
        /// </summary>
        /// <param name="source">要移动的知识点</param>
        /// <param name="targetParent">目标知识点(P)</param>
        /// <returns></returns>
        public async Task MoveToAsync(KnowledgePoint source, KnowledgePoint targetParent)
        {
            if (source.DisciplineId != targetParent.DisciplineId)
                throw new UserFriendlyException("目标知识点所属学科和当前知识点学科不匹配!");

            var isChildTarget = await _treePathRepository.GetAll()
                 .Where(x => x.Ancestor == source.Id)
                 .AnyAsync(x => x.Descendant == targetParent.Id);
            if (isChildTarget)
                throw new UserFriendlyException("不能移动到子节点下");

            source.ParentId = targetParent.Id;
            var ancQueryable = _treePathRepository.GetAll()
                .Where(x => x.Descendant == source.Id)
                .Where(x => x.Ancestor != source.Id)
                .Select(x => x.Ancestor);
            var desQueryable = _treePathRepository.GetAll()
                .Where(x => x.Ancestor == source.Id)
                .Select(x => x.Descendant);

            //删除过去的父节点信息
            await _treePathRepository.GetAll()
                .Where(x => ancQueryable.Contains(x.Ancestor))
                .Where(x => desQueryable.Contains(x.Descendant))
                .DeleteAsync();


            var anc = await _treePathRepository.GetAll()
                .Where(x => x.Descendant == source.ParentId)
                .ToListAsync();

            var des = await _treePathRepository.GetAll()
                .Where(x => x.Ancestor == source.Id)
                .ToListAsync();

            foreach (var treePath in anc)
            {
                foreach (var desTreePath in des)
                {
                    await _treePathRepository.InsertAsync(new KnowledgePointTreePath()
                    {
                        Ancestor = treePath.Ancestor,
                        Descendant = desTreePath.Descendant,
                        Depth = treePath.Depth + desTreePath.Depth + 1
                    });
                }
            }
            var lastSort = await _knowledgePointRepository.Query(s => s
                .Where(x => x.ParentId == targetParent.Id)
                .Select(x => x.Sort)
                .OrderByDescending(x => x)
                .FirstOrDefaultAsync());
            source.ParentId = targetParent.Id;
            source.Sort = lastSort + 1;
        }

        /// <summary>
        /// 检查知识点名称是否被占用
        /// </summary>
        /// <param name="name"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        public async Task CheckNameAsync(string name, long? parentId)
        {
            var isExist = await _knowledgePointRepository.GetAll()
                .Where(x => x.ParentId == parentId)
                .Where(x => x.Name == name)
                .AnyAsync();
            if (isExist)
                throw new UserFriendlyException($"知识点名称:{name}已被占用.");
        }
    }
}