import {
  Injectable,
  NotFoundException,
  BadRequestException,
  ConflictException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { QuerySubmissionDto } from './dto/query-submission.dto';
import { CreateSubmissionDto } from './dto/create-submission.dto';

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

  /**
   * 根据ID查找提交记录
   */
  async findById(id: number, tenantId?: number) {
    const where: any = { id, validState: 1 };
    if (tenantId) {
      where.tenantId = tenantId;
    }

    const submission = await this.prisma.homeworkSubmission.findFirst({
      where,
      include: {
        homework: {
          select: {
            id: true,
            name: true,
            reviewRuleId: true,
            reviewRule: {
              select: {
                id: true,
                name: true,
                criteria: true,
              },
            },
          },
        },
        student: {
          select: {
            id: true,
            username: true,
            nickname: true,
            student: {
              select: {
                id: true,
                studentNo: true,
                class: {
                  select: {
                    id: true,
                    name: true,
                    grade: {
                      select: {
                        id: true,
                        name: true,
                      },
                    },
                  },
                },
              },
            },
          },
        },
        scores: {
          where: { validState: 1 },
          include: {
            reviewer: {
              select: {
                id: true,
                nickname: true,
              },
            },
          },
        },
      },
    });

    if (!submission) {
      throw new NotFoundException('提交记录不存在');
    }

    return submission;
  }

  /**
   * 分页查询提交记录列表
   */
  async findAll(queryDto: QuerySubmissionDto, tenantId?: number) {
    const {
      page = 1,
      pageSize = 10,
      homeworkId,
      workNo,
      workName,
      studentAccount,
      studentName,
      status,
      classIds,
      gradeId,
    } = queryDto;
    const skip = (page - 1) * pageSize;

    const where: any = {
      validState: 1,
    };

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

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

    if (workNo) {
      where.workNo = {
        contains: workNo,
      };
    }

    if (workName) {
      where.workName = {
        contains: workName,
      };
    }

    if (studentAccount || studentName || classIds || gradeId) {
      where.student = {};

      if (studentAccount) {
        where.student.username = {
          contains: studentAccount,
        };
      }

      if (studentName) {
        where.student.nickname = {
          contains: studentName,
        };
      }

      if (classIds && classIds.length > 0) {
        where.student.student = {
          classId: {
            in: classIds,
          },
        };
      } else if (gradeId) {
        where.student.student = {
          class: {
            gradeId: gradeId,
          },
        };
      }
    }

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

    const [data, total] = await Promise.all([
      this.prisma.homeworkSubmission.findMany({
        where,
        skip,
        take: pageSize,
        include: {
          homework: {
            select: {
              id: true,
              name: true,
            },
          },
          student: {
            select: {
              id: true,
              username: true,
              nickname: true,
              student: {
                select: {
                  studentNo: true,
                  class: {
                    select: {
                      id: true,
                      name: true,
                      grade: {
                        select: {
                          id: true,
                          name: true,
                        },
                      },
                    },
                  },
                },
              },
            },
          },
          _count: {
            select: {
              scores: true,
            },
          },
        },
        orderBy: {
          submitTime: 'desc',
        },
      }),
      this.prisma.homeworkSubmission.count({ where }),
    ]);

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

  /**
   * 获取班级树结构（用于左侧筛选）
   */
  async getClassTree(tenantId: number) {
    const grades = await this.prisma.grade.findMany({
      where: {
        tenantId,
        validState: 1,
      },
      include: {
        classes: {
          where: {
            validState: 1,
            type: 1, // 只获取行政班级
          },
          select: {
            id: true,
            name: true,
            code: true,
          },
          orderBy: {
            code: 'asc',
          },
        },
      },
      orderBy: {
        level: 'asc',
      },
    });

    return grades.map((grade) => ({
      id: `grade_${grade.id}`,
      name: grade.name,
      type: 'grade',
      gradeId: grade.id,
      children: grade.classes.map((cls) => ({
        id: cls.id,
        name: cls.name,
        type: 'class',
        classId: cls.id,
      })),
    }));
  }

  /**
   * 根据学生ID和作业ID查找提交记录
   */
  async findByStudentAndHomework(
    studentId: number,
    homeworkId: number,
    tenantId: number,
  ) {
    const submission = await this.prisma.homeworkSubmission.findFirst({
      where: {
        studentId,
        homeworkId,
        tenantId,
        validState: 1,
      },
      include: {
        homework: {
          select: {
            id: true,
            name: true,
            reviewRuleId: true,
            reviewRule: {
              select: {
                id: true,
                name: true,
                criteria: true,
              },
            },
          },
        },
        scores: {
          where: { validState: 1 },
          include: {
            reviewer: {
              select: {
                id: true,
                nickname: true,
              },
            },
          },
        },
      },
    });

    if (!submission) {
      throw new NotFoundException('未找到提交记录');
    }

    return submission;
  }

  /**
   * 创建提交记录（学生提交作业）
   */
  async create(
    createDto: CreateSubmissionDto,
    studentId: number,
    tenantId: number,
  ) {
    const { homeworkId, workName, workDescription, files } = createDto;

    // 检查作业是否存在且已发布
    const homework = await this.prisma.homework.findFirst({
      where: {
        id: homeworkId,
        tenantId,
        validState: 1,
        status: 'published',
      },
    });

    if (!homework) {
      throw new NotFoundException('作业不存在或未发布');
    }

    // 检查是否在提交时间范围内
    const now = new Date();
    if (now < new Date(homework.submitStartTime)) {
      throw new BadRequestException('作业提交尚未开始');
    }
    if (now > new Date(homework.submitEndTime)) {
      throw new BadRequestException('作业提交已截止');
    }

    // 检查学生是否已提交
    const existingSubmission = await this.prisma.homeworkSubmission.findFirst({
      where: {
        homeworkId,
        studentId,
        tenantId,
        validState: 1,
      },
    });

    if (existingSubmission) {
      throw new ConflictException('您已提交过该作业');
    }

    // 生成作品编号
    const workNo = await this.generateWorkNo(tenantId);

    // 创建提交记录
    const submission = await this.prisma.homeworkSubmission.create({
      data: {
        tenantId,
        homeworkId,
        studentId,
        workNo,
        workName,
        workDescription,
        files: files ? JSON.stringify(files) : null,
        submitTime: now,
        status: 'pending',
        creator: studentId,
        modifier: studentId,
        createTime: now,
        modifyTime: now,
        validState: 1,
      },
      include: {
        homework: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });

    return submission;
  }

  /**
   * 生成作品编号
   */
  private async generateWorkNo(tenantId: number): Promise<string> {
    const today = new Date();
    const dateStr = today.toISOString().slice(0, 10).replace(/-/g, '');

    // 获取今天的提交数量
    const count = await this.prisma.homeworkSubmission.count({
      where: {
        tenantId,
        workNo: {
          startsWith: `HW${dateStr}`,
        },
      },
    });

    const seq = String(count + 1).padStart(4, '0');
    return `HW${dateStr}${seq}`;
  }
}
