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.Runtime.Session;
using Abp.UI;
using Mapster;
using Microsoft.EntityFrameworkCore;
using YGNT.Infrastructure.Extension;
using YGNT.Infrastructure.Helper;
using YGNT.Infrastructure.Model;
using YGNT.QuestionLibrary.Core.Disciplines;
using YGNT.QuestionLibrary.Core.Disciplines.Domain;
using YGNT.QuestionLibrary.Core.IRepositories;
using YGNT.QuestionLibrary.Core.Permissions;
using YGNT.QuestionLibrary.Courses;
using YGNT.QuestionLibrary.Disciplines.Dto;
using YGNT.QuestionLibrary.Grades;

namespace YGNT.QuestionLibrary.Disciplines
{
    /// <summary>
    /// 学科
    /// </summary>
    public class DisciplineAppService : IDisciplineAppService
    {
        private readonly IDisciplineRepository _disciplineRepository;
        private readonly IRepository<UserDiscipline, long> _userDisciplineRepository;
        private readonly IDisciplineManager _disciplineManager;
        private readonly IHttpHelper _httpHelper;
        public IAbpSession AbpSession { get; set; }
        private readonly IGradesAppService _gradesAppService;
        private readonly ICoursesAppService _coursesAppService;

        public DisciplineAppService(IDisciplineRepository disciplineRepository, 
            IRepository<UserDiscipline, long> userDisciplineRepository, 
            IDisciplineManager disciplineManager,
            IHttpHelper httpHelper,
            IGradesAppService gradesAppService,
            ICoursesAppService coursesAppService)
        {
            _disciplineRepository = disciplineRepository;
            _userDisciplineRepository = userDisciplineRepository;
            _disciplineManager = disciplineManager;
            AbpSession = NullAbpSession.Instance;
            _httpHelper = httpHelper;
            _gradesAppService = gradesAppService;
            _coursesAppService = coursesAppService;
        }

        /// <summary>
        /// 查询学科列表
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<DisciplineDto>> GetListAsync(SearchDisciplineInputDto search)
        {
            
            var queryable = _disciplineRepository.GetAll()
                .WhereIf(!search.GradeId.HasValue, x => x.Grade.EducationCategory.IsActive)
                .WhereIf(!search.KeyWord.IsNullOrEmpty(), x => x.Name.Contains(search.KeyWord))
                .WhereIf(search.GradeId.HasValue, x => x.GradeId == search.GradeId)
                .OrderBy(x => x.Name);
            return await queryable.GetResultAsync(search, x => x.Adapt(new DisciplineDto()
            {
                GradeName = x.Grade.Name
            }));
        }


        /// <summary>
        /// 查询学科详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<DisciplineDto> GetOneAsync([Required] int id)
        {
            var disciplineDto = await _disciplineRepository.GetAll()
                .Where(x => x.Id == id)
                .Select(x => x.Adapt(new DisciplineDto()
                {
                    GradeName = x.Grade.Name
                }))
                .FirstOrDefaultAsync();
            return disciplineDto;
        }

        /// <summary>
        /// 创建新学科
        /// </summary>
        /// <param name="create"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.DisciplinePermissionName)]
        public async Task<int> CreateAsync(CreateDisciplineDto create)
        {
            var discipline = create.Adapt<Discipline>();
            await _disciplineManager.CheckNameAsync(discipline.Name, discipline.GradeId);
            await _disciplineRepository.InsertAndGetIdAsync(discipline);
            await _userDisciplineRepository.InsertAndGetIdAsync(new UserDiscipline()
            {
                UserId = AbpSession.GetUserId(),
                DisciplineId = discipline.Id
            });
            return discipline.Id;
        }

        /// <summary>
        /// 根据年级ID和科目ID获取主键
        /// </summary>
        /// <param name="gradeId"></param>
        /// <param name="courseId"></param>
        /// <returns></returns>
        public async Task<DisciplineDto> GetOndeByGradeAsync(int gradeId,int courseId)
        {
            var disciplineDto = await _disciplineRepository.GetAll()
                .Where(x => x.GradeId== gradeId)
                .Where(x => x.CourseId == courseId)
                .Select(x => x.Adapt(new DisciplineDto()
                {
                    GradeName = x.Grade.Name
                }))
                .FirstOrDefaultAsync();
            return disciplineDto;

        }

        /// <summary>
        /// 修改学科
        /// </summary>
        /// <param name="id"></param>
        /// <param name="update"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.DisciplinePermissionName)]
        public async Task UpdateAsync([Required] int id, UpdateDisciplineDto update)
        {
            var discipline = await _disciplineRepository.GetAsync(id);
            update.Adapt(discipline);
            await _disciplineManager.CheckNameAsync(discipline.Name, discipline.GradeId);
        }

        /// <summary>
        /// 删除学科
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.DisciplinePermissionName)]
        public async Task DeleteAsync([Required] int id)
        {
            await _disciplineRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 删除学科
        /// </summary>
        /// <param name="idList"></param>
        /// <returns></returns>
        [AbpAuthorize(QuestionLibraryAuthorizationProvider.DisciplinePermissionName)]
        public async Task DeleteListAsync(List<int> idList)
        {
            foreach (var id in idList)
            {
                await DeleteAsync(id);
            }
        }

        /// <summary>
        /// 同步学科
        /// </summary>
        /// <returns></returns>
        public async Task DataSyncAsync()
        {
            await _coursesAppService.DataSyncAsync();
            HttpResult httpResult = await _httpHelper.GetAsync($"{AppSettings.App("App", "ServerRoot")}/api/magic-api/educational/abutment/grade-course-info");
            if (httpResult.Success)
            {
                var list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DisciplineSyncDto>>(httpResult.Data.ToString());
                var gradeList = await _gradesAppService.GetListAll();
                var courseList = await _coursesAppService.GetListAll();
                foreach (var item in list)
                {
                    var grade = gradeList.FirstOrDefault(x => x.SourceId == item.GradeId);
                    var course = courseList.FirstOrDefault(x => x.SourceId == item.CourseId);
                    if (grade == null || course == null) continue;

                    var isExist = await _disciplineRepository.GetAll().AnyAsync(x => x.CourseId == course.Id && x.GradeId == grade.Id);
                    if (isExist)
                    {
                        var discipline = await _disciplineRepository.FirstOrDefaultAsync(x => x.CourseId == course.Id && x.GradeId == grade.Id);
                        discipline.Name = item.CourseName;
                        await _disciplineRepository.UpdateAsync(discipline);
                    }
                    else
                    {
                        var discipline = new Discipline { CourseId = course.Id, GradeId = grade.Id, Name = item.CourseName };
                        await _disciplineRepository.InsertAndGetIdAsync(discipline);
                    }
                }
            }
            else
            {
                throw new UserFriendlyException(httpResult.Message);
            }
        }
    }
}