import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateGroupDto } from './dto/create-group.dto';
import { UpdateGroupDto } from './dto/update-group.dto';
import { AddMembersDto } from './dto/add-members.dto';

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

  // Gruppen-Verwaltung
  async createGroup(createdById: number, dto: CreateGroupDto) {
    const group = await this.prisma.chatGroup.create({
      data: {
        name: dto.name,
        description: dto.description,
        createdById,
        members: {
          create: [
            // Ersteller ist automatisch Mitglied
            { userId: createdById },
            // Weitere Mitglieder hinzufügen
            ...(dto.memberIds || []).map((userId) => ({ userId })),
          ],
        },
      },
      include: {
        members: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                email: true,
                role: true,
              },
            },
          },
        },
      },
    });

    return group;
  }

  async getAllGroups() {
    return this.prisma.chatGroup.findMany({
      include: {
        members: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                email: true,
                role: true,
              },
            },
          },
        },
        _count: {
          select: {
            messages: true,
            members: true,
          },
        },
      },
      orderBy: {
        updatedAt: 'desc',
      },
    });
  }

  async getGroupById(groupId: number) {
    const group = await this.prisma.chatGroup.findUnique({
      where: { id: groupId },
      include: {
        members: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                email: true,
                role: true,
              },
            },
          },
        },
        _count: {
          select: {
            messages: true,
          },
        },
      },
    });

    if (!group) {
      throw new NotFoundException('Gruppe nicht gefunden');
    }

    return group;
  }

  async getUserGroups(userId: number) {
    const memberships = await this.prisma.chatGroupMember.findMany({
      where: { userId },
      include: {
        group: {
          include: {
            members: {
              include: {
                user: {
                  select: {
                    id: true,
                    username: true,
                    email: true,
                    role: true,
                  },
                },
              },
            },
            _count: {
              select: {
                messages: true,
                members: true,
              },
            },
          },
        },
      },
      orderBy: {
        group: {
          updatedAt: 'desc',
        },
      },
    });

    return memberships.map((m) => m.group);
  }

  async updateGroup(groupId: number, userId: number, userRole: string, dto: UpdateGroupDto) {
    const group = await this.getGroupById(groupId);

    // Nur Lehrer oder der Ersteller kann die Gruppe bearbeiten
    if (userRole !== 'Lehrer' && group.createdById !== userId) {
      throw new ForbiddenException('Keine Berechtigung zum Bearbeiten dieser Gruppe');
    }

    return this.prisma.chatGroup.update({
      where: { id: groupId },
      data: {
        name: dto.name,
        description: dto.description,
      },
      include: {
        members: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                email: true,
                role: true,
              },
            },
          },
        },
      },
    });
  }

  async deleteGroup(groupId: number, userId: number, userRole: string) {
    const group = await this.getGroupById(groupId);

    // Nur Lehrer können Gruppen löschen
    if (userRole !== 'Lehrer') {
      throw new ForbiddenException('Nur Lehrer können Gruppen löschen');
    }

    await this.prisma.chatGroup.delete({
      where: { id: groupId },
    });

    return { message: 'Gruppe erfolgreich gelöscht' };
  }

  async addMembers(groupId: number, userId: number, userRole: string, dto: AddMembersDto) {
    const group = await this.getGroupById(groupId);

    // Nur Lehrer können Mitglieder hinzufügen
    if (userRole !== 'Lehrer') {
      throw new ForbiddenException('Nur Lehrer können Mitglieder hinzufügen');
    }

    // Mitglieder hinzufügen (ignoriert bereits existierende)
    const newMembers = await Promise.all(
      dto.userIds.map((userId) =>
        this.prisma.chatGroupMember.upsert({
          where: {
            userId_groupId: {
              userId,
              groupId,
            },
          },
          create: {
            userId,
            groupId,
          },
          update: {},
          include: {
            user: {
              select: {
                id: true,
                username: true,
                email: true,
                role: true,
              },
            },
          },
        }),
      ),
    );

    return newMembers;
  }

  async removeMember(groupId: number, memberUserId: number, requestUserId: number, userRole: string) {
    const group = await this.getGroupById(groupId);

    // Nur Lehrer können Mitglieder entfernen
    if (userRole !== 'Lehrer') {
      throw new ForbiddenException('Nur Lehrer können Mitglieder entfernen');
    }

    // Ersteller kann nicht entfernt werden
    if (memberUserId === group.createdById) {
      throw new ForbiddenException('Der Ersteller der Gruppe kann nicht entfernt werden');
    }

    await this.prisma.chatGroupMember.delete({
      where: {
        userId_groupId: {
          userId: memberUserId,
          groupId,
        },
      },
    });

    return { message: 'Mitglied erfolgreich entfernt' };
  }

  // Nachrichten-Verwaltung
  async getGroupMessages(groupId: number, userId: number, limit = 100, offset = 0) {
    // Prüfen ob User Mitglied der Gruppe ist
    const membership = await this.prisma.chatGroupMember.findUnique({
      where: {
        userId_groupId: {
          userId,
          groupId,
        },
      },
    });

    if (!membership) {
      throw new ForbiddenException('Sie sind kein Mitglied dieser Gruppe');
    }

    const messages = await this.prisma.chatMessage.findMany({
      where: { groupId },
      include: {
        user: {
          select: {
            id: true,
            username: true,
            email: true,
            role: true,
          },
        },
      },
      orderBy: {
        createdAt: 'desc',
      },
      take: limit,
      skip: offset,
    });

    return messages.reverse(); // Älteste zuerst
  }

  async createMessage(groupId: number, userId: number, content: string) {
    // Prüfen ob User Mitglied der Gruppe ist
    const membership = await this.prisma.chatGroupMember.findUnique({
      where: {
        userId_groupId: {
          userId,
          groupId,
        },
      },
    });

    if (!membership) {
      throw new ForbiddenException('Sie sind kein Mitglied dieser Gruppe');
    }

    const message = await this.prisma.chatMessage.create({
      data: {
        content,
        userId,
        groupId,
      },
      include: {
        user: {
          select: {
            id: true,
            username: true,
            email: true,
            role: true,
          },
        },
      },
    });

    // Update group's updatedAt
    await this.prisma.chatGroup.update({
      where: { id: groupId },
      data: { updatedAt: new Date() },
    });

    return message;
  }
}
