import { Injectable, NotFoundException, ConflictException, BadRequestException } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateGradeDto } from './dto/create-grade.dto';
import { UpdateGradeDto } from './dto/update-grade.dto';

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

  async create(createGradeDto: CreateGradeDto, tenantId: number, creatorId?: number) {
    // 检查年级编码是否已存在
    const existingByCode = await this.prisma.grade.findFirst({
      where: {
        tenantId,
        code: createGradeDto.code,
      },
    });

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

    // 检查年级级别是否已存在
    const existingByLevel = await this.prisma.grade.findFirst({
      where: {
        tenantId,
        level: createGradeDto.level,
      },
    });

    if (existingByLevel) {
      throw new ConflictException('年级级别已存在');
    }

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

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

    return this.prisma.grade.create({
      data,
      include: {
        classes: {
          where: {
            validState: 1,
          },
        },
      },
    });
  }

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

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

    if (!grade) {
      throw new NotFoundException('年级不存在');
    }

    return grade;
  }

  async update(id: number, updateGradeDto: UpdateGradeDto, tenantId?: number, modifierId?: number) {
    // 验证年级是否存在
    const existingGrade = await this.findOne(id, tenantId);

    const data: any = {};

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

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

    // 如果更新级别，检查是否冲突
    if (updateGradeDto.level && updateGradeDto.level !== existingGrade.level) {
      const existingByLevel = await this.prisma.grade.findFirst({
        where: {
          tenantId: tenantId || existingGrade.tenantId,
          level: updateGradeDto.level,
          id: { not: id },
        },
      });

      if (existingByLevel) {
        throw new ConflictException('年级级别已存在');
      }
      data.level = updateGradeDto.level;
    }

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

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

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

    return this.prisma.grade.update({
      where: { id },
      data,
      include: {
        classes: {
          where: {
            validState: 1,
          },
        },
      },
    });
  }

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

    // 检查是否有班级关联
    const classCount = await this.prisma.class.count({
      where: {
        gradeId: id,
        validState: 1,
      },
    });

    if (classCount > 0) {
      throw new BadRequestException('删除年级前需先删除所有班级');
    }

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

