using System.Linq;
using System.Threading.Tasks;
using Abp.Domain.Repositories;
using Abp.UI;
using Microsoft.EntityFrameworkCore;
using YGNT.Infrastructure.Model;
using YGNT.QuestionLibrary.Core.BaseData.Enum;
using YGNT.QuestionLibrary.Core.Disciplines;
using YGNT.QuestionLibrary.Core.Models;
using YGNT.QuestionLibrary.Core.Questions;

namespace YGNT.QuestionLibrary.Core.BaseData.Domain
{
    public class QuestionTypeManager : IQuestionTypeManager
    {
        private readonly IRepository<QuestionType> _repository;
        private readonly IRepository<Question, long> _questionRepository;
        private readonly IRepository<DisciplineQuestionType> _disciplineQuestionTypeRepository;

        public QuestionTypeManager(IRepository<QuestionType> repository, IRepository<Question, long> questionRepository, IRepository<DisciplineQuestionType> disciplineQuestionTypeRepository)
        {
            _repository = repository;
            _questionRepository = questionRepository;
            _disciplineQuestionTypeRepository = disciplineQuestionTypeRepository;
        }

        /// <summary>
        /// 检查题型名称是否被占用
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public async Task CheckNameAsync(string name)
        {
            var isExist = await _repository.GetAll()
                .AnyAsync(x => x.Name == name);
            if (isExist)
                throw new UserFriendlyException($"题型名称:{name}已被占用.");
        }

        /// <summary>
        /// 创建新题型
        /// </summary>
        /// <param name="name"></param>
        /// <param name="questionCategory"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public async Task<QuestionType> CreateAsync(string name, QuestionCategory questionCategory, int? sort = null)
        {
            await CheckNameAsync(name);
            var questionType = new QuestionType()
            {
                Name = name,
                QuestionCategory = questionCategory
            };

            if (sort != null)
            {
                var minSort = await _repository.GetAll()
                    .MinAsync(x => (int?)x.Sort) ?? default;
                if (minSort > sort)
                    questionType.Sort = (int)sort;
                else
                {
                    var lastSort = await _repository.GetAll()
                                       .MaxAsync(x => (int?)x.Sort) ?? default;
                    questionType.Sort = lastSort + 1;
                    await UpdateSortAsync(questionType, (int)sort);
                }
            }
            else
            {
                var lastSort = await _repository.GetAll()
                                   .MaxAsync(x => (int?)x.Sort) ?? default;
                questionType.Sort = lastSort + 1;
            }

            await _repository.InsertAndGetIdAsync(questionType);
            return questionType;
        }

        /// <summary>
        /// 排序
        /// </summary>
        /// <param name="questionType"></param>
        /// <param name="sortType"></param>
        /// <returns></returns>
        public async Task SortAsync(QuestionType questionType, SortType sortType)
        {
            switch (sortType)
            {
                case SortType.上移:
                    var lastSort = await _repository.GetAll()
                        .Where(x => x.Sort < questionType.Sort)
                        .Select(x => x.Sort)
                        .OrderByDescending(x => x)
                        .FirstOrDefaultAsync();
                    await UpdateSortAsync(questionType, lastSort);
                    break;
                case SortType.下移:
                    var nextSort = await _repository.GetAll()
                        .Where(x => x.Sort > questionType.Sort)
                        .Select(x => x.Sort)
                        .OrderBy(x => x)
                        .FirstOrDefaultAsync();
                    await UpdateSortAsync(questionType, nextSort);
                    break;
            }


        }

        /// <summary>
        /// 修改题型
        /// </summary>
        /// <param name="questionType"></param>
        /// <param name="name"></param>
        /// <param name="questionCategory"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public async Task UpdateAsync(QuestionType questionType, string name, QuestionCategory questionCategory, int sort)
        {
            await CheckNameAsync(name);
            await UpdateSortAsync(questionType, sort);
            if (questionType.IsStruct)
                return;
            questionType.Name = name;
            questionType.QuestionCategory = questionCategory;
        }

        /// <summary>
        /// 修改题型排序
        /// </summary>
        /// <param name="questionType"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public async Task<QuestionType> UpdateSortAsync(QuestionType questionType, int sort)
        {
            if (questionType.Sort == sort) return questionType;
            var diff = questionType.Sort - sort;
            if (diff > 0)
            {
                var questionTypes = await _repository.GetAllListAsync(x => x.Sort >= sort
                                                                       && x.Sort < questionType.Sort);
                questionTypes.ForEach(x => x.Sort++);
            }
            else
            {
                var questionTypes = await _repository.GetAllListAsync(x => x.Sort <= sort
                                                                           && x.Sort > questionType.Sort);
                questionTypes.ForEach(x => x.Sort--);
            }
            questionType.Sort = sort;
            return questionType;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync(int id)
        {
            var questionType = await _repository.GetAsync(id);
            await DeleteAsync(questionType);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="questionType"></param>
        /// <returns></returns>
        public async Task DeleteAsync(QuestionType questionType)
        {
            if (questionType.IsStruct)
                throw new UserFriendlyException("禁止删除固定类型");
            var isUsed = await _disciplineQuestionTypeRepository.GetAll()
                .AnyAsync(x => x.QuestionTypeId == questionType.Id);
            if (isUsed) throw new UserFriendlyException("当前类型下有细分题型,禁止删除");

            isUsed = await _questionRepository.GetAll()
                .AnyAsync(x => x.QuestionTypeId == questionType.Id);
            if (isUsed) throw new UserFriendlyException("当前类型下已有试题,禁止删除");

            var nextList = await _repository.GetAllListAsync(x => x.Sort > questionType.Sort);
            nextList.ForEach(x => x.Sort--);
            await _repository.DeleteAsync(questionType);
        }
    }
}