import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { PrismaService } from '@chatapp/database';

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

  async list(wsId: string) {
    const groups = await this.prisma.userGroup.findMany({
      where: { workspaceId: wsId },
      include: {
        members: {
          include: {
            user: { select: { id: true, displayName: true, avatarUrl: true } },
          },
        },
      },
      orderBy: { createdAt: 'desc' },
    });

    return {
      groups: groups.map(g => ({
        id: g.id,
        name: g.name,
        handle: g.handle,
        description: g.description,
        is_auto: g.isAuto,
        created_by: g.createdBy,
        created_at: g.createdAt,
        members: g.members.map(m => ({
          user_id: m.userId,
          display_name: m.user.displayName,
          avatar_url: m.user.avatarUrl,
          added_at: m.addedAt,
        })),
      })),
    };
  }

  async create(wsId: string, userId: string, dto: { name: string; handle: string; description?: string }) {
    const existing = await this.prisma.userGroup.findFirst({
      where: { workspaceId: wsId, handle: dto.handle },
    });
    if (existing) throw new BadRequestException('Handle already exists in this workspace');

    const group = await this.prisma.userGroup.create({
      data: {
        workspaceId: wsId,
        name: dto.name,
        handle: dto.handle,
        description: dto.description || null,
        createdBy: userId,
      },
    });
    return {
      id: group.id,
      name: group.name,
      handle: group.handle,
      description: group.description,
    };
  }

  async update(id: string, wsId: string, dto: { name?: string; handle?: string; description?: string }) {
    const group = await this.prisma.userGroup.findFirst({ where: { id, workspaceId: wsId } });
    if (!group) throw new NotFoundException('User group not found');

    const data: any = {};
    if (dto.name !== undefined) data.name = dto.name;
    if (dto.handle !== undefined) {
      const conflict = await this.prisma.userGroup.findFirst({
        where: { workspaceId: wsId, handle: dto.handle, NOT: { id } },
      });
      if (conflict) throw new BadRequestException('Handle already exists in this workspace');
      data.handle = dto.handle;
    }
    if (dto.description !== undefined) data.description = dto.description;

    const updated = await this.prisma.userGroup.update({ where: { id }, data });
    return {
      id: updated.id,
      name: updated.name,
      handle: updated.handle,
      description: updated.description,
    };
  }

  async delete(id: string, wsId: string) {
    const group = await this.prisma.userGroup.findFirst({ where: { id, workspaceId: wsId } });
    if (!group) throw new NotFoundException('User group not found');

    await this.prisma.userGroup.delete({ where: { id } });
    return { deleted: true };
  }

  async addMember(groupId: string, userId: string, addedBy: string) {
    const group = await this.prisma.userGroup.findUnique({ where: { id: groupId } });
    if (!group) throw new NotFoundException('User group not found');

    await this.prisma.userGroupMember.create({
      data: {
        userGroupId: groupId,
        userId,
        addedBy,
      },
    }).catch(() => {
      // Member already exists (composite PK conflict)
    });

    return { added: true, user_id: userId };
  }

  async removeMember(groupId: string, userId: string) {
    const group = await this.prisma.userGroup.findUnique({ where: { id: groupId } });
    if (!group) throw new NotFoundException('User group not found');

    await this.prisma.userGroupMember.delete({
      where: { userGroupId_userId: { userGroupId: groupId, userId } },
    });

    return { removed: true, user_id: userId };
  }
}