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.Mvc;
using Microsoft.EntityFrameworkCore;
using YGNT.Infrastructure.Extension;
using YGNT.Infrastructure.Helper;
using YGNT.Infrastructure.Model;
using YGNT.QuestionLibrary.Core.Chapters;
using YGNT.QuestionLibrary.Core.Disciplines;
using YGNT.QuestionLibrary.Core.IRepositories;
using YGNT.QuestionLibrary.Core.Permissions;
using YGNT.QuestionLibrary.Core.Textbooks;
using YGNT.QuestionLibrary.Core.Textbooks.Domain;
using YGNT.QuestionLibrary.Courses;
using YGNT.QuestionLibrary.Disciplines;
using YGNT.QuestionLibrary.Disciplines.Dto;
using YGNT.QuestionLibrary.Extension;
using YGNT.QuestionLibrary.Grades;
using YGNT.QuestionLibrary.Textbooks.Dto;

namespace YGNT.QuestionLibrary.Textbooks
{
    /// <summary>
    /// 教材
    /// </summary>
    [AbpAuthorize()]
    public class TextbookAppService : ITextbookAppService
    {
        private readonly ITextbookRepository _textbookRepository;
        private readonly IDisciplineRepository _disciplineRepository;
        private readonly IRepository<Chapter, long> _chapterRepository;
        private readonly ITextbookManager _textbookManager;
        private readonly IHttpHelper _httpHelper;
        private readonly IGradesAppService _gradesAppService;
        private readonly ICoursesAppService _coursesAppService;

        public TextbookAppService(ITextbookRepository textbookRepository,
            IRepository<Chapter, long> chapterRepository,
            IDisciplineRepository disciplineRepository,
            ITextbookManager textbookManager,
           IHttpHelper httpHelper,
            IGradesAppService gradesAppService,
            ICoursesAppService coursesAppService
            )
        {
            _textbookRepository = textbookRepository;
            _chapterRepository = chapterRepository;
            _disciplineRepository = disciplineRepository;
            _textbookManager = textbookManager;
            _httpHelper = httpHelper;
            _gradesAppService = gradesAppService;
            _coursesAppService = coursesAppService;
        }

        /// <summary>
        /// 获取教材列表
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<TextbookDto>> GetListAsync(SearchTextbookInputDto search)
        {
            var queryable = _textbookRepository.GetAll()
                .WhereIf(!search.EducationCategoryId.HasValue
                    || !search.DisciplineId.HasValue, x => x.Discipline.Grade.EducationCategory.IsActive)
                .WhereIf(search.DisciplineId.HasValue, x => x.DisciplineId == search.DisciplineId)
                .WhereIf(!search.KeyWord.IsNullOrEmpty(), x => x.Name.Contains(search.KeyWord))
                .WhereIf(search.IsActive.HasValue, x => x.IsActive == search.IsActive)
                .WhereIf(search.EducationCategoryId.HasValue, x => x.Discipline.GradeId == search.EducationCategoryId)
                .OrderBy(x => x.IsActive)
                .ThenBy(x => x.Discipline.GradeId)
                .ThenByDescending(x => x.DisciplineId)
                .ThenBy(x => x.Name);

            return await queryable.GetResultAsync(search, x => x.Adapt(new TextbookDto()
            {
                Discipline = x.Discipline.Name,
                EducationCategory = x.Discipline.Grade.Name
            }));
        }

        /// <summary>
        /// 新建教材
        /// </summary>
        /// <param name="create"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.TextbookPermissionName)]
        public async Task<int> CreateAsync(CreateTextbookDto create)
        {
            var textbook = create.Adapt<Textbook>();
            await _textbookManager.CheckNameAsync(textbook.Name, textbook.DisciplineId);
            await _disciplineRepository.GetAsync(textbook.DisciplineId);
            return await _textbookRepository.InsertAndGetIdAsync(textbook);
        }

        /// <summary>
        /// 更新教材信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="update"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.TextbookPermissionName)]
        public async Task UpdateAsync([Required] int id, UpdateTextbookDto update)
        {
            var textbook = await _textbookRepository.GetAsync(id);
            update.Adapt(textbook);
            await _textbookManager.CheckNameAsync(textbook.Name, textbook.DisciplineId);
            await _textbookRepository.UpdateAsync(textbook);
        }

        /// <summary>
        /// 激活教材
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isActive"></param>
        /// <returns></returns>
        [HttpPut]
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.TextbookPermissionName)]
        public async Task<bool> ActiveAsync([Required] int id, bool isActive = false)
        {
            var textbook = await _textbookRepository.GetAsync(id);
            textbook.IsActive = isActive;
            await _textbookRepository.UpdateAsync(textbook);
            return textbook.IsActive;
        }

        /// <summary>
        /// 删除教材
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.TextbookPermissionName)]
        public async Task DeleteAsync([Required] int id)
        {
            var isUsed = await _chapterRepository.GetAll()
                .AnyAsync(x => x.TextbookId == id);
            if (isUsed) throw new UserFriendlyException($"教材已被使用,禁止删除");
            await _textbookRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 同步教材
        /// </summary>
        /// <returns></returns>
        public async Task DataSyncAsync()
        {
            HttpResult httpResult = await _httpHelper.GetAsync($"{AppSettings.App("App", "ServerRoot")}/api/magic-api/educational/abutment/book-info");
            if (httpResult.Success)
            {
                var list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<TextbookSyncDto>>(httpResult.Data.ToString());

                var gradeList = await _gradesAppService.GetListAll();
                var courseList = await _coursesAppService.GetListAll();
                foreach (var item in list)
                {
                    try
                    {
                        var grade = gradeList.FirstOrDefault(x => x.SourceId == item.GradeId);
                        var course = courseList.FirstOrDefault(x => x.SourceId == item.CourseId);

                        var discipline = await _disciplineRepository.GetAll()
                                                .Where(x => x.GradeId == grade.Id)
                                                .Where(x => x.CourseId == course.Id)
                                                .FirstOrDefaultAsync();
                        if (discipline == null) continue;

                        var isExist = await _textbookRepository.GetAll().AnyAsync(x => x.DisciplineId == discipline.Id && x.SourceId==item.BookId);

                        if (isExist)
                        {
                            var textbook = await _textbookRepository.FirstOrDefaultAsync(x => x.DisciplineId == discipline.Id && x.SourceId == item.BookId);
                            textbook.Name = item.BookName;
                            await _textbookRepository.UpdateAsync(textbook);

                        }
                        else
                        {
                            var textbook = new Textbook { Name = item.BookName, IsActive = true, DisciplineId = discipline.Id, SourceId = item.BookId };
                            await _textbookRepository.InsertAndGetIdAsync(textbook);

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

    }
}