using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.UI;
using Mapster;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using YGNT.Infrastructure.Helper;
using YGNT.Infrastructure.Model;
using YGNT.QuestionLibrary.Core.Disciplines;
using YGNT.QuestionLibrary.Core.EducationCategories;
using YGNT.QuestionLibrary.Core.EducationCategories.Domain;
using YGNT.QuestionLibrary.Core.Permissions;
using YGNT.QuestionLibrary.EducationCategories.Dto;
using YGNT.QuestionLibrary.EntityFrameworkCore.Repositories.Filter;

namespace YGNT.QuestionLibrary.EducationCategories
{
    /// <summary>
    /// 教育类别
    /// </summary>
    public class EducationCategoryAppService : IEducationCategoryAppService
    {
        private readonly IRepository<EducationCategory> _educationCategoryRepository;
        private readonly IDisciplineFilter _disciplineFilter;
        private readonly IRepository<Discipline> _disciplineRepository;
        private readonly IEducationCategoryManager _educationCategoryManager;
        private readonly IHttpHelper _httpHelper;

        public EducationCategoryAppService(IRepository<EducationCategory> educationCategoryRepository,
            IRepository<Discipline> disciplineRepository,
            IEducationCategoryManager educationCategoryManager, 
            IDisciplineFilter disciplineFilter,
            IHttpHelper httpHelper)
        {
            _educationCategoryRepository = educationCategoryRepository;
            _disciplineRepository = disciplineRepository;
            _educationCategoryManager = educationCategoryManager;
            _disciplineFilter = disciplineFilter;
            _httpHelper = httpHelper;
        }

        /// <summary>
        /// 查询教育类别列表
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<EducationCategoryDto>> GetListAsync(SearchEducationCategoriesInputDto search)
        {
            var queryable = _educationCategoryRepository.GetAll()
                .WhereIf(!search.KeyWord.IsNullOrEmpty(), x => x.Name.Contains(search.KeyWord))
                .WhereIf(search.IsActive.HasValue, x => x.IsActive == search.IsActive)
                .OrderBy(x => x.Name);

            var result = new PagedResultDto<EducationCategoryDto>()
            {
                TotalCount = await queryable.CountAsync(),
                Items = await queryable.PageBy(search.SkipCount, search.MaxResultCount)
                    .Select(x => x.Adapt(new EducationCategoryDto()
                    {
                        GradeCount = x.Grade.Count(f => _disciplineFilter.GetFilterQueryable().Select(s => s.Id).Contains(f.Id))
                    }))
                    .ToListAsync()
            };

            return result;
        }

        /// <summary>
        /// 查询教育类别详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<EducationCategoryDto> GetOneAsync([Required] int id)
        {
            var education = await _educationCategoryRepository.GetAsync(id);
            return education.Adapt<EducationCategoryDto>();
        }

        /// <summary>
        /// 查询教育类别包含的年级、学科、教材
        /// </summary>
        public async Task<List<GetChildrenAllDto>> GetChildrenAll()
        {
            var queryable = await _educationCategoryRepository.GetAll()
                                .Where(o => o.IsActive == true)
                    .Select(x => new GetChildrenAllDto()
                    {
                        Id = x.Id,
                        Name = x.Name,
                        Grades = x.Grade.Select(x1 => new GetChildrenAllGradesDto()
                        {
                            Id = x1.Id,
                            Name = x1.Name,
                            Disciplines = x1.Disciplines.Select(x2 => new GetChildrenAllDisciplinesDto()
                            {
                                Id = x2.Id,
                                Name = x2.Name,
                                Textbooks = x2.Textbooks.Select(x3 => new GetChildrenAllTextbooksDto()
                                {
                                    Id = x3.Id,
                                    Name = x3.Name,
                                })
                            })
                        })
                    })
                    .ToListAsync();
            return queryable;
        }

        /// <summary>
        /// 创建新教育类别
        /// </summary>
        /// <param name="create"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.EducationCategoryPermissionName)]
        public async Task<int> CreateAsync(CreateEducationCategoryDto create)
        {
            var educationCategory = EducationCategory.Create(create.Name, create.IsActive);
            await _educationCategoryManager.CheckNameAsync(educationCategory.Name);
            return await _educationCategoryRepository.InsertAndGetIdAsync(educationCategory);
        }

        /// <summary>
        /// 修改教育类别
        /// </summary>
        /// <param name="id"></param>
        /// <param name="update"></param>
        /// <returns></returns>
        public async Task UpdateAsync([Required] int id, UpdateEducationCategoryDto update)
        {
            var educationCategory = await _educationCategoryRepository.GetAsync(id);
            update.Adapt(educationCategory);
            await _educationCategoryManager.CheckNameAsync(educationCategory.Name);
        }

        /// <summary>
        /// 是否启用
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isActive"></param>
        /// <returns></returns>
        [HttpPut]
        public async Task ActiveAsync([Required] int id, bool isActive)
        {
            var educationCategory = await _educationCategoryRepository.GetAsync(id);
            educationCategory.IsActive = isActive;
            await _educationCategoryRepository.UpdateAsync(educationCategory);
        }

        /// <summary>
        /// 是否启用
        /// </summary>
        /// <param name="idList"></param>
        /// <param name="isActive"></param>
        /// <returns></returns>
        [HttpPut]
        public async Task ActiveListAsync([Required] List<int> idList, bool isActive)
        {
            foreach (var id in idList)
            {
                await ActiveAsync(id, isActive);
            }
        }

        /// <summary>
        /// 删除教育类别
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync([Required] int id)
        {
            var isUsed = await _disciplineRepository.GetAll().AnyAsync(x => x.GradeId == id);
            if (isUsed) throw new UserFriendlyException("当前教育类比正在被年级使用,禁止删除!");
            await _educationCategoryRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 删除教育类别
        /// </summary>
        /// <param name="idList"></param>
        /// <returns></returns>
        public async Task DeleteListAsync([Required] List<int> idList)
        {
            foreach (var id in idList)
            {
                await DeleteAsync(id);
            }
        }

        /// <summary>
        /// 同步教育类别
        /// </summary>
        /// <returns></returns>
        public async Task DataSyncAsync()
        {
            HttpResult httpResult = await _httpHelper.GetResponse($"{AppSettings.App("App", "ServerRoot")}/api/magic-api/abutment/major-gradation");
            if (httpResult.Success)
            {
                /*var sourceList = await _educationCategoryRepository.GetAllListAsync();
                foreach(var item in sourceList)
                {
                    await _educationCategoryRepository.DeleteAsync(item);
                }*/
                //await _educationCategoryRepository.DeleteAsync(i => i.Id > 0);
                var list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<EducationCategorySyncDto>>(httpResult.Data.ToString());
                foreach (var item in list)
                {
                    var isExist = await _educationCategoryRepository.GetAll().AnyAsync(x => x.SourceId == item.Id);
                    if (isExist)
                    {
                        var educationCategory = await _educationCategoryRepository.FirstOrDefaultAsync(i => i.SourceId == item.Id);
                        educationCategory.Name = item.Name;
                        await _educationCategoryRepository.UpdateAsync(educationCategory);
                    }
                    else
                    {
                        var educationCategory = EducationCategory.Create(item.Name, true);
                        educationCategory.SourceId = item.Id;
                        await _educationCategoryRepository.InsertAndGetIdAsync(educationCategory);
                    }

                }
            }
            else
            {
                throw new UserFriendlyException(httpResult.Message);
            }
        }
    }
}