using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Entities.DTO.Class;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Org.BouncyCastle.Crypto;
using SharedDATA.Api;

namespace TechHelper.Services
{
	public class ClassService : IClassService
	{
		private readonly IUnitOfWork _work;
		private readonly IMapper _mapper;
		private readonly UserManager<User> _userManager;

		public ClassService(IUnitOfWork work, IMapper mapper, UserManager<User> userManager)
		{
			_work = work;
			_mapper = mapper;
			_userManager = userManager;
		}

		public async Task<ApiResponse> AddAsync(ClassDto model)
		{
			try
			{
				var @class = _mapper.Map<Class>(model);
				await _work.GetRepository<Class>().InsertAsync(@class);

				if (await _work.SaveChangesAsync() > 0)
				{
					return new ApiResponse(true, _mapper.Map<ClassDto>(@class));
				}
				return new ApiResponse("添加班级失败。");
			}
			catch (Exception ex)
			{
				return new ApiResponse($"添加班级时发生错误: {ex.Message}");
			}
		}

		// 实现 IBaseService<ClassDto, int>.DeleteAsync
		public async Task<ApiResponse> DeleteAsync(Guid id) 
		{
			try
			{
				var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
					predicate: c => c.Id == id);

				if (existingClass == null)
				{
					return new ApiResponse("班级未找到。");
				}

				_work.GetRepository<Class>().Delete(existingClass);

				if (await _work.SaveChangesAsync() > 0)
				{
					return new ApiResponse(true, "班级删除成功。");
				}
				return new ApiResponse("删除班级失败。");
			}
			catch (Exception ex)
			{
				return new ApiResponse($"删除班级时发生错误: {ex.Message}");
			}
		}

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

				Func<IQueryable<Class>, IOrderedQueryable<Class>> orderBy = null;
				if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
				{
					// 在 Name 字段中进行模糊搜索
					var classes = await repository.GetPagedListAsync(
						orderBy: orderBy,
						pageSize: query.PageSize,
						pageIndex: query.PageIndex
					);
					var classDtosFiltered = _mapper.Map<IEnumerable<ClassDto>>(classes);
					return new ApiResponse(true, classDtosFiltered);
				}
				else
				{
					// 如果没有搜索条件，获取所有（带分页）
					var classes = await repository.GetPagedListAsync(
						orderBy: orderBy,
						pageSize: query.PageSize,
						pageIndex: query.PageIndex
					);
					var classDtos = _mapper.Map<IEnumerable<ClassDto>>(classes);
					return new ApiResponse(true, classDtos);
				}
			}
			catch (Exception ex)
			{
				return new ApiResponse($"获取所有班级时发生错误: {ex.Message}");
			}
		}

		// 实现 IBaseService<ClassDto, int>.GetAsync
		public async Task<ApiResponse> GetAsync(Guid id)
		{
			try
			{
				var @class = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
					predicate: c => c.Id == id);

				if (@class == null)
				{
					return new ApiResponse("班级未找到。");
				}

				var classDto = _mapper.Map<ClassDto>(@class);
				return new ApiResponse(true, classDto);
			}
			catch (Exception ex)
			{
				return new ApiResponse($"获取班级时发生错误: {ex.Message}");
			}
		}

		public async Task<ApiResponse> GetClassStudents(ClassDto classDto)
		{
			try
			{
				var result = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(predicate:
					c => c.Grade == classDto.Grade && c.Number == classDto.Class,
					include: i => i
					.Include(c => c.ClassStudents)
						.ThenInclude(cs => cs.Student));

				return ApiResponse.Success(result: result.ClassStudents);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"获取学生列表错误, {ex.Message}, {ex.InnerException}");
			}
		}

		public Task GetClassStudents(byte Grade, byte Class)
		{
			try
			{
				var result = _work.GetRepository<Class>().GetFirstOrDefault(predicate:
					c => c.Grade == Grade && c.Number == Class,
					include: i => i
					.Include(c => c.ClassStudents)
					.ThenInclude(cs => cs.Student));

			}
			catch (Exception ex)
			{ }
		}

		public async Task<ApiResponse> GetGradeClasses(byte Grade)
		{
			try
			{
				var result = await _work.GetRepository<Class>().GetAllAsync(predicate:
					c => c.Grade == Grade);

				var classes = result.Select(x => x.Number).ToList();
				return ApiResponse.Success(result: classes);
			}
			catch (Exception ex)
			{
				return ApiResponse.Error($"年级班级列表失败, {ex.Message}, {ex.InnerException}");
			}
		}

		public async Task<ApiResponse> GetUserClass(Guid id)
		{
			var tch = await _work.GetRepository<ClassTeacher>().GetAllAsync(predicate: user => user.TeacherId == id, include: i => i
			.Include(t => t.Class));
			var std = await _work.GetRepository<ClassStudent>().GetAllAsync(predicate: user => user.StudentId == id, include: i => i
			.Include(t => t.Class));

			if (tch == null && std == null) return ApiResponse.Error("你没有加入任何班级。");


			List<Class> result = new List<Class>();
			tch?.ToList().ForEach(c => result.Add(c.Class));
			std?.ToList().ForEach(c => result.Add(c.Class));
			return ApiResponse.Success(result: result);
		}

		public async Task<ApiResponse> GetUserClassRole(Guid id)
		{
			var tch = await _work.GetRepository<ClassTeacher>().GetAllAsync(predicate: user => user.TeacherId == id, include: i => i
.Include(t => t.Class));
			var std = await _work.GetRepository<ClassStudent>().GetAllAsync(predicate: user => user.StudentId == id, include: i => i
			.Include(t => t.Class));

			if (tch == null && std == null) return ApiResponse.Error("你没有加入任何班级。");


			UserClassRoleDto result = new UserClassRoleDto();
			tch?.ToList().ForEach(c => result.ClassInfo.Add((c.Class.Number, c.Class.Grade)));
			std?.ToList().ForEach(c => result.ClassInfo.Add((c.Class.Number, c.Class.Grade)));
			if (tch?.Count > 0) result.Role = "Teacher"; else result.Role = "Student";

			return ApiResponse.Success(result: result);

		}

		// 实现 IBaseService<ClassDto, int>.UpdateAsync
		public async Task<ApiResponse> UpdateAsync(ClassDto model)
		{
			try
			{
				// 首先通过 ID 查找现有实体
				var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
					predicate: c => c.Number == model.Class);

				if (existingClass == null)
				{
					return new ApiResponse("班级未找到。");
				}

				_mapper.Map(model, existingClass);
				_work.GetRepository<Class>().Update(existingClass);

				if (await _work.SaveChangesAsync() > 0)
				{
					return new ApiResponse(true, _mapper.Map<ClassDto>(existingClass));
				}
				return new ApiResponse("更新班级失败。");
			}
			catch (Exception ex)
			{
				return new ApiResponse($"更新班级时发生错误: {ex.Message}");
			}
		}

		public async Task<ApiResponse> UserRegister(UserRegistrationToClassDto user)
		{
			try
			{
				var usrinfo = await _userManager.FindByEmailAsync(user.User);
				var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
					predicate: (c => c.Number == user.ClassId && c.Grade == user.GradeId));


				if (existingClass == null || usrinfo == null) // Simplified check
				{
					return new ApiResponse("班级或用户未找到。"); // More accurate message
				}

				bool registrationExists = false;

				if (user.Roles == UserRoles.Student)
				{
					// Check for existing student registration
					var existingStudentRegistration = await _work.GetRepository<ClassStudent>().GetFirstOrDefaultAsync(
						predicate: cs => cs.StudentId == usrinfo.Id && cs.ClassId == existingClass.Id);

					if (existingStudentRegistration != null)
					{
						registrationExists = true;
					}
					else
					{
						var addresult = await _work.GetRepository<ClassStudent>().InsertAsync(new ClassStudent
						{
							StudentId = usrinfo.Id, // Use usrinfo.Id
							ClassId = existingClass.Id
						});
					}

					await _userManager.AddToRoleAsync(usrinfo, UserRoles.Student.ToString());
				}
				else if (user.Roles == UserRoles.Teacher)
				{
					// Check for existing teacher registration
					var existingTeacherRegistration = await _work.GetRepository<ClassTeacher>().GetFirstOrDefaultAsync(
						predicate: ct => ct.TeacherId == usrinfo.Id && ct.ClassId == existingClass.Id);

					if (existingTeacherRegistration != null)
					{
						registrationExists = true;
					}
					else
					{
						var classTeacher = new ClassTeacher
						{
							ClassId = existingClass.Id,
							TeacherId = usrinfo.Id, // Use usrinfo.Id
							SubjectTaught = user.SubjectArea
						};
						await _work.GetRepository<ClassTeacher>().InsertAsync(classTeacher);
					}

					await _userManager.AddToRoleAsync(usrinfo, UserRoles.Teacher.ToString());
				}

				if (registrationExists)
				{
					return new ApiResponse("用户已在此班级注册，请勿重复注册。");
				}

				if (await _work.SaveChangesAsync() > 0)
				{
					// It's possible SaveChangesAsync returns 0 even if a role was added
					// A more robust check might be needed depending on your exact requirements.
					return new ApiResponse(true, _mapper.Map<ClassDto>(existingClass));
				}

				// If SaveChangesAsync returns 0 and registrationExists is false, it means no actual DB change occurred for the ClassStudent/ClassTeacher insert.
				// This could happen if only the role was added, but the ClassStudent/Teacher was already there (and caught by the check).
				// Or it means the insert failed for another reason not caught by the duplicate check.
				// The previous error message "班级注册失败" is still appropriate in such cases.
				return new ApiResponse("班级注册失败。");

			}
			catch (Exception ex)
			{
				// Log the exception details for debugging
				// _logger.LogError(ex, "注册进班级时发生错误"); 
				return new ApiResponse($"注册进班级时发生错误: {ex.Message}");
			}
		}
	}
}
