import {
  BadRequestException,
  ConflictException,
  Injectable,
  NotFoundException,
} from "@nestjs/common";
import { TeamMemberRole } from "@prisma/client";
import { PrismaService } from "../prisma/prisma.service";
import { CreateTeamDto } from "./dto/create-team.dto";
import { ManageTeamMemberDto } from "./dto/manage-team-member.dto";

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

  async create(workspaceId: string, createTeamDto: CreateTeamDto) {
    return this.prisma.team.create({
      data: {
        workspaceId,
        name: createTeamDto.name,
        description: createTeamDto.description ?? null,
      },
    });
  }

  async findAll(workspaceId: string) {
    return this.prisma.team.findMany({
      where: { workspaceId },
      include: {
        _count: {
          select: { members: true },
        },
      },
      orderBy: { createdAt: "asc" },
    });
  }

  async addMember(workspaceId: string, teamId: string, dto: ManageTeamMemberDto) {
    await this.ensureTeamInWorkspace(workspaceId, teamId);

    const workspaceMember = await this.prisma.workspaceMember.findUnique({
      where: {
        workspaceId_userId: {
          workspaceId,
          userId: dto.userId,
        },
      },
      select: { userId: true },
    });

    if (!workspaceMember) {
      throw new BadRequestException(
        `User ${dto.userId} must be a workspace member before being added to a team`
      );
    }

    const existingTeamMember = await this.prisma.teamMember.findUnique({
      where: {
        teamId_userId: {
          teamId,
          userId: dto.userId,
        },
      },
      select: { userId: true },
    });

    if (existingTeamMember) {
      throw new ConflictException(`User ${dto.userId} is already a member of team ${teamId}`);
    }

    return this.prisma.teamMember.create({
      data: {
        teamId,
        userId: dto.userId,
        role: dto.role ?? TeamMemberRole.MEMBER,
      },
      include: {
        user: {
          select: {
            id: true,
            name: true,
            email: true,
          },
        },
      },
    });
  }

  async removeMember(workspaceId: string, teamId: string, userId: string): Promise<void> {
    await this.ensureTeamInWorkspace(workspaceId, teamId);

    const result = await this.prisma.teamMember.deleteMany({
      where: {
        teamId,
        userId,
      },
    });

    if (result.count === 0) {
      throw new NotFoundException(`User ${userId} is not a member of team ${teamId}`);
    }
  }

  async remove(workspaceId: string, teamId: string): Promise<void> {
    const result = await this.prisma.team.deleteMany({
      where: {
        id: teamId,
        workspaceId,
      },
    });

    if (result.count === 0) {
      throw new NotFoundException(`Team with ID ${teamId} not found`);
    }
  }

  private async ensureTeamInWorkspace(workspaceId: string, teamId: string): Promise<void> {
    const team = await this.prisma.team.findFirst({
      where: {
        id: teamId,
        workspaceId,
      },
      select: { id: true },
    });

    if (!team) {
      throw new NotFoundException(`Team with ID ${teamId} not found`);
    }
  }
}
