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

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

  async start(channelId: string, wsId: string, userId: string, dto: any) {
    // Check if there's already an active huddle in the channel
    const existing = await this.prisma.huddle.findFirst({
      where: { channelId, status: 'active' },
    });
    if (existing) {
      // Join the existing one instead
      return this.join(existing.id, userId, dto);
    }

    const huddle = await this.prisma.huddle.create({
      data: {
        workspaceId: wsId,
        channelId,
        startedBy: userId,
        status: 'active',
        isVideo: dto?.is_video ?? false,
        roomId: dto?.room_id,
      },
      include: {
        startedByUser: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    // Add the starter as a participant
    await this.prisma.huddleParticipant.create({
      data: {
        huddleId: huddle.id,
        userId,
        hadVideo: dto?.is_video ?? false,
        hadAudio: true,
      },
    });

    await this.prisma.huddle.update({
      where: { id: huddle.id },
      data: {
        participantCount: 1,
        maxParticipants: 1,
      },
    });

    return {
      id: huddle.id,
      channel_id: huddle.channelId,
      started_by: huddle.startedByUser,
      status: huddle.status,
      is_video: huddle.isVideo,
      room_id: huddle.roomId,
      started_at: huddle.startedAt,
      participant_count: 1,
    };
  }

  async join(huddleId: string, userId: string, dto?: any) {
    const huddle = await this.prisma.huddle.findUnique({ where: { id: huddleId } });
    if (!huddle) throw new NotFoundException('Huddle not found');
    if (huddle.status !== 'active') throw new BadRequestException('Huddle is not active');

    // Upsert participant — handle rejoin
    const existing = await this.prisma.huddleParticipant.findUnique({
      where: {
        huddleId_userId: { huddleId, userId },
      },
    });

    if (existing && !existing.leftAt) {
      // Already in the huddle
      return { joined: true, huddle_id: huddleId, participant_id: existing.id };
    }

    const participant = await this.prisma.huddleParticipant.upsert({
      where: {
        huddleId_userId: { huddleId, userId },
      },
      create: {
        huddleId,
        userId,
        hadVideo: dto?.is_video ?? false,
        hadAudio: dto?.has_audio ?? true,
      },
      update: {
        leftAt: null,
        hadVideo: dto?.is_video ?? false,
        hadAudio: dto?.has_audio ?? true,
      },
    });

    // Update participant count
    const activeCount = await this.prisma.huddleParticipant.count({
      where: { huddleId, leftAt: null },
    });

    await this.prisma.huddle.update({
      where: { id: huddleId },
      data: {
        participantCount: activeCount,
        maxParticipants: { set: Math.max(activeCount, huddle.maxParticipants) },
      },
    });

    return { joined: true, huddle_id: huddleId, participant_id: participant.id };
  }

  async leave(huddleId: string, userId: string) {
    const huddle = await this.prisma.huddle.findUnique({ where: { id: huddleId } });
    if (!huddle) throw new NotFoundException('Huddle not found');

    await this.prisma.huddleParticipant.updateMany({
      where: { huddleId, userId, leftAt: null },
      data: { leftAt: new Date() },
    });

    const activeCount = await this.prisma.huddleParticipant.count({
      where: { huddleId, leftAt: null },
    });

    await this.prisma.huddle.update({
      where: { id: huddleId },
      data: { participantCount: activeCount },
    });

    // Auto-end huddle if no participants left
    if (activeCount === 0 && huddle.status === 'active') {
      await this.prisma.huddle.update({
        where: { id: huddleId },
        data: { status: 'ended', endedAt: new Date() },
      });
    }

    return { left: true };
  }

  async addNote(huddleId: string, dto: any) {
    const huddle = await this.prisma.huddle.findUnique({ where: { id: huddleId } });
    if (!huddle) throw new NotFoundException('Huddle not found');

    const note = await this.prisma.huddleNote.create({
      data: {
        huddleId,
        transcript: dto.transcript,
        summary: dto.summary,
        actionItems: dto.action_items,
        keyTakeaways: dto.key_takeaways || [],
      },
    });

    return note;
  }

  async getStatus(huddleId: string) {
    const huddle = await this.prisma.huddle.findUnique({
      where: { id: huddleId },
      include: {
        startedByUser: { select: { id: true, displayName: true, avatarUrl: true } },
        participants: {
          where: { leftAt: null },
          include: {
            user: { select: { id: true, displayName: true, avatarUrl: true } },
          },
        },
        notes: { orderBy: { generatedAt: 'desc' } },
      },
    });

    if (!huddle) throw new NotFoundException('Huddle not found');

    return {
      id: huddle.id,
      channel_id: huddle.channelId,
      started_by: huddle.startedByUser,
      status: huddle.status,
      is_video: huddle.isVideo,
      room_id: huddle.roomId,
      started_at: huddle.startedAt,
      ended_at: huddle.endedAt,
      participant_count: huddle.participantCount,
      max_participants: huddle.maxParticipants,
      participants: huddle.participants.map(p => ({
        id: p.id,
        user: p.user,
        had_video: p.hadVideo,
        had_audio: p.hadAudio,
        was_screensharing: p.wasScreensharing,
        joined_at: p.joinedAt,
      })),
      notes: huddle.notes.map(n => ({
        id: n.id,
        summary: n.summary,
        key_takeaways: n.keyTakeaways,
        action_items: n.actionItems,
        generated_at: n.generatedAt,
      })),
    };
  }

  async end(huddleId: string, userId: string) {
    const huddle = await this.prisma.huddle.findUnique({ where: { id: huddleId } });
    if (!huddle) throw new NotFoundException('Huddle not found');
    if (huddle.status !== 'active') throw new BadRequestException('Huddle is not active');

    // Mark all active participants as left
    await this.prisma.huddleParticipant.updateMany({
      where: { huddleId, leftAt: null },
      data: { leftAt: new Date() },
    });

    await this.prisma.huddle.update({
      where: { id: huddleId },
      data: {
        status: 'ended',
        endedAt: new Date(),
        participantCount: 0,
      },
    });

    return { ended: true };
  }

  /**
   * Activa/desactiva screen sharing para un participante del huddle.
   */
  async toggleScreenShare(huddleId: string, userId: string, dto: { sharing: boolean }) {
    const participant = await this.prisma.huddleParticipant.findUnique({
      where: { huddleId_userId: { huddleId, userId } },
    });
    if (!participant) throw new NotFoundException('Participant not found in this huddle');

    const updated = await this.prisma.huddleParticipant.update({
      where: { huddleId_userId: { huddleId, userId } },
      data: { wasScreensharing: dto.sharing },
      include: {
        user: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    return {
      user: updated.user,
      is_screensharing: updated.wasScreensharing,
    };
  }

  /**
   * Envía un mensaje de chat dentro del huddle (se guarda como mensaje del canal
   * con systemType='huddle_message' para no requerir nueva tabla).
   */
  async sendChatMessage(huddleId: string, userId: string, wsId: string, dto: { text: string }) {
    const huddle = await this.prisma.huddle.findUnique({
      where: { id: huddleId },
      select: { id: true, channelId: true, status: true },
    });
    if (!huddle) throw new NotFoundException('Huddle not found');
    if (huddle.status !== 'active') throw new BadRequestException('Huddle is not active');

    const participant = await this.prisma.huddleParticipant.findUnique({
      where: { huddleId_userId: { huddleId, userId } },
    });
    if (!participant || participant.leftAt) {
      throw new BadRequestException('You are not a participant in this huddle');
    }

    const message = await this.prisma.message.create({
      data: {
        workspaceId: wsId,
        channelId: huddle.channelId,
        userId,
        text: dto.text,
        isSystem: true,
        systemType: 'huddle_message',
      },
      include: {
        user: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    return {
      id: message.id,
      text: message.text,
      user: message.user,
      system_type: message.systemType,
      created_at: message.createdAt,
    };
  }

  /**
   * Lista los participantes activos con su estado de screen sharing.
   */
  async getActiveParticipants(huddleId: string) {
    const huddle = await this.prisma.huddle.findUnique({ where: { id: huddleId } });
    if (!huddle) throw new NotFoundException('Huddle not found');

    const participants = await this.prisma.huddleParticipant.findMany({
      where: { huddleId, leftAt: null },
      include: {
        user: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    return {
      participants: participants.map(p => ({
        id: p.id,
        user: p.user,
        had_video: p.hadVideo,
        had_audio: p.hadAudio,
        is_screensharing: p.wasScreensharing,
        joined_at: p.joinedAt,
      })),
    };
  }
}