import {
  Injectable,
  NotFoundException,
  ConflictException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateTeamDto } from './dto/create-team.dto';
import { UpdateTeamDto } from './dto/update-team.dto';
import { InviteMemberDto } from './dto/invite-member.dto';

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

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

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

    // 检查活动类型
    if (contest.contestType !== 'team') {
      throw new BadRequestException('该活动不是团队参与');
    }

    // 检查团队名称是否已存在（同一活动、同一租户内）
    const existing = await this.prisma.contestTeam.findFirst({
      where: {
        tenantId,
        contestId: createTeamDto.contestId,
        teamName: createTeamDto.teamName,
        validState: 1,
      },
    });

    if (existing) {
      throw new ConflictException('团队名称已存在');
    }

    // 验证队长用户是否存在
    const leader = await this.prisma.user.findUnique({
      where: { id: createTeamDto.leaderId },
    });

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

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

    // 使用事务创建团队和报名记录
    return this.prisma.$transaction(async (tx) => {
      // 创建团队
      const data: any = {
        tenantId,
        contestId: createTeamDto.contestId,
        teamName: createTeamDto.teamName,
        leaderUserId: createTeamDto.leaderId,
        maxMembers: createTeamDto.maxMembers,
      };

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

      const team = await tx.contestTeam.create({
        data,
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
            },
          },
          leader: {
            select: {
              id: true,
              username: true,
              nickname: true,
            },
          },
        },
      });

      // 自动添加队长为成员
      await tx.contestTeamMember.create({
        data: {
          tenantId,
          teamId: team.id,
          userId: createTeamDto.leaderId,
          role: 'leader',
          creator: creatorId,
        },
      });

      // 添加其他队员（排除队长）
      if (createTeamDto.memberIds && createTeamDto.memberIds.length > 0) {
        const memberIdsToAdd = createTeamDto.memberIds.filter(
          (id) => id !== createTeamDto.leaderId,
        );
        for (const memberId of memberIdsToAdd) {
          await tx.contestTeamMember.create({
            data: {
              tenantId,
              teamId: team.id,
              userId: memberId,
              role: 'member',
              creator: creatorId,
            },
          });
        }
      }

      // 添加指导老师
      if (createTeamDto.teacherIds && createTeamDto.teacherIds.length > 0) {
        for (const teacherId of createTeamDto.teacherIds) {
          await tx.contestTeamMember.create({
            data: {
              tenantId,
              teamId: team.id,
              userId: teacherId,
              role: 'mentor',
              creator: creatorId,
            },
          });
        }
      }

      // 自动创建团队报名记录
      const accountNo = leader.username;
      const accountName = leader.nickname;

      await tx.contestRegistration.create({
        data: {
          contestId: createTeamDto.contestId,
          tenantId,
          registrationType: 'team',
          teamId: team.id,
          teamName: createTeamDto.teamName,
          userId: createTeamDto.leaderId,
          accountNo,
          accountName,
          registrationState: 'pending',
          registrationTime: new Date(),
          registrant: creatorId || createTeamDto.leaderId,
          creator: creatorId,
        },
      });

      // 返回完整的团队信息
      return tx.contestTeam.findUnique({
        where: { id: team.id },
        include: {
          contest: {
            select: {
              id: true,
              contestName: true,
            },
          },
          leader: {
            select: {
              id: true,
              username: true,
              nickname: true,
            },
          },
          members: {
            include: {
              user: {
                select: {
                  id: true,
                  username: true,
                  nickname: true,
                },
              },
            },
          },
          _count: {
            select: {
              members: true,
            },
          },
        },
      });
    });
  }

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

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

    const teams = await this.prisma.contestTeam.findMany({
      where,
      orderBy: {
        createTime: 'desc',
      },
      include: {
        leader: {
          select: {
            id: true,
            username: true,
            nickname: true,
          },
        },
        members: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
          },
        },
        registrations: {
          select: {
            id: true,
            registrationState: true,
          },
          take: 1,
        },
        _count: {
          select: {
            members: true,
            registrations: true,
          },
        },
      },
    });

    // 将报名状态扁平化到团队对象上
    return teams.map((team) => ({
      ...team,
      registrationState: team.registrations?.[0]?.registrationState || 'pending',
      registrationId: team.registrations?.[0]?.id,
    }));
  }

  async findOne(id: number, tenantId?: number, strictTenantCheck = false) {
    const where: any = {
      id,
      validState: 1,
    };

    // 只有明确要求严格租户检查时才限制 tenantId
    // 通过 ID 查询单个团队时，ID 已经是唯一的，不需要再限制 tenantId
    if (tenantId && strictTenantCheck) {
      where.tenantId = tenantId;
    }

    const team = await this.prisma.contestTeam.findFirst({
      where,
      include: {
        contest: {
          select: {
            id: true,
            contestName: true,
            contestType: true,
          },
        },
        leader: {
          select: {
            id: true,
            username: true,
            nickname: true,
          },
        },
        members: {
          where: {
            role: { in: ['leader', 'member'] }, // 只查询队长和队员，不包含指导老师
          },
          include: {
            user: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
          },
        },
        registrations: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
          },
        },
      },
    });

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

    return team;
  }

  async update(
    id: number,
    updateTeamDto: UpdateTeamDto,
    tenantId: number,
    modifierId?: number,
  ) {
    const team = await this.findOne(id, tenantId);

    // 检查团队名称是否重复
    if (updateTeamDto.teamName && updateTeamDto.teamName !== team.teamName) {
      const existing = await this.prisma.contestTeam.findFirst({
        where: {
          tenantId,
          contestId: team.contestId,
          teamName: updateTeamDto.teamName,
          validState: 1,
          id: { not: id },
        },
      });

      if (existing) {
        throw new ConflictException('团队名称已存在');
      }
    }

    const data: any = {};

    if (updateTeamDto.teamName !== undefined) {
      data.teamName = updateTeamDto.teamName;
    }
    if (updateTeamDto.maxMembers !== undefined) {
      data.maxMembers = updateTeamDto.maxMembers;
    }

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

    return this.prisma.contestTeam.update({
      where: { id },
      data,
      include: {
        contest: {
          select: {
            id: true,
            contestName: true,
          },
        },
        leader: {
          select: {
            id: true,
            username: true,
            nickname: true,
          },
        },
        members: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
          },
        },
      },
    });
  }

  async inviteMember(
    teamId: number,
    inviteMemberDto: InviteMemberDto,
    tenantId: number,
    creatorId?: number,
  ) {
    const team = await this.findOne(teamId, tenantId);

    // 检查成员数量限制
    const memberCount = await this.prisma.contestTeamMember.count({
      where: { teamId },
    });

    if (team.maxMembers && memberCount >= team.maxMembers) {
      throw new BadRequestException('团队人数已达上限');
    }

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

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

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

    // 检查是否已是成员
    const existing = await this.prisma.contestTeamMember.findFirst({
      where: {
        tenantId,
        teamId,
        userId: inviteMemberDto.userId,
      },
    });

    if (existing) {
      throw new ConflictException('用户已是团队成员');
    }

    // 检查用户是否已加入其他团队（同一活动）
    const otherTeam = await this.prisma.contestTeamMember.findFirst({
      where: {
        tenantId,
        userId: inviteMemberDto.userId,
        team: {
          contestId: team.contestId,
          validState: 1,
        },
      },
    });

    if (otherTeam) {
      throw new ConflictException('用户已加入其他团队');
    }

    return this.prisma.contestTeamMember.create({
      data: {
        tenantId,
        teamId,
        userId: inviteMemberDto.userId,
        role: inviteMemberDto.role || 'member',
        creator: creatorId,
      },
      include: {
        user: {
          select: {
            id: true,
            username: true,
            nickname: true,
          },
        },
        team: {
          select: {
            id: true,
            teamName: true,
          },
        },
      },
    });
  }

  async removeMember(teamId: number, userId: number, tenantId: number) {
    const team = await this.findOne(teamId, tenantId);

    // 不能移除队长
    if (team.leaderUserId === userId) {
      throw new BadRequestException('不能移除队长');
    }

    const member = await this.prisma.contestTeamMember.findFirst({
      where: {
        tenantId,
        teamId,
        userId,
      },
    });

    if (!member) {
      throw new NotFoundException('成员不存在');
    }

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

  async remove(teamId: number, tenantId: number) {
    const team = await this.findOne(teamId, tenantId);

    // 检查是否有报名记录
    const registrationCount = await this.prisma.contestRegistration.count({
      where: { teamId },
    });

    if (registrationCount > 0) {
      throw new BadRequestException('团队已有报名记录，无法删除');
    }

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

