import { Injectable, NotFoundException, ConflictException, BadRequestException } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateClassDto } from './dto/create-class.dto';
import { UpdateClassDto } from './dto/update-class.dto';

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

  async create(createClassDto: CreateClassDto, tenantId: number, creatorId?: number) {
    // 验证年级是否存在且属于该租户
    const grade = await this.prisma.grade.findFirst({
      where: {
        id: createClassDto.gradeId,
        tenantId,
        validState: 1,
      },
    });

    if (!grade) {
      throw new NotFoundException('年级不存在或不属于该租户');
    }

    // 检查班级编码是否已存在
    const existingByCode = await this.prisma.class.findFirst({
      where: {
        tenantId,
        code: createClassDto.code,
      },
    });

    if (existingByCode) {
      throw new ConflictException('班级编码已存在');
    }

    const data: any = {
      ...createClassDto,
      tenantId,
    };

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

    return this.prisma.class.create({
      data,
      include: {
        grade: true,
        _count: {
          select: {
            students: {
              where: {
                validState: 1,
              },
            },
            studentInterestClasses: true,
          },
        },
      },
    });
  }

  async findAll(
    page: number = 1,
    pageSize: number = 10,
    tenantId?: number,
    gradeId?: number,
    type?: number,
  ) {
    const skip = (page - 1) * pageSize;
    const where: any = { validState: 1 };
    
    if (tenantId) {
      where.tenantId = tenantId;
    }
    
    if (gradeId) {
      where.gradeId = gradeId;
    }
    
    if (type !== undefined) {
      where.type = type;
    }

    const [list, total] = await Promise.all([
      this.prisma.class.findMany({
        where,
        skip,
        take: pageSize,
        orderBy: [
          { grade: { level: 'asc' } },
          { name: 'asc' },
        ],
        include: {
          grade: true,
          _count: {
            select: {
              students: {
                where: {
                  validState: 1,
                },
              },
              studentInterestClasses: true,
            },
          },
        },
      }),
      this.prisma.class.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 classEntity = await this.prisma.class.findFirst({
      where,
      include: {
        grade: true,
        students: {
          where: {
            validState: 1,
          },
          include: {
            user: true,
          },
        },
        studentInterestClasses: {
          include: {
            student: {
              include: {
                user: true,
              },
            },
          },
        },
      },
    });

    if (!classEntity) {
      throw new NotFoundException('班级不存在');
    }

    return classEntity;
  }

  async update(id: number, updateClassDto: UpdateClassDto, tenantId?: number, modifierId?: number) {
    // 验证班级是否存在
    const existingClass = await this.findOne(id, tenantId);

    const data: any = {};

    // 如果更新年级，验证年级是否存在
    if (updateClassDto.gradeId && updateClassDto.gradeId !== existingClass.gradeId) {
      const grade = await this.prisma.grade.findFirst({
        where: {
          id: updateClassDto.gradeId,
          tenantId: tenantId || existingClass.tenantId,
          validState: 1,
        },
      });

      if (!grade) {
        throw new NotFoundException('年级不存在或不属于该租户');
      }
      data.gradeId = updateClassDto.gradeId;
    }

    // 如果更新编码，检查是否冲突
    if (updateClassDto.code && updateClassDto.code !== existingClass.code) {
      const existingByCode = await this.prisma.class.findFirst({
        where: {
          tenantId: tenantId || existingClass.tenantId,
          code: updateClassDto.code,
          id: { not: id },
        },
      });

      if (existingByCode) {
        throw new ConflictException('班级编码已存在');
      }
      data.code = updateClassDto.code;
    }

    if (updateClassDto.name) {
      data.name = updateClassDto.name;
    }

    if (updateClassDto.type !== undefined) {
      // 如果从行政班级改为兴趣班，需要检查是否有学生
      if (existingClass.type === 1 && updateClassDto.type === 2) {
        const studentCount = await this.prisma.student.count({
          where: {
            classId: id,
            validState: 1,
          },
        });

        if (studentCount > 0) {
          throw new BadRequestException('无法将包含学生的行政班级改为兴趣班');
        }
      }
      data.type = updateClassDto.type;
    }

    if (updateClassDto.capacity !== undefined) {
      data.capacity = updateClassDto.capacity;
    }

    if (updateClassDto.description !== undefined) {
      data.description = updateClassDto.description;
    }

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

    return this.prisma.class.update({
      where: { id },
      data,
      include: {
        grade: true,
        _count: {
          select: {
            students: {
              where: {
                validState: 1,
              },
            },
            studentInterestClasses: true,
          },
        },
      },
    });
  }

  async remove(id: number, tenantId?: number) {
    // 验证班级是否存在
    const classEntity = await this.findOne(id, tenantId);

    // 如果是行政班级，检查是否有学生
    if (classEntity.type === 1) {
      const studentCount = await this.prisma.student.count({
        where: {
          classId: id,
          validState: 1,
        },
      });

      if (studentCount > 0) {
        throw new BadRequestException('删除班级前需先转移或删除所有学生');
      }
    }

    // 如果是兴趣班，删除关联关系
    if (classEntity.type === 2) {
      await this.prisma.studentInterestClass.deleteMany({
        where: {
          classId: id,
        },
      });
    }

    // 软删除
    return this.prisma.class.update({
      where: { id },
      data: {
        validState: 2,
      },
    });
  }
}

