using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Abp.Domain.Repositories;
using Abp.UI;
using Mapster;
using Microsoft.EntityFrameworkCore;
using YGNT.QuestionLibrary.Core.BaseData;
using YGNT.QuestionLibrary.Core.BaseData.Cache;
using YGNT.QuestionLibrary.Core.Papers;
using YGNT.QuestionLibrary.Papers.Dto;
using Z.EntityFramework.Plus;

namespace YGNT.QuestionLibrary.Papers
{
    /// <summary>
    /// 试卷设置
    /// </summary>
    public class PaperSettingAppService : IPaperSettingAppService
    {
        private readonly IRepository<PaperStructureSetting> _paperStructureSettingRepository;
        private readonly IRepository<PaperSetting> _paperSettingRepository;
        private readonly IRepository<PaperDisciplineQtSortSetting> _paperDisciplineQtSortSettingRepository;
        private readonly IPaperStructureSettingCache _paperStructureSettingCache;

        public PaperSettingAppService(IRepository<PaperStructureSetting> paperStructureSettingRepository, IRepository<PaperSetting> paperSettingRepository, IPaperStructureSettingCache paperStructureSettingCache, IRepository<PaperDisciplineQtSortSetting> paperDisciplineQtSortSettingRepository)
        {
            _paperStructureSettingRepository = paperStructureSettingRepository;
            _paperSettingRepository = paperSettingRepository;
            _paperStructureSettingCache = paperStructureSettingCache;
            _paperDisciplineQtSortSettingRepository = paperDisciplineQtSortSettingRepository;
        }

        /// <summary>
        /// 获取试卷设置
        /// </summary>
        /// <param name="paperId">试卷id</param>
        /// <returns></returns>
        public async Task<List<PaperSettingDto>> GetPaperSettingsAsync([Required] int paperId)
        {
            var result = await _paperStructureSettingRepository.GetAll()
                .GroupJoin(_paperSettingRepository.GetAll().Where(x => x.PaperId == paperId), x => x.Id,
                                x => x.PaperStructureSettingId, (s, x) => new { s, x })
                            .SelectMany(x => x.x.DefaultIfEmpty(), (s, x) => new PaperSettingDto()
                            {
                                Id = s.s.Id,
                                Code = s.s.Code,
                                Name = s.s.Name,
                                Param = x.Param,
                                DefaultParam = s.s.Param,
                                IsSet = x != null
                            }).ToListAsync();
            return result;
        }

        /// <summary>
        /// 获取试卷细分题型排序设置
        /// </summary>
        /// <param name="paperId"></param>
        /// <returns></returns>
        public async Task<List<DisciplineQtSortSettingDto>> GetDisciplineSortSettingAsync([Required] int paperId)
        {
            var setting = await _paperDisciplineQtSortSettingRepository.GetAll()
                .Where(x => x.PaperId == paperId)
                .OrderBy(x => x.Sort)
                .Select(x => x.Adapt(new DisciplineQtSortSettingDto()
                {
                    Discipline = x.Discipline.Name,
                    DisciplineQuestionType = x.DisciplineQuestionType.Name
                }))
                .ToListAsync();
            return setting;
        }

        /// <summary>
        /// 修改试卷细分题型排序
        /// </summary>
        /// <param name="paperId"></param>
        /// <param name="update"></param>
        /// <returns></returns>
        public async Task UpdateDisciplineSortSettingAsync([Required] int paperId, List<UpdateDisciplineQtSortSettingDto> update)
        {
            var sortSettings = await _paperDisciplineQtSortSettingRepository.GetAllListAsync(x => x.PaperId == paperId);
            Hashtable hs = new Hashtable();
            foreach (var sortSetting in sortSettings)
            {
                foreach (var updateSettingDto in update)
                {
                    if (updateSettingDto.Id == sortSetting.Id)
                        sortSetting.Sort = updateSettingDto.Sort;
                }
                if (!hs.ContainsKey(sortSetting.Sort))
                    hs.Add(sortSetting.Sort, sortSetting);
                else
                    throw new UserFriendlyException($"排序编号{sortSetting.Sort}出现重复!");
            }
        }

        /// <summary>
        /// 保存设置
        /// </summary>
        /// <param name="paperId"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public async Task SavePaperSettingAsync(int paperId, List<SavePaperSetDto> settings)
        {
            //删除原有设置
            await _paperSettingRepository.GetAll()
                .Where(x => x.PaperId == paperId)
                .DeleteAsync();
            foreach (var setting in settings)
            {
                var structureSettingCache = await _paperStructureSettingCache.GetAsync(setting.PaperSetId);
                await _paperSettingRepository.InsertAndGetIdAsync(new PaperSetting()
                {
                    PaperId = paperId,
                    PaperStructureSettingId = setting.PaperSetId,
                    PaperStructureSettingCode = structureSettingCache.Code,
                    Param = setting.Param
                });
            }
        }
    }
}