using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using SharedDATA.Context;
using TechHelper.Services;

namespace TechHelper.Server.Services
{
	public class SubmissionServices : ISubmissionServices
	{
		private readonly IUnitOfWork _unitOfWork;
		private readonly IMapper _mapper;
		private readonly IRepository<Submission> _submissionRepository;
		private readonly IRepository<SubmissionDetail> _submissionDetailRepository;

		public SubmissionServices(IMapper mapper, IUnitOfWork unitOfWork)
		{
			_mapper = mapper;
			_unitOfWork = unitOfWork;
			_submissionRepository = _unitOfWork.GetRepository<Submission>();
			_submissionDetailRepository = _unitOfWork.GetRepository<SubmissionDetail>();
		}

		public async Task<ApiResponse> AddAsync(Submission model)
		{
			try
			{
				model.SubmissionTime = DateTime.Now;
				model.IsDeleted = false;

				await _submissionRepository.InsertAsync(model);
				await _unitOfWork.SaveChangesAsync();

				var result = _mapper.Map<SubmissionDto>(model);
				return ApiResponse.Success("提交成功。", result);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"添加提交失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> DeleteAsync(Guid id)
		{
			try
			{
				var submission = await _submissionRepository.GetFirstOrDefaultAsync(predicate: s => s.Id == id);
				if (submission == null)
				{
					return ApiResponse.Error("未找到要删除的提交。", 404);
				}

				submission.IsDeleted = true;
				_submissionRepository.Update(submission);

				var submissionDetails = await _submissionDetailRepository.GetPagedListAsync(predicate: sd => sd.SubmissionId == id);
				foreach (var detail in submissionDetails.Items)
				{
					detail.IsDeleted = true;
					_submissionDetailRepository.Update(detail);
				}

				await _unitOfWork.SaveChangesAsync();
				return ApiResponse.Success("提交及相关详情删除成功。", null);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"删除提交失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAllAsync(QueryParameter query)
		{
			try
			{
				var pagedSubmissions = await _submissionRepository.GetPagedListAsync(
					pageIndex: query.PageIndex,
					pageSize: query.PageSize,
					orderBy: s => s.OrderByDescending(s => s.SubmissionTime),
					predicate: s => !s.IsDeleted,
					include: i => i.Include(s => s.Student)
									.Include(s => s.Exam));

				var submissionDtos = _mapper.Map<List<SubmissionDto>>(pagedSubmissions.Items);

				return ApiResponse.Success("获取所有提交成功。", new PagedList<SubmissionDto>
				{
					PageIndex = pagedSubmissions.PageIndex,
					PageSize = pagedSubmissions.PageSize,
					TotalCount = pagedSubmissions.TotalCount,
					TotalPages = pagedSubmissions.TotalPages,
					Items = submissionDtos
				});
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取所有提交失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAllErrorQuestionsAsync(Guid userId)
		{
			try
			{

				var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
					predicate: sd => sd.StudentId == userId && sd.IsCorrect == false &&
									 (sd.Status == SubmissionStatus.Submitted || sd.Status == SubmissionStatus.Graded),
					include: i => i
						.Include(s => s.ExamQuestion)
							.ThenInclude(aq => aq.Question));

				var errorQuestions = errorSDs.Items.Select(sd => sd.ExamQuestion.Question)
										 .Where(q => q != null)
										 .DistinctBy(q => q.Id)
										 .ToList();


				var result = _mapper.Map<List<QuestionDto>>(errorQuestions);
				return ApiResponse.Success("获取所有错题成功。", result);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取所有错题失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAllErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId)
		{
			try
			{
				var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
					predicate: sd => sd.Submission.ExamId == assignmentId &&
									 sd.StudentId == userId &&
									 sd.IsCorrect == false &&
									 (sd.Status == SubmissionStatus.Submitted || sd.Status == SubmissionStatus.Graded),
					include: i => i
						.Include(s => s.ExamQuestion)
							.ThenInclude(aq => aq.Question));

				// 对错题按类型进行分组计数
				var errorTypeDistribution = errorSDs.Items
					.Where(sd => sd.ExamQuestion?.Question != null)
					.GroupBy(sd => sd.ExamQuestion.Question.Type)
					.Select(g => new
					{
						QuestionType = g.Key.ToString(),
						Count = g.Count()
					})
					.ToList();

				return ApiResponse.Success("获取错题类型分布成功。", errorTypeDistribution);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取错题类型分布失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAssignmentAllStudentsError(Guid assignmentId, Guid teacherId)
		{
			try
			{
				var submissionDetails = await _submissionDetailRepository.GetPagedListAsync(
					predicate: sd => sd.Submission.ExamId == assignmentId &&
									 sd.IsCorrect == false &&
									 (sd.Status == SubmissionStatus.Submitted || sd.Status == SubmissionStatus.Graded),
					include: i => i.Include(sd => sd.Student));


				var studentsErrorSummary = submissionDetails.Items
					.Where(sd => sd.Student != null)
					.GroupBy(sd => new { sd.StudentId, sd.Student.UserName })
					.Select(g => new
					{
						StudentId = g.Key.StudentId,
						StudentName = g.Key.UserName,
						ErrorQuestionCount = g.Count()
					})
					.ToList();

				return ApiResponse.Success("获取作业中所有学生的错题情况成功。", studentsErrorSummary);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取作业中所有学生的错题情况失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAssignmentErrorQuestionsAsync(Guid assignmentId, Guid userId)
		{
			try
			{
				var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
					predicate: sd => sd.Submission.ExamId == assignmentId &&
									 sd.StudentId == userId &&
									 sd.IsCorrect == false &&
									 (sd.Status == SubmissionStatus.Submitted || sd.Status == SubmissionStatus.Graded),
					include: i => i
						.Include(s => s.ExamQuestion)
							.ThenInclude(aq => aq.Question));

				var errorQuestions = errorSDs.Items.Select(sd => sd.ExamQuestion.Question)
										 .Where(q => q != null)
										 .DistinctBy(q => q.Id)
										 .ToList();

				var result = _mapper.Map<List<QuestionDto>>(errorQuestions);
				return ApiResponse.Success("获取指定作业错题成功。", result);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取指定作业错题失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAssignmentErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId)
		{
			try
			{
				var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
					predicate: sd => sd.Submission.ExamId == assignmentId &&
									 sd.StudentId == userId &&
									 sd.IsCorrect == false &&
									 (sd.Status == SubmissionStatus.Submitted || sd.Status == SubmissionStatus.Graded),
					include: i => i
						.Include(s => s.ExamQuestion)
							.ThenInclude(aq => aq.Question));

				var errorTypeDistribution = errorSDs.Items
					.Where(sd => sd.ExamQuestion?.Question != null)
					.GroupBy(sd => sd.ExamQuestion.Question.Type)
					.Select(g => new
					{
						QuestionType = g.Key.ToString(),
						Count = g.Count()
					})
					.ToList();

				return ApiResponse.Success("获取指定作业错题类型分布成功。", errorTypeDistribution);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取指定作业错题类型分布失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetAsync(Guid id)
		{
			try
			{
				var submission = await _submissionRepository.GetFirstOrDefaultAsync(
					predicate: s => s.Id == id && !s.IsDeleted,
					include: i => i.Include(s => s.Student)
									.Include(s => s.Exam)
									.Include(s => s.Grader)
									.Include(s => s.SubmissionDetails)
										.ThenInclude(sd => sd.ExamQuestion)
											.ThenInclude(aq => aq.Question));

				if (submission == null)
				{
					return ApiResponse.Error("未找到提交。", 404);
				}

				var submissionDto = _mapper.Map<SubmissionDto>(submission);
				return ApiResponse.Success("获取提交成功。", submissionDto);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取提交失败: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetQuestionErrorStudents(Guid assignmentQuestionId)
		{
			try
			{
				var errorSubmissionDetails = await _submissionDetailRepository.GetPagedListAsync(
					predicate: sd => sd.ExamQuestionId == assignmentQuestionId &&
									 sd.IsCorrect == false &&
									 (sd.Status == SubmissionStatus.Submitted || sd.Status == SubmissionStatus.Graded),
					include: i => i
						.Include(sd => sd.Student)
						.Include(sd => sd.ExamQuestion)
							.ThenInclude(aq => aq.Question));


				var errorStudentsByQuestion = errorSubmissionDetails.Items
					.Where(sd => sd.ExamQuestion?.Question != null && sd.Student != null)
					.GroupBy(sd => new { sd.ExamQuestionId, sd.ExamQuestion.Question.Title })
					.Select(g => new
					{
						AssignmentQuestionId = g.Key.AssignmentQuestionId,
						QuestionTitle = g.Key.Title,
						ErrorStudents = g.Select(sd => new
						{
							StudentId = sd.StudentId,
							StudentName = sd.Student.UserName
						}).Distinct().ToList()
					})
					.ToList();

				return ApiResponse.Success("获取出现错题的学生成功。", errorStudentsByQuestion);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取出现错题的学生失败: {ex.Message}");
			}
		}

		public async Task<byte> IsHasSubmissionAsync(Guid assignment, Guid studentId)
		{
			try
			{
				var result = await _unitOfWork.GetRepository<Submission>().GetAllAsync(predicate: s => s.ExamId == assignment && s.StudentId == studentId);
				return (byte)result.Count;
			}
			catch (Exception ex)
			{
				throw;
			}
		}

		public async Task<ApiResponse> UpdateAsync(Submission model)
		{
			try
			{
				var existingSubmission = await _submissionRepository.GetFirstOrDefaultAsync(predicate: s => s.Id == model.Id && !s.IsDeleted);
				if (existingSubmission == null)
				{
					return ApiResponse.Error("未找到要更新的提交。", 404);
				}
				_mapper.Map(model, existingSubmission);


				_submissionRepository.Update(existingSubmission);
				await _unitOfWork.SaveChangesAsync();

				var result = _mapper.Map<SubmissionDto>(existingSubmission);
				return ApiResponse.Success("更新提交成功。", result);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"更新提交失败: {ex.Message}");
			}
		}
	}
}
