import {
  Injectable,
  NotFoundException,
  ConflictException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateRegistrationDto } from './dto/create-registration.dto';
import { ReviewRegistrationDto } from './dto/review-registration.dto';
import { QueryRegistrationDto } from './dto/query-registration.dto';

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

  async create(
    createRegistrationDto: CreateRegistrationDto,
    tenantId: number,
    creatorId?: number,
  ) {
    // 验证活动是否存在
    const contest = await this.prisma.contest.findUnique({
      where: { id: createRegistrationDto.contestId },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    // 检查活动是否已发布
    if (contest.contestState !== 'published') {
      throw new BadRequestException('活动未发布，无法报名');
    }

    // 检查报名时间
    const now = new Date();
    if (now < contest.registerStartTime || now > contest.registerEndTime) {
      throw new BadRequestException('不在报名时间范围内');
    }

    // 验证用户是否存在
    const user = await this.prisma.user.findUnique({
      where: { id: createRegistrationDto.userId },
    });

    if (!user) {
      throw new NotFoundException('用户不存在');
    }

    // 检查用户是否已报名（个人参与）
    if (createRegistrationDto.registrationType === 'individual') {
      const existing = await this.prisma.contestRegistration.findFirst({
        where: {
          contestId: createRegistrationDto.contestId,
          userId: createRegistrationDto.userId,
          registrationType: 'individual',
        },
      });

      if (existing) {
        throw new ConflictException('您已报名该活动');
      }
    }

    // 团队参与验证
    if (createRegistrationDto.registrationType === 'team') {
      if (!createRegistrationDto.teamId) {
        throw new BadRequestException('团队参与必须指定团队ID');
      }

      const team = await this.prisma.contestTeam.findUnique({
        where: { id: createRegistrationDto.teamId },
        include: {
          members: true,
        },
      });

      if (!team) {
        throw new NotFoundException('团队不存在');
      }

      if (team.tenantId !== tenantId) {
        throw new BadRequestException('团队不属于当前租户');
      }

      if (team.contestId !== createRegistrationDto.contestId) {
        throw new BadRequestException('团队不属于该活动');
      }

      // 检查用户是否是团队成员
      const isMember = team.members.some(
        (m) => m.userId === createRegistrationDto.userId,
      );

      if (!isMember) {
        throw new BadRequestException('您不是该团队成员');
      }
    }

    // 获取用户账号信息快照
    const accountNo = user.username;
    const accountName = user.nickname;

    // 检查当前登录用户是否是老师，如果是则设置为指导老师（registrant）
    let registrantId = createRegistrationDto.userId;
    if (creatorId) {
      // 检查创建者是否是老师
      const creator = await this.prisma.user.findUnique({
        where: { id: creatorId },
        include: {
          teacher: true,
        },
      });
      
      // 如果创建者是老师，则设置为指导老师
      if (creator?.teacher) {
        registrantId = creatorId;
      }
    }

    const data: any = {
      contestId: createRegistrationDto.contestId,
      tenantId,
      registrationType: createRegistrationDto.registrationType,
      teamId: createRegistrationDto.teamId || null,
      teamName:
        createRegistrationDto.registrationType === 'team'
          ? (await this.prisma.contestTeam.findUnique({
              where: { id: createRegistrationDto.teamId },
            }))?.teamName
          : null,
      userId: createRegistrationDto.userId,
      accountNo,
      accountName,
      registrationState: 'pending',
      registrationTime: new Date(),
      registrant: registrantId,
    };

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

    // 使用事务创建报名记录和默认指导老师
    return this.prisma.$transaction(async (tx) => {
      // 如果创建者是老师，先检查并创建默认指导老师关联
      let shouldCreateDefaultTeacher = false;
      if (creatorId) {
        const creator = await tx.user.findUnique({
          where: { id: creatorId },
          include: { teacher: true },
        });

        if (creator?.teacher) {
          shouldCreateDefaultTeacher = true;
        }
      }

      // 创建报名记录
      const registration = await tx.contestRegistration.create({
        data,
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
              contestType: true,
            },
          },
          user: {
            select: {
              id: true,
              username: true,
              nickname: true,
            },
          },
          team: createRegistrationDto.registrationType === 'team'
            ? {
                include: {
                  members: {
                    include: {
                      user: {
                        select: {
                          id: true,
                          username: true,
                          nickname: true,
                        },
                      },
                    },
                  },
                },
              }
            : false,
        },
      });

      // 如果创建者是老师，自动添加为默认指导老师
      if (shouldCreateDefaultTeacher && creatorId) {
        try {
          await tx.contestRegistrationTeacher.create({
            data: {
              registrationId: registration.id,
              tenantId,
              userId: creatorId,
              isDefault: true,
              creator: creatorId,
            },
          });
        } catch (error) {
          // 如果创建失败（可能是重复），记录日志但不影响主流程
          console.error('创建默认指导老师失败:', error);
        }
      }

      // 重新查询包含指导老师信息
      return tx.contestRegistration.findUnique({
        where: { id: registration.id },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
              contestType: true,
            },
          },
          user: {
            select: {
              id: true,
              username: true,
              nickname: true,
            },
          },
          teachers: {
            include: {
              user: {
                select: {
                  id: true,
                  username: true,
                  nickname: true,
                },
              },
            },
          },
          team: createRegistrationDto.registrationType === 'team'
            ? {
                include: {
                  members: {
                    include: {
                      user: {
                        select: {
                          id: true,
                          username: true,
                          nickname: true,
                        },
                      },
                    },
                  },
                },
              }
            : false,
        },
      });
    });
  }

  /**
   * 报名统计（仅超管）
   */
  async getStats(contestId?: number) {
    const baseWhere: any = {};
    if (contestId) {
      baseWhere.contestId = contestId;
    }

    const [total, pending, passed, rejected] = await Promise.all([
      this.prisma.contestRegistration.count({ where: baseWhere }),
      this.prisma.contestRegistration.count({ where: { ...baseWhere, registrationState: 'pending' } }),
      this.prisma.contestRegistration.count({ where: { ...baseWhere, registrationState: 'passed' } }),
      this.prisma.contestRegistration.count({ where: { ...baseWhere, registrationState: 'rejected' } }),
    ]);

    return { total, pending, passed, rejected };
  }

  async findAll(queryDto: QueryRegistrationDto, tenantId?: number) {
    const {
      page = 1,
      pageSize = 10,
      contestId,
      registrationState,
      registrationType,
      userId,
      participantType,
      keyword,
    } = queryDto;
    const skip = (page - 1) * pageSize;

    const where: any = {};

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

    // 超管可以看到所有报名记录（不区分租户）
    // 普通租户只能看到自己租户的报名记录
    if (tenantId && !isSuper) {
      where.tenantId = tenantId;
    }

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

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

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

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

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

    // 关键词搜索：参与者姓名、手机号、子女姓名
    if (keyword) {
      where.OR = [
        { user: { nickname: { contains: keyword } } },
        { user: { phone: { contains: keyword } } },
        { accountName: { contains: keyword } },
        { child: { name: { contains: keyword } } },
      ];
    }

    const [list, total] = await Promise.all([
      this.prisma.contestRegistration.findMany({
        where,
        skip,
        take: pageSize,
        orderBy: {
          registrationTime: 'desc',
        },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
              contestType: true,
            },
          },
          user: {
            include: {
              tenant: {
                select: {
                  id: true,
                  name: true,
                },
              },
              student: {
                include: {
                  class: {
                    include: {
                      grade: {
                        select: {
                          id: true,
                          name: true,
                        },
                      },
                    },
                  },
                },
              },
            },
          },
          child: {
            select: {
              id: true,
              name: true,
              grade: true,
              city: true,
              schoolName: true,
            },
          },
          teachers: {
            include: {
              user: {
                select: {
                  id: true,
                  username: true,
                  nickname: true,
                },
              },
            },
          },
          team: {
            include: {
              members: {
                include: {
                  user: {
                    select: {
                      id: true,
                      username: true,
                      nickname: true,
                    },
                  },
                },
              },
            },
          },
          _count: {
            select: {
              works: true,
            },
          },
        },
      }),
      this.prisma.contestRegistration.count({ where }),
    ]);

    return {
      list,
      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 };
    // 超管可以查看所有报名记录，普通租户只能查看自己租户的报名
    if (tenantId && !isSuper) {
      where.tenantId = tenantId;
    }

    const registration = await this.prisma.contestRegistration.findFirst({
      where,
      include: {
        contest: true,
        user: {
          include: {
            tenant: {
              select: {
                id: true,
                name: true,
              },
            },
            student: {
              include: {
                class: {
                  include: {
                    grade: {
                      select: {
                        id: true,
                        name: true,
                      },
                    },
                  },
                },
              },
            },
          },
        },
        team: {
          include: {
            members: {
              include: {
                user: {
                  select: {
                    id: true,
                    username: true,
                    nickname: true,
                  },
                },
              },
            },
          },
        },
        teachers: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
          },
        },
        works: {
          where: { validState: 1 },
          orderBy: {
            submitTime: 'desc',
          },
        },
      },
    });

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

    return registration;
  }

  async review(
    id: number,
    reviewDto: ReviewRegistrationDto,
    operatorId: number,
    tenantId?: number,
  ) {
    const registration = await this.findOne(id, tenantId);

    if (registration.registrationState !== 'pending') {
      throw new BadRequestException('只能审核待审核状态的报名');
    }

    return this.prisma.contestRegistration.update({
      where: { id },
      data: {
        registrationState: reviewDto.registrationState,
        reason: reviewDto.reason,
        operator: operatorId,
        operationDate: new Date(),
        modifier: operatorId,
      },
      include: {
        contest: {
          select: {
            id: true,
            contestName: true,
          },
        },
        user: {
          select: {
            id: true,
            username: true,
            nickname: true,
          },
        },
      },
    });
  }

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

    // 检查是否有作品
    const workCount = await this.prisma.contestWork.count({
      where: { registrationId: id },
    });

    if (workCount > 0) {
      throw new BadRequestException('该报名已有作品，无法删除');
    }

    return this.prisma.contestRegistration.delete({
      where: { id },
    });
  }

  async addTeacher(
    registrationId: number,
    teacherUserId: number,
    tenantId: number,
    creatorId?: number,
  ) {
    // 验证报名记录是否存在
    const registration = await this.prisma.contestRegistration.findFirst({
      where: {
        id: registrationId,
        tenantId,
      },
    });

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

    // 验证用户是否是老师
    const teacher = await this.prisma.user.findUnique({
      where: { id: teacherUserId },
      include: { teacher: true },
    });

    if (!teacher?.teacher) {
      throw new BadRequestException('该用户不是老师');
    }

    // 检查是否已经添加过
    const existing = await this.prisma.contestRegistrationTeacher.findFirst({
      where: {
        registrationId,
        userId: teacherUserId,
        tenantId,
      },
    });

    if (existing) {
      throw new ConflictException('该老师已经添加过了');
    }

    // 添加指导老师
    return this.prisma.contestRegistrationTeacher.create({
      data: {
        registrationId,
        tenantId,
        userId: teacherUserId,
        isDefault: false,
        creator: creatorId,
      },
      include: {
        user: {
          select: {
            id: true,
            username: true,
            nickname: true,
          },
        },
      },
    });
  }

  async removeTeacher(
    registrationId: number,
    teacherUserId: number,
    tenantId: number,
  ) {
    // 查找指导老师记录
    const teacherRecord = await this.prisma.contestRegistrationTeacher.findFirst({
      where: {
        registrationId,
        userId: teacherUserId,
        tenantId,
      },
    });

    if (!teacherRecord) {
      throw new NotFoundException('指导老师记录不存在');
    }

    // 如果是默认指导老师，不能移除
    if (teacherRecord.isDefault) {
      throw new BadRequestException('默认指导老师不能移除');
    }

    // 删除指导老师
    return this.prisma.contestRegistrationTeacher.delete({
      where: { id: teacherRecord.id },
    });
  }

  /**
   * 获取用户在某活动中的报名记录（包括作为团队成员的情况）
   * @param contestId 活动ID
   * @param userId 用户ID
   * @returns 报名记录或null
   */
  async getMyRegistration(contestId: number, userId: number) {
    try {
      // 1. 先查询个人参与报名（直接按 userId 匹配）
      const individualReg = await this.prisma.contestRegistration.findFirst({
        where: {
          contestId,
          userId,
          registrationType: 'individual',
          registrationState: 'passed',
        },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
              contestType: true,
            },
          },
          works: {
            where: { validState: 1, isLatest: true },
            orderBy: { submitTime: 'desc' },
          },
        },
      });

      if (individualReg) {
        return individualReg;
      }

      // 2. 查询用户所属的团队（该活动的）
      const teamMemberships = await this.prisma.contestTeamMember.findMany({
        where: {
          userId,
        },
        select: {
          teamId: true,
          team: {
            select: {
              id: true,
              contestId: true,
              validState: true,
            },
          },
        },
      });

      // 过滤出该活动且有效的团队
      const validTeamIds = teamMemberships
        .filter((m) => m.team?.contestId === contestId && m.team?.validState === 1)
        .map((m) => m.teamId);

      if (validTeamIds.length === 0) {
        return null;
      }

      // 3. 通过团队ID查询团队报名记录
      const teamReg = await this.prisma.contestRegistration.findFirst({
        where: {
          contestId,
          teamId: { in: validTeamIds },
          registrationType: 'team',
          registrationState: 'passed',
        },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
              contestType: true,
            },
          },
          team: {
            include: {
              members: {
                where: {
                  role: { in: ['leader', 'member'] }, // 只查询队长和队员，不包含指导老师
                },
                include: {
                  user: {
                    select: {
                      id: true,
                      username: true,
                      nickname: true,
                    },
                  },
                },
              },
            },
          },
          works: {
            where: { validState: 1, isLatest: true },
            orderBy: { submitTime: 'desc' },
          },
        },
      });

      return teamReg;
    } catch (error) {
      console.error('getMyRegistration error:', error);
      throw error;
    }
  }
}

