import {
  Injectable,
  NotFoundException,
  ConflictException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateStudentDto } from './dto/create-student.dto';
import { UpdateStudentDto } from './dto/update-student.dto';
import * as bcrypt from 'bcrypt';

@Injectable()
export class StudentsService {
  constructor(private prisma: PrismaService) {}

  async create(
    createStudentDto: CreateStudentDto,
    tenantId: number,
    creatorId?: number,
  ) {
    // 验证行政班级是否存在且属于该租户，且是行政班级
    const classEntity = await this.prisma.class.findFirst({
      where: {
        id: createStudentDto.classId,
        tenantId,
        type: 1, // 必须是行政班级
        validState: 1,
      },
    });

    if (!classEntity) {
      throw new BadRequestException('行政班级不存在或不属于该租户');
    }

    // 检查用户名是否已存在
    const existingUser = await this.prisma.user.findFirst({
      where: {
        tenantId,
        username: createStudentDto.username,
      },
    });

    if (existingUser) {
      throw new ConflictException('用户名已存在');
    }

    // 如果提供了学号，检查学号是否已存在
    if (createStudentDto.studentNo) {
      const existingStudent = await this.prisma.student.findFirst({
        where: {
          tenantId,
          studentNo: createStudentDto.studentNo,
        },
      });

      if (existingStudent) {
        throw new ConflictException('学号已存在');
      }
    }

    // 如果提供了兴趣班，验证兴趣班是否存在且是兴趣班类型
    if (
      createStudentDto.interestClassIds &&
      createStudentDto.interestClassIds.length > 0
    ) {
      const interestClasses = await this.prisma.class.findMany({
        where: {
          id: { in: createStudentDto.interestClassIds },
          tenantId,
          type: 2, // 必须是兴趣班
          validState: 1,
        },
      });

      if (interestClasses.length !== createStudentDto.interestClassIds.length) {
        throw new NotFoundException('部分兴趣班不存在或不属于该租户');
      }
    }

    // 加密密码
    const hashedPassword = await bcrypt.hash(createStudentDto.password, 10);

    // 创建 User 记录
    const userData: any = {
      username: createStudentDto.username,
      password: hashedPassword,
      nickname: createStudentDto.nickname,
      tenantId,
    };

    if (createStudentDto.email) {
      userData.email = createStudentDto.email;
    }

    if (createStudentDto.avatar) {
      userData.avatar = createStudentDto.avatar;
    }

    if (creatorId) {
      userData.creator = creatorId;
    }

    // 创建 Student 记录
    const studentData: any = {
      classId: createStudentDto.classId,
      tenantId,
    };

    if (createStudentDto.studentNo) {
      studentData.studentNo = createStudentDto.studentNo;
    }

    if (createStudentDto.phone) {
      studentData.phone = createStudentDto.phone;
    }

    if (createStudentDto.idCard) {
      studentData.idCard = createStudentDto.idCard;
    }

    if (createStudentDto.gender) {
      studentData.gender = createStudentDto.gender;
    }

    if (createStudentDto.birthDate) {
      studentData.birthDate = new Date(createStudentDto.birthDate);
    }

    if (createStudentDto.enrollmentDate) {
      studentData.enrollmentDate = new Date(createStudentDto.enrollmentDate);
    }

    if (createStudentDto.parentName) {
      studentData.parentName = createStudentDto.parentName;
    }

    if (createStudentDto.parentPhone) {
      studentData.parentPhone = createStudentDto.parentPhone;
    }

    if (createStudentDto.address) {
      studentData.address = createStudentDto.address;
    }

    if (createStudentDto.description) {
      studentData.description = createStudentDto.description;
    }

    if (creatorId) {
      studentData.creator = creatorId;
    }

    // 使用事务创建 User、Student 和兴趣班关联
    return this.prisma.$transaction(async (tx) => {
      const user = await tx.user.create({
        data: userData,
      });

      const student = await tx.student.create({
        data: {
          ...studentData,
          userId: user.id,
        },
        include: {
          user: true,
          class: {
            include: {
              grade: true,
            },
          },
        },
      });

      // 创建兴趣班关联
      if (
        createStudentDto.interestClassIds &&
        createStudentDto.interestClassIds.length > 0
      ) {
        await tx.studentInterestClass.createMany({
          data: createStudentDto.interestClassIds.map((classId) => ({
            studentId: student.id,
            classId,
          })),
        });
      }

      // 重新查询以包含兴趣班信息
      return tx.student.findUnique({
        where: { id: student.id },
        include: {
          user: true,
          class: {
            include: {
              grade: true,
            },
          },
          interestClasses: {
            include: {
              class: {
                include: {
                  grade: true,
                },
              },
            },
          },
        },
      });
    });
  }

  async findAll(
    page: number = 1,
    pageSize: number = 10,
    tenantId?: number,
    classId?: number,
  ) {
    const skip = (page - 1) * pageSize;
    const where: any = { validState: 1 };

    if (tenantId) {
      where.tenantId = tenantId;
    }

    if (classId) {
      where.classId = classId;
    }

    const [list, total] = await Promise.all([
      this.prisma.student.findMany({
        where,
        skip,
        take: pageSize,
        orderBy: {
          createTime: 'desc',
        },
        include: {
          user: true,
          class: {
            include: {
              grade: true,
            },
          },
          interestClasses: {
            include: {
              class: {
                include: {
                  grade: true,
                },
              },
            },
          },
        },
      }),
      this.prisma.student.count({ where }),
    ]);

    return {
      list,
      total,
      page,
      pageSize,
    };
  }

  async findOne(id: number, tenantId?: number) {
    const where: any = { id, validState: 1 };
    if (tenantId) {
      where.tenantId = tenantId;
    }

    const student = await this.prisma.student.findFirst({
      where,
      include: {
        user: true,
        class: {
          include: {
            grade: true,
          },
        },
        interestClasses: {
          include: {
            class: {
              include: {
                grade: true,
              },
            },
          },
        },
      },
    });

    if (!student) {
      throw new NotFoundException('学生不存在');
    }

    return student;
  }

  async findByUserId(userId: number, tenantId?: number) {
    const where: any = { userId, validState: 1 };
    if (tenantId) {
      where.tenantId = tenantId;
    }

    const student = await this.prisma.student.findFirst({
      where,
      include: {
        user: true,
        class: {
          include: {
            grade: true,
          },
        },
        interestClasses: {
          include: {
            class: {
              include: {
                grade: true,
              },
            },
          },
        },
      },
    });

    if (!student) {
      throw new NotFoundException('学生不存在');
    }

    return student;
  }

  async update(
    id: number,
    updateStudentDto: UpdateStudentDto,
    tenantId?: number,
    modifierId?: number,
  ) {
    // 验证学生是否存在
    const existingStudent = await this.findOne(id, tenantId);

    // 如果更新行政班级，验证班级是否存在且是行政班级
    if (
      updateStudentDto.classId &&
      updateStudentDto.classId !== existingStudent.classId
    ) {
      const classEntity = await this.prisma.class.findFirst({
        where: {
          id: updateStudentDto.classId,
          tenantId: tenantId || existingStudent.tenantId,
          type: 1, // 必须是行政班级
          validState: 1,
        },
      });

      if (!classEntity) {
        throw new NotFoundException('行政班级不存在或不属于该租户');
      }
    }

    // 如果更新学号，检查是否冲突
    if (
      updateStudentDto.studentNo &&
      updateStudentDto.studentNo !== existingStudent.studentNo
    ) {
      const existingByStudentNo = await this.prisma.student.findFirst({
        where: {
          tenantId: tenantId || existingStudent.tenantId,
          studentNo: updateStudentDto.studentNo,
          id: { not: id },
        },
      });

      if (existingByStudentNo) {
        throw new ConflictException('学号已存在');
      }
    }

    // 更新 Student 记录
    const studentData: any = {};

    if (updateStudentDto.classId !== undefined) {
      studentData.classId = updateStudentDto.classId;
    }

    if (updateStudentDto.studentNo !== undefined) {
      studentData.studentNo = updateStudentDto.studentNo;
    }

    if (updateStudentDto.phone !== undefined) {
      studentData.phone = updateStudentDto.phone;
    }

    if (updateStudentDto.idCard !== undefined) {
      studentData.idCard = updateStudentDto.idCard;
    }

    if (updateStudentDto.gender !== undefined) {
      studentData.gender = updateStudentDto.gender;
    }

    if (updateStudentDto.birthDate !== undefined) {
      studentData.birthDate = new Date(updateStudentDto.birthDate);
    }

    if (updateStudentDto.enrollmentDate !== undefined) {
      studentData.enrollmentDate = new Date(updateStudentDto.enrollmentDate);
    }

    if (updateStudentDto.parentName !== undefined) {
      studentData.parentName = updateStudentDto.parentName;
    }

    if (updateStudentDto.parentPhone !== undefined) {
      studentData.parentPhone = updateStudentDto.parentPhone;
    }

    if (updateStudentDto.address !== undefined) {
      studentData.address = updateStudentDto.address;
    }

    if (updateStudentDto.description !== undefined) {
      studentData.description = updateStudentDto.description;
    }

    if (updateStudentDto.validState !== undefined) {
      studentData.validState = updateStudentDto.validState;
    }

    if (modifierId) {
      studentData.modifier = modifierId;
    }

    // 更新 User 记录
    const userData: any = {};

    if (updateStudentDto.nickname !== undefined) {
      userData.nickname = updateStudentDto.nickname;
    }

    if (updateStudentDto.email !== undefined) {
      userData.email = updateStudentDto.email;
    }

    if (updateStudentDto.avatar !== undefined) {
      userData.avatar = updateStudentDto.avatar;
    }

    if (updateStudentDto.validState !== undefined) {
      userData.validState = updateStudentDto.validState;
    }

    if (modifierId) {
      userData.modifier = modifierId;
    }

    // 使用事务更新 User、Student 和兴趣班关联
    return this.prisma.$transaction(async (tx) => {
      if (Object.keys(userData).length > 0) {
        await tx.user.update({
          where: { id: existingStudent.userId },
          data: userData,
        });
      }

      const student = await tx.student.update({
        where: { id },
        data: studentData,
      });

      // 如果提供了兴趣班ID数组，更新兴趣班关联
      if (updateStudentDto.interestClassIds !== undefined) {
        // 验证兴趣班是否存在且是兴趣班类型
        if (updateStudentDto.interestClassIds.length > 0) {
          const interestClasses = await tx.class.findMany({
            where: {
              id: { in: updateStudentDto.interestClassIds },
              tenantId: tenantId || existingStudent.tenantId,
              type: 2, // 必须是兴趣班
              validState: 1,
            },
          });

          if (
            interestClasses.length !== updateStudentDto.interestClassIds.length
          ) {
            throw new NotFoundException('部分兴趣班不存在或不属于该租户');
          }
        }

        // 删除现有关联
        await tx.studentInterestClass.deleteMany({
          where: {
            studentId: id,
          },
        });

        // 创建新关联
        if (updateStudentDto.interestClassIds.length > 0) {
          await tx.studentInterestClass.createMany({
            data: updateStudentDto.interestClassIds.map((classId) => ({
              studentId: id,
              classId,
            })),
          });
        }
      }

      // 重新查询以包含所有关联信息
      return tx.student.findUnique({
        where: { id },
        include: {
          user: true,
          class: {
            include: {
              grade: true,
            },
          },
          interestClasses: {
            include: {
              class: {
                include: {
                  grade: true,
                },
              },
            },
          },
        },
      });
    });
  }

  async remove(id: number, tenantId?: number) {
    // 验证学生是否存在
    await this.findOne(id, tenantId);

    // 删除学生会级联删除 User 和兴趣班关联（通过 Prisma schema 的 onDelete: Cascade）
    return this.prisma.student.delete({
      where: { id },
    });
  }
}
