using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Entities.DTO.Class;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Repository;

namespace TechHelper.Services.Beta
{
    public class ClassService : IClassService
    {
        private readonly IUnitOfWork _work;
        private readonly IMapper _mapper;

        public ClassService(IUnitOfWork work, IMapper mapper)
        {
            _work = work;
            _mapper = mapper;
        }

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

                if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
                {
                    var classes = await repository.GetPagedListAsync(
                        predicate: c => c.ClassName.Contains(query.Search),
                        pageSize: query.PageSize,
                        pageIndex: query.PageIndex
                    );
                    var classDtosFiltered = _mapper.Map<IEnumerable<ClassDto>>(classes.Items);
                    return new ApiResponse(true, classDtosFiltered);
                }
                else
                {
                    var classes = await repository.GetPagedListAsync(
                        pageSize: query.PageSize,
                        pageIndex: query.PageIndex
                    );
                    var classDtos = _mapper.Map<IEnumerable<ClassDto>>(classes.Items);
                    return new ApiResponse(true, classDtos);
                }
            }
            catch (Exception ex)
            {
                return new ApiResponse($"获取所有班级时发生错误: {ex.Message}");
            }
        }

        public async Task<ApiResponse> GetAsync(Guid id)
        {
            try
            {
                var @class = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
                    predicate: c => c.Id == id,
                    include: i => i.Include(c => c.Grade).Include(c => c.HeadTeacher));

                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> AddAsync(ClassDto model)
        {
            try
            {
                // 检查是否已存在相同年级下的同名班级
                var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
                    predicate: c => c.GradeId == model.GradeId && (c.ClassName == model.ClassName || c.Index == model.Index));

                if (existingClass != null)
                {
                    return new ApiResponse($"在当前年级下，班级 '{model.ClassName}', 序号 '{model.Index}' 已存在。 请检查你的班级名称和序号, 如有问题请联系管理员.");
                }

                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}");
            }
        }

        public async Task<ApiResponse> UpdateAsync(ClassDto model)
        {
            try
            {
                var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
                    predicate: c => c.Id == model.Id);

                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> 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> GetClassStudentsAsync(Guid classId)
        {
            try
            {
                var classEntity = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
                    predicate: c => c.Id == classId);

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

                var students = classEntity.Students
                    .Where(u => !u.IsDeleted)
                    .Select(u => u.User)
                    .ToList();


                var StudentsDto = _mapper.Map<IEnumerable<UserListDto>>(students);
                return new ApiResponse(true, StudentsDto);
            }
            catch (Exception ex)
            {
                return new ApiResponse($"获取班级学生时发生错误: {ex.Message}");
            }
        }

        public async Task<ApiResponse> ValidateClassRegistration(ClassValidDto user)
        {
            try
            {
                // 验证学校是否存在
                var schoolRepository = _work.GetRepository<School>();
                var school = await schoolRepository.GetFirstOrDefaultAsync(
                    predicate: s => s.SchoolName == user.SchoolName);

                if (school == null)
                {
                    return new ApiResponse("学校未找到。");
                }

                // 验证年级是否存在
                var gradeRepository = _work.GetRepository<Grade>();
                var grade = await gradeRepository.GetFirstOrDefaultAsync(
                    predicate: g => g.SchoolId == school.Id && g.GradeLevel == user.Grade);

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

                // 验证班级是否存在
                var classRepository = _work.GetRepository<Class>();
                var classEntity = await classRepository.GetFirstOrDefaultAsync(
                    predicate: c => c.GradeId == grade.Id && c.Index == user.Class && !c.IsDeleted);

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

                // 返回验证成功的班级信息
                return new ApiResponse(true, classEntity.Id);
            }
            catch (Exception ex)
            {
                return new ApiResponse($"验证班级信息时发生错误: {ex.Message}");
            }
        }

        public async Task<ApiResponse> UserRegister(RegisterUserToClassDto user)
        {
            try
            {
                // 获取班级实体
                var classRepository = _work.GetRepository<Class>();
                var classEntity = await classRepository.GetFirstOrDefaultAsync(
                    predicate: c => c.Id == user.ClassId);

                if (classEntity == null)
                {
                    return new ApiResponse("检查你的班级输入,没有该班级。");
                }

                // 检查用户是否已经在该班级中
                var existingClassUser = classEntity.ClassUsers.FirstOrDefault(u => u.UserId == user.UserId);
                if (existingClassUser != null )
                {
                    return new ApiResponse("用户已经在该班级中。");
                }

                await _work.GetRepository<ClassUser>().InsertAsync(
                     new ClassUser { ClassId = user.ClassId, UserId = user.UserId, EnrollmentDate = DateTime.Now });

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

		public async Task<ApiResponse> GetUserInjoinedClasses(Guid user)
		{
            try
            {
                var userInfo = await _work.GetRepository<User>().GetFirstOrDefaultAsync(predicate:
                    u => u.Id == user,include: i => i
                    .Include(u => u.UserInjoinedClass)
                        .ThenInclude(c => c.Class)
                            .ThenInclude(cs => cs.Grade));
                var schoolName = userInfo.UserInjoinedClass.First().Class.Grade.School.SchoolName;
                var userClassInfo = userInfo.UserInjoinedClass.Select(c => c.Class);
                var userClassDto = userClassInfo.Select(c => new UserClassInfoDto(c.Id, c.Index, c.Grade.GradeLevel));
                var result = new UserClassDetailInfoDto(userClassDto, schoolName);
				return ApiResponse.Success(result: result);
            }
            catch(Exception ex)
            {
                return ApiResponse.Error($"获取用户班级信息时发生错误: {ex.Message}");
            }


		}

		public Task<ApiResponse> GetUserClassRole(Guid id)
		{
			throw new NotImplementedException();
		}

		public async Task<ApiResponse> AdminAddAsync(ClassCreateDto model)
		{
			try
			{
				// 检查是否已存在相同年级下的同名班级
				var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
					predicate: c => c.Grade.GradeLevel == model.Grade.GradeLevel && (c.ClassName == model.ClassName || c.Index == model.Index));

				if (existingClass != null)
				{
					return new ApiResponse($"在当前年级下，班级 '{model.ClassName}', 序号 '{model.Index}' 已存在。 请检查你的班级名称和序号, 如有问题请联系管理员.");
				}

				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}");
			}
		}
	}
}
