import {
  Injectable,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateHomeworkDto } from './dto/create-homework.dto';
import { UpdateHomeworkDto } from './dto/update-homework.dto';
import { QueryHomeworkDto } from './dto/query-homework.dto';

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

  /**
   * 创建作业
   */
  async create(
    createHomeworkDto: CreateHomeworkDto,
    tenantId: number,
    creatorId?: number,
  ) {
    const data: any = {
      tenantId,
      name: createHomeworkDto.name,
      content: createHomeworkDto.content || null,
      submitStartTime: new Date(createHomeworkDto.submitStartTime),
      submitEndTime: new Date(createHomeworkDto.submitEndTime),
      status: 'unpublished',
    };

    if (createHomeworkDto.attachments) {
      data.attachments = JSON.stringify(createHomeworkDto.attachments);
    }

    if (createHomeworkDto.publishScope) {
      data.publishScope = JSON.stringify(createHomeworkDto.publishScope);
    }

    if (createHomeworkDto.reviewRuleId) {
      data.reviewRuleId = createHomeworkDto.reviewRuleId;
    }

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

    return this.prisma.homework.create({
      data,
      include: {
        reviewRule: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });
  }

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

    const homework = await this.prisma.homework.findFirst({
      where,
      include: {
        reviewRule: {
          select: {
            id: true,
            name: true,
            description: true,
            criteria: true,
          },
        },
        _count: {
          select: {
            submissions: true,
          },
        },
      },
    });

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

    return homework;
  }

  /**
   * 更新作业
   */
  async update(
    id: number,
    updateHomeworkDto: UpdateHomeworkDto,
    tenantId?: number,
    modifierId?: number,
  ) {
    const homework = await this.findById(id, tenantId);

    // 已发布的作业不能修改
    if (homework.status === 'published') {
      throw new BadRequestException('已发布的作业不能修改');
    }

    const data: any = {};

    if (updateHomeworkDto.name !== undefined) {
      data.name = updateHomeworkDto.name;
    }
    if (updateHomeworkDto.content !== undefined) {
      data.content = updateHomeworkDto.content;
    }
    if (updateHomeworkDto.submitStartTime !== undefined) {
      data.submitStartTime = new Date(updateHomeworkDto.submitStartTime);
    }
    if (updateHomeworkDto.submitEndTime !== undefined) {
      data.submitEndTime = new Date(updateHomeworkDto.submitEndTime);
    }
    if (updateHomeworkDto.attachments !== undefined) {
      data.attachments = JSON.stringify(updateHomeworkDto.attachments);
    }
    if (updateHomeworkDto.publishScope !== undefined) {
      data.publishScope = JSON.stringify(updateHomeworkDto.publishScope);
    }
    if (updateHomeworkDto.reviewRuleId !== undefined) {
      data.reviewRuleId = updateHomeworkDto.reviewRuleId;
    }

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

    return this.prisma.homework.update({
      where: { id },
      data,
      include: {
        reviewRule: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });
  }

  /**
   * 发布作业
   */
  async publish(id: number, publishScope: number[], tenantId?: number, modifierId?: number) {
    const homework = await this.findById(id, tenantId);

    if (homework.status === 'published') {
      throw new BadRequestException('作业已发布');
    }

    if (!publishScope || publishScope.length === 0) {
      throw new BadRequestException('请选择公开范围');
    }

    return this.prisma.homework.update({
      where: { id },
      data: {
        status: 'published',
        publishTime: new Date(),
        publishScope: JSON.stringify(publishScope),
        modifier: modifierId,
      },
    });
  }

  /**
   * 取消发布作业
   */
  async unpublish(id: number, tenantId?: number, modifierId?: number) {
    const homework = await this.findById(id, tenantId);

    if (homework.status === 'unpublished') {
      throw new BadRequestException('作业未发布');
    }

    // 检查是否有提交记录
    const submissionCount = await this.prisma.homeworkSubmission.count({
      where: {
        homeworkId: id,
        validState: 1,
      },
    });

    if (submissionCount > 0) {
      throw new BadRequestException('已有学生提交作业，无法取消发布');
    }

    return this.prisma.homework.update({
      where: { id },
      data: {
        status: 'unpublished',
        publishTime: null,
        modifier: modifierId,
      },
    });
  }

  /**
   * 删除作业（软删除）
   */
  async remove(id: number, tenantId?: number) {
    const homework = await this.findById(id, tenantId);

    // 检查是否有提交记录
    const submissionCount = await this.prisma.homeworkSubmission.count({
      where: {
        homeworkId: id,
        validState: 1,
      },
    });

    if (submissionCount > 0) {
      throw new BadRequestException('已有学生提交作业，无法删除');
    }

    return this.prisma.homework.update({
      where: { id },
      data: {
        validState: 2,
      },
    });
  }

  /**
   * 分页查询作业列表
   */
  async findAll(queryDto: QueryHomeworkDto, tenantId?: number) {
    const { page = 1, pageSize = 10, name, status, submitStartTime, submitEndTime } = queryDto;
    const skip = (page - 1) * pageSize;

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

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

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

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

    if (submitStartTime && submitEndTime) {
      where.submitStartTime = {
        gte: new Date(submitStartTime),
      };
      where.submitEndTime = {
        lte: new Date(submitEndTime),
      };
    }

    const [data, total] = await Promise.all([
      this.prisma.homework.findMany({
        where,
        skip,
        take: pageSize,
        include: {
          reviewRule: {
            select: {
              id: true,
              name: true,
            },
          },
          _count: {
            select: {
              submissions: true,
            },
          },
        },
        orderBy: {
          createTime: 'desc',
        },
      }),
      this.prisma.homework.count({ where }),
    ]);

    // 解析 publishScope 并获取班级名称
    const list = await Promise.all(
      data.map(async (homework) => {
        let publishScopeNames: string[] = [];
        if (homework.publishScope) {
          try {
            const classIds = typeof homework.publishScope === 'string'
              ? JSON.parse(homework.publishScope)
              : homework.publishScope;

            if (Array.isArray(classIds) && classIds.length > 0) {
              const classes = await this.prisma.class.findMany({
                where: {
                  id: { in: classIds },
                  validState: 1,
                },
                select: {
                  id: true,
                  name: true,
                },
              });
              publishScopeNames = classes.map((c) => c.name);
            }
          } catch (e) {
            // 解析失败，保持空数组
          }
        }
        return {
          ...homework,
          publishScopeNames,
        };
      }),
    );

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

  /**
   * 获取我的作业列表（学生端）
   * 只返回已发布且对当前学生可见的作业，包含提交状态
   */
  async findMyHomeworks(queryDto: QueryHomeworkDto, tenantId: number, userId: number) {
    const { page = 1, pageSize = 10, name } = queryDto;
    const skip = (page - 1) * pageSize;

    // 获取学生信息，包括班级
    const user = await this.prisma.user.findUnique({
      where: { id: userId },
      include: {
        student: {
          select: {
            id: true,
            classId: true,
          },
        },
      },
    });

    const studentClassId = user?.student?.classId;

    // 构建查询条件
    const where: any = {
      tenantId,
      validState: 1,
      status: 'published',
    };

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

    // 查询所有已发布的作业
    const allHomeworks = await this.prisma.homework.findMany({
      where,
      orderBy: {
        createTime: 'desc',
      },
      include: {
        reviewRule: {
          select: {
            id: true,
            name: true,
          },
        },
      },
    });

    // 过滤出对当前学生可见的作业（根据 publishScope）
    const visibleHomeworks = allHomeworks.filter((homework) => {
      if (!homework.publishScope) {
        // 没有设置公开范围，不可见
        return false;
      }

      try {
        const classIds = typeof homework.publishScope === 'string'
          ? JSON.parse(homework.publishScope)
          : homework.publishScope;

        if (!Array.isArray(classIds) || classIds.length === 0) {
          return false;
        }

        // 检查学生班级是否在公开范围内
        return studentClassId && classIds.includes(studentClassId);
      } catch {
        return false;
      }
    });

    const total = visibleHomeworks.length;
    const pagedHomeworks = visibleHomeworks.slice(skip, skip + pageSize);

    // 获取学生对这些作业的提交记录
    const homeworkIds = pagedHomeworks.map((h) => h.id);
    const submissions = await this.prisma.homeworkSubmission.findMany({
      where: {
        homeworkId: { in: homeworkIds },
        studentId: userId,
        validState: 1,
      },
      select: {
        id: true,
        homeworkId: true,
        workName: true,
        submitTime: true,
        totalScore: true,
      },
    });

    // 构建提交记录映射
    const submissionMap = new Map(
      submissions.map((s) => [s.homeworkId, s]),
    );

    // 组装返回数据
    const list = pagedHomeworks.map((homework) => ({
      ...homework,
      submission: submissionMap.get(homework.id) || null,
    }));

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