import {
  Injectable,
  NotFoundException,
  BadRequestException,
  ConflictException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { SubmitWorkDto } from './dto/submit-work.dto';
import { QueryWorkDto } from './dto/query-work.dto';

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

  async submit(
    submitWorkDto: SubmitWorkDto,
    tenantId: number,
    submitterUserId: number,
  ) {
    // 验证报名记录是否存在
    const registration = await this.prisma.contestRegistration.findUnique({
      where: { id: submitWorkDto.registrationId },
      include: {
        contest: true,
      },
    });

    if (!registration) {
      throw new NotFoundException('报名记录不存在');
    }

    if (registration.tenantId !== tenantId) {
      throw new BadRequestException('报名记录不属于当前租户');
    }

    // 检查报名状态
    if (registration.registrationState !== 'passed') {
      throw new BadRequestException('报名未通过审核，无法提交作品');
    }

    // 检查提交时间
    const now = new Date();
    if (
      now < registration.contest.submitStartTime ||
      now > registration.contest.submitEndTime
    ) {
      throw new BadRequestException('不在作品提交时间范围内');
    }

    // 检查提交规则
    const existingWorks = await this.prisma.contestWork.findMany({
      where: {
        registrationId: submitWorkDto.registrationId,
        validState: 1,
      },
      orderBy: {
        version: 'desc',
      },
    });

    if (
      registration.contest.submitRule === 'once' &&
      existingWorks.length > 0
    ) {
      throw new ConflictException('该活动只允许提交一次作品');
    }

    // 如果已有作品，将旧版本标记为非最新
    if (existingWorks.length > 0) {
      await this.prisma.contestWork.updateMany({
        where: {
          registrationId: submitWorkDto.registrationId,
          validState: 1,
        },
        data: {
          isLatest: false,
        },
      });
    }

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

    // 获取提交人信息（必须包含租户ID以确保多租户隔离）
    if (!submitterUserId) {
      throw new BadRequestException('提交人ID不能为空');
    }

    const submitter = await this.prisma.user.findFirst({
      where: {
        id: submitterUserId,
        tenantId,
        validState: 1,
      },
    });

    if (!submitter) {
      throw new NotFoundException('提交人不存在或不属于当前租户');
    }

    // 创建新版本作品
    const data: any = {
      tenantId,
      contestId: registration.contestId,
      registrationId: submitWorkDto.registrationId,
      workNo,
      title: submitWorkDto.title,
      description: submitWorkDto.description,
      files: submitWorkDto.files || null,
      version: existingWorks.length > 0 ? existingWorks[0].version + 1 : 1,
      isLatest: true,
      status: 'submitted',
      submitTime: new Date(),
      submitterUserId,
      submitterAccountNo: submitter?.username,
      submitSource: 'student', // 可以根据实际情况判断
      previewUrl: submitWorkDto.previewUrl,
      previewUrls: submitWorkDto.previewUrls || null,
      aiModelMeta: submitWorkDto.aiModelMeta || null,
      creator: submitterUserId,
    };

    // 使用事务创建作品和附件
    return this.prisma.$transaction(async (tx) => {
      const work = await tx.contestWork.create({
        data,
      });

      // 创建附件记录
      if (submitWorkDto.attachments && submitWorkDto.attachments.length > 0) {
        for (const attachment of submitWorkDto.attachments) {
          await tx.contestWorkAttachment.create({
            data: {
              tenantId,
              contestId: registration.contestId,
              workId: work.id,
              fileName: attachment.fileName,
              fileUrl: attachment.fileUrl,
              fileType: attachment.fileType,
              size: attachment.size,
              creator: submitterUserId,
            },
          });
        }
      }

      // 返回完整的作品信息
      return tx.contestWork.findUnique({
        where: { id: work.id },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
            },
          },
          registration: {
            include: {
              user: {
                select: {
                  id: true,
                  username: true,
                  nickname: true,
                },
              },
            },
          },
          attachments: true,
        },
      });
    });
  }

  /**
   * 生成作品编号
   */
  private async generateWorkNo(
    contestId: number,
    tenantId: number,
  ): Promise<string> {
    const prefix = `WORK-${contestId}-${tenantId}-`;
    const count = await this.prisma.contestWork.count({
      where: {
        contestId,
        tenantId,
      },
    });

    return `${prefix}${String(count + 1).padStart(6, '0')}`;
  }

  /**
   * 作品统计（仅超管）
   */
  async getStats(contestId?: number) {
    const baseWhere: any = { validState: 1, isLatest: true };
    if (contestId) baseWhere.contestId = contestId;

    const [total, submitted, reviewing] = await Promise.all([
      this.prisma.contestWork.count({ where: baseWhere }),
      this.prisma.contestWork.count({ where: { ...baseWhere, status: 'submitted' } }),
      this.prisma.contestWork.count({ where: { ...baseWhere, status: 'reviewing' } }),
    ]);

    // reviewed = 有评分记录的作品
    const reviewed = await this.prisma.contestWork.count({
      where: {
        ...baseWhere,
        scores: { some: { validState: 1 } },
      },
    });

    return { total, submitted: total - reviewing - reviewed, reviewing, reviewed };
  }

  async findAll(queryDto: QueryWorkDto, tenantId?: number) {
    const {
      page = 1,
      pageSize = 10,
      contestId,
      registrationId,
      status,
      title,
      workNo,
      username,
      keyword,
    } = queryDto;
    const skip = (page - 1) * pageSize;

    // 检查是否为超级租户
    let isSuper = false;
    if (tenantId) {
      const tenant = await this.prisma.tenant.findUnique({
        where: { id: tenantId },
        select: { isSuper: true },
      });
      isSuper = tenant?.isSuper === 1;
    }

    const where: any = {
      validState: 1,
      isLatest: true, // 默认只查询最新版本
    };

    // 超级租户可以看到所有作品，普通租户只能看到自己租户的作品
    if (tenantId && !isSuper) {
      where.tenantId = tenantId;
    }

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

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

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

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

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

    if (username) {
      where.OR = [
        {
          submitterAccountNo: {
            contains: username,
          },
        },
        {
          registration: {
            user: {
              username: {
                contains: username,
              },
            },
          },
        },
      ];
    }

    // keyword: 搜索作品编号、提交者姓名
    if (keyword && !username) {
      where.OR = [
        { workNo: { contains: keyword } },
        { submitterAccountNo: { contains: keyword } },
        { registration: { user: { nickname: { contains: keyword } } } },
        { registration: { user: { username: { contains: keyword } } } },
        { registration: { team: { teamName: { contains: keyword } } } },
      ];
    }

    const [list, total] = await Promise.all([
      this.prisma.contestWork.findMany({
        where,
        skip,
        take: pageSize,
        orderBy: {
          submitTime: 'desc',
        },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
              reviewRuleId: true,
              reviewRule: {
                select: {
                  judgeCount: true,
                },
              },
            },
          },
          registration: {
            include: {
              user: {
                select: {
                  id: true,
                  username: true,
                  nickname: true,
                },
              },
              team: {
                select: {
                  id: true,
                  teamName: true,
                },
              },
            },
          },
          attachments: true,
          scores: {
            where: { validState: 1 },
            select: {
              id: true,
              totalScore: true,
            },
          },
          assignments: {
            include: {
              judge: {
                select: {
                  id: true,
                  username: true,
                  nickname: true,
                },
              },
            },
          },
          _count: {
            select: {
              scores: true,
              assignments: true,
            },
          },
        },
      }),
      this.prisma.contestWork.count({ where }),
    ]);

    // 计算评审统计数据
    const enrichedList = list.map((work) => {
      const reviewedCount = work._count?.scores || 0;
      const totalJudgesCount =
        work.contest?.reviewRule?.judgeCount || work._count?.assignments || 0;

      // 计算平均分
      let averageScore: number | null = null;
      if (work.scores && work.scores.length > 0) {
        const totalScore = work.scores.reduce(
          (sum, score) => sum + Number(score.totalScore || 0),
          0,
        );
        averageScore = totalScore / work.scores.length;
      }

      return {
        ...work,
        reviewedCount,
        totalJudgesCount,
        averageScore,
      };
    });

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

  async findOne(id: number, tenantId?: number) {
    // 检查是否为超级租户
    let isSuper = false;
    if (tenantId) {
      const tenant = await this.prisma.tenant.findUnique({
        where: { id: tenantId },
        select: { isSuper: true },
      });
      isSuper = tenant?.isSuper === 1;
    }

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

    // 超级租户可以查看所有作品
    if (tenantId && !isSuper) {
      where.tenantId = tenantId;
    }

    const work = await this.prisma.contestWork.findFirst({
      where,
      include: {
        contest: true,
        registration: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
            team: {
              include: {
                members: {
                  include: {
                    user: {
                      select: {
                        id: true,
                        username: true,
                        nickname: true,
                      },
                    },
                  },
                },
              },
            },
          },
        },
        attachments: true,
        assignments: {
          include: {
            judge: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
          },
        },
        scores: {
          where: { validState: 1 },
          include: {
            judge: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
          },
        },
      },
    });

    if (!work) {
      throw new NotFoundException('作品不存在');
    }

    return work;
  }

  async getVersions(registrationId: number, tenantId?: number) {
    const where: any = {
      registrationId,
      validState: 1,
    };

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

    return this.prisma.contestWork.findMany({
      where,
      orderBy: {
        version: 'desc',
      },
      include: {
        attachments: true,
        _count: {
          select: {
            scores: true,
          },
        },
      },
    });
  }

  async remove(id: number, tenantId?: number) {
    await this.findOne(id, tenantId);

    // 检查是否已有评分
    const scoreCount = await this.prisma.contestWorkScore.count({
      where: { workId: id },
    });

    if (scoreCount > 0) {
      throw new BadRequestException('作品已有评分，无法删除');
    }

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

  /**
   * 获取教师指导的作品列表
   * @param queryDto 查询参数
   * @param tenantId 租户ID
   * @param teacherUserId 教师用户ID
   */
  async findGuidedWorks(
    queryDto: {
      page?: number;
      pageSize?: number;
      contestId?: number;
      workNo?: string;
      playerName?: string;
      accountNo?: string;
    },
    tenantId: number,
    teacherUserId: number,
  ) {
    const {
      page = 1,
      pageSize = 10,
      contestId,
      workNo,
      playerName,
      accountNo,
    } = queryDto;
    const skip = (page - 1) * pageSize;

    // 首先获取该教师指导的所有报名记录ID
    const teacherRegistrations = await this.prisma.contestRegistrationTeacher.findMany({
      where: {
        userId: teacherUserId,
        ...(tenantId && { tenantId }),
      },
      select: {
        registrationId: true,
      },
    });

    const registrationIds = teacherRegistrations.map((r) => r.registrationId);

    if (registrationIds.length === 0) {
      return {
        list: [],
        total: 0,
        page,
        pageSize,
      };
    }

    // 构建查询条件
    const where: any = {
      validState: 1,
      isLatest: true,
      registrationId: { in: registrationIds },
    };

    if (contestId) {
      where.contestId = Number(contestId);
    }

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

    // 处理选手姓名和报名账号的查询
    if (playerName || accountNo) {
      const userConditions: any = {};
      if (playerName) {
        userConditions.nickname = { contains: playerName };
      }
      if (accountNo) {
        userConditions.username = { contains: accountNo };
      }
      where.registration = {
        user: userConditions,
      };
    }

    const [list, total] = await Promise.all([
      this.prisma.contestWork.findMany({
        where,
        skip,
        take: pageSize,
        orderBy: {
          submitTime: 'desc',
        },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
              reviewRuleId: true,
              reviewRule: {
                select: {
                  judgeCount: true,
                },
              },
            },
          },
          registration: {
            include: {
              user: {
                select: {
                  id: true,
                  username: true,
                  nickname: true,
                },
              },
            },
          },
          scores: {
            where: { validState: 1 },
            select: {
              id: true,
              totalScore: true,
            },
          },
          _count: {
            select: {
              scores: true,
              assignments: true,
            },
          },
        },
      }),
      this.prisma.contestWork.count({ where }),
    ]);

    // 计算评审进度
    const enrichedList = list.map((work) => {
      const reviewedCount = work._count?.scores || 0;
      const totalJudgesCount =
        work.contest?.reviewRule?.judgeCount || work._count?.assignments || 0;

      return {
        ...work,
        reviewedCount,
        totalJudgesCount,
        reviewProgress: totalJudgesCount > 0
          ? `${reviewedCount}/${totalJudgesCount}`
          : '未分配',
      };
    });

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