using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualBasic;
using SharedDATA.Api;
using System.Linq;
using TechHelper.Context;
using TechHelper.Server.Repositories;
using TechHelper.Services.Beta;
using static TechHelper.Services.Beta.IExamService;

namespace TechHelper.Services.Beta
{

	public class ExamService : IExamService
	{
		private readonly IUnitOfWork _unitOfWork;
		private readonly ISubmissionService _submissionService;
		private readonly IClassService _classService;
		private readonly IMapper _mapper;

		public ExamService(IUnitOfWork unitOfWork, IMapper mapper, IClassService classService, ISubmissionService submissionService)
		{
			_unitOfWork = unitOfWork;
			_mapper = mapper;
			_classService = classService;
			_submissionService = submissionService;
		}

		public async Task<ApiResponse> CreateExamAsync(ExamDto ExamDto)
		{
			try
			{

				Exam newAssi = _mapper.Map<Exam>(ExamDto);
				//var context = _unitOfWork.GetDbContext<ApplicationContext>();

				//foreach (var entry in context.ChangeTracker.Entries())
				//{
				//	if (entry.State == Microsoft.EntityFrameworkCore.EntityState.Added)
				//	{
				//		if (entry.Entity is Question newQues)
				//		{
				//			newQues.CreatorId = newAssi.CreatorId;
				//		}
				//	}

				//}




				if (await _unitOfWork.SaveChangesAsync() > 0)
				{
					return ApiResponse.Success();
				}

				return ApiResponse.Error("保存失败");
			}
			catch (Exception ex)
			{
				return ApiResponse.Error(ex.Message);
			}
		}


		public async Task<ApiResponse> GetAllAsync(QueryParameter query)
		{
			try
			{
				var repository = _unitOfWork.GetRepository<Exam>();

				if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
				{
					var examQuestions = await repository.GetPagedListAsync(
						predicate: eq => eq.Title.Contains(query.Search),
						pageSize: query.PageSize,
						pageIndex: query.PageIndex
					);
					var examQuestionDtosFiltered = _mapper.Map<IEnumerable<ExamListDto>>(examQuestions.Items);
					return new ApiResponse(true, examQuestionDtosFiltered);
				}
				else
				{
					var examQuestions = await repository.GetPagedListAsync(
						pageSize: query.PageSize,
						pageIndex: query.PageIndex
					);
					var examQuestionDtos = _mapper.Map<IEnumerable<ExamListDto>>(examQuestions.Items);
					return new ApiResponse(true, examQuestionDtos);
				}
			}
			catch (Exception ex)
			{
				return new ApiResponse($"获取所有考试题目时发生错误: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAsync(Guid id)
		{
			try
			{
				var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == id);
				if (assignment == null)
				{
					return ApiResponse.Error("获取失败");
				}
				var result = _mapper.Map<ExamDto>(assignment);
				return ApiResponse.Success(result: result);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error(ex.Message);
			}
		}

		public async Task<ApiResponse> AddAsync(ExamDto model)
		{
			try
			{
				var exam = _mapper.Map<Exam>(model);
				await _unitOfWork.GetRepository<Exam>().InsertAsync(exam);
				if (await _unitOfWork.SaveChangesAsync() > 0)
				{
					return ApiResponse.Success("创建成功", exam.Id);
				}
				return ApiResponse.Error("创建失败");
			}
			catch (Exception ex)
			{
				return ApiResponse.Error(ex.Message);
			}
		}

		public async Task<ApiResponse> UpdateAsync(ExamDto model)
		{
			try
			{
				var existingExam = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == model.Id);
				if (existingExam == null) return ApiResponse.Error("找不到该试卷");
				_mapper.Map(model, existingExam);
				_unitOfWork.GetRepository<Exam>().Update(existingExam);
				if (await _unitOfWork.SaveChangesAsync() > 0)
				{
					return ApiResponse.Success("更新成功");
				}
				return ApiResponse.Error("更新失败");
			}
			catch (Exception ex)
			{
				return ApiResponse.Error(ex.Message);
			}
		}

		public async Task<ApiResponse> DeleteAsync(Guid id)
		{
			try
			{
				var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == id);

				if (assignment == null) return ApiResponse.Error("找不到该试卷");
				_unitOfWork.GetRepository<Exam>().Delete(id);
				_unitOfWork.GetRepository<ExamQuestion>().Delete(assignment.ExamStructId);


				if (await _unitOfWork.SaveChangesAsync() > 0)
				{
					return ApiResponse.Success();
				}
				return ApiResponse.Error("删除失败");
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"内部问题,{ex.Message}, InerException{ex.InnerException}");
			}
		}

		public async Task<ApiResponse> AssignmentToAllClassesAsync(AssigExamToClassDto examToClassDto, Guid TeacherId)
		{
			try
			{
				var result = await _classService.GetUserInjoinedClasses(TeacherId);

				if (result.Status == false) return ApiResponse.Error(result.Message);
				var userClass = result.Result as UserClassDetailInfoDto;
				if (userClass == null || !userClass.UserClassInfos.Any()) return ApiResponse.Error("教师没有管理任何班级");


				var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == examToClassDto.examId);
				if (assignment == null) return ApiResponse.Error("没有找到该试卷");

				foreach (var classId in userClass.UserClassInfos)
				{
					await AssignmentToClassAsync(TeacherId, examToClassDto.examId, classId.Id);
				}

				if (await _unitOfWork.SaveChangesAsync() > 0)
				{
					return ApiResponse.Success("分配成功");
				}
				return ApiResponse.Error("分配失败");
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"内部错误, {ex.Message}");
			}
		}

		public async Task<ApiResponse> AssignmentToStudentsAsync(AssigExamToStudentsDto examToStudentsDto)
		{
			try
			{
				var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == examToStudentsDto.ExamId);
				if (assignment == null)
				{
					return ApiResponse.Error("获取失败");
				}
				if (assignment == null) return ApiResponse.Error("没有找到该试卷");

				if (examToStudentsDto.StudentIds == null || !examToStudentsDto.StudentIds.Any())
				{
					return ApiResponse.Error("没有选择学生");
				}

				foreach (var studentId in examToStudentsDto.StudentIds)
				{
					var subCount = await _unitOfWork.GetRepository<Submission>().GetAll(
						predicate: su => su.ExamId == examToStudentsDto.ExamId && su.StudentId == studentId
					).CountAsync();

					var submission = assignment.ConvertToSubmission(studentId, examToStudentsDto.CreaterId, examToStudentsDto.ClassId);
					submission.AttemptNumber = (byte)(subCount + 1);
					await _unitOfWork.GetRepository<Submission>().InsertAsync(submission);
				}

				if (await _unitOfWork.SaveChangesAsync() > 0)
				{
					return ApiResponse.Success();
				}
				return ApiResponse.Error();
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"内部错误, {ex.Message}");
			}
		}

		public async Task<ApiResponse> AssignmentToClassAsync(Guid TeacherId, Guid examId, Guid classId)
		{
			try
			{
				var classStudents = await _classService.GetClassStudentsAsync(classId);
				if (!classStudents.Status) return ApiResponse.Error(classStudents.Message);
				var userlist = classStudents.Result as IEnumerable<UserListDto>;
				if (userlist == null || !userlist.Any()) return ApiResponse.Error("班级没有学生");

				var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == examId);
				if (assignment == null) return ApiResponse.Error("没有找到该试卷");

				foreach (var student in userlist)
				{
					var subCount = await _unitOfWork.GetRepository<Submission>().GetAll(
						predicate: su => su.ExamId == examId && su.StudentId == student.Id
					).CountAsync();

					var submission = assignment.ConvertToSubmission(student.Id, TeacherId, classId);
					submission.AttemptNumber = (byte)(subCount + 1);
					await _unitOfWork.GetRepository<Submission>().InsertAsync(submission);
				}

				if (await _unitOfWork.SaveChangesAsync() > 0)
				{
					return ApiResponse.Success("创建成功");
				}
				return ApiResponse.Error("创建失败");
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"内部错误, {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetExamSubmissionDetailInClassAsync(AssigExamToClassDto examToClassDto)
		{
			try
			{
				var submissions = await _unitOfWork.GetRepository<Submission>().GetAllAsync(predicate: s => s.ExamId == examToClassDto.examId && s.ClassId == examToClassDto.classId);

				if (submissions == null || !submissions.Any()) return ApiResponse.Error("没有找到该试卷");

				var result = _mapper.Map<List<SubmissionListDto>>(submissions);

				return ApiResponse.Success(result: result);


			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"内部错误, {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetExamTotalErrorDistributionInClassAsync(AssigExamToClassDto examToClassDto)
		{
			try
			{
				var submissions = await _unitOfWork.GetRepository<Submission>().
					GetAllAsync(predicate: s => s.ExamId == examToClassDto.examId && s.ClassId == examToClassDto.classId);

				if (submissions == null || !submissions.Any()) return ApiResponse.Error("没有找到该试卷");

				var errorTypeDistribution = submissions
					.SelectMany(s => s.SubmissionDetails)
					.Where(d => d.IsCorrect == false)
					.GroupBy(d => d.ExamQuestion.Type.Name)
					.ToDictionary(g => g.Key, g => g.Count());

				var errorLessonDistribution = submissions
					.SelectMany(s => s.SubmissionDetails)
					.Where(d => d.IsCorrect == false)
					.Where(d => d.ExamQuestion?.Question?.Lesson?.Title != null)
					.GroupBy(d => d.ExamQuestion.Question?.Lesson?.Title)
					.ToDictionary(g => g.Key, g => g.Count());


				var scores = submissions.Select(s => s.OverallGrade);
				var result = new ExamDistributionDto(errorTypeDistribution, errorLessonDistribution, scores);

				return ApiResponse.Success(result: result);


			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"内部错误, {ex.Message}");
			}
		}
	}

}
