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

/**
 * FASE 5 — Huddle Notes Service
 *
 * Genera notas inteligentes para huddles: transcripción simulada + resumen
 * + action items + key takeaways. En producción esto conectaría con un
 * servicio de speech-to-text y un LLM para generar el resumen.
 */
@Injectable()
export class HuddleNotesService {
  private readonly logger = new Logger(HuddleNotesService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * Genera notas de un huddle a partir de la transcripción (o la simula
   * si no se proporciona texto). Crea un HuddleNote en la BD.
   */
  async generateNotes(
    huddleId: string,
    wsId: string,
    userId: string,
    opts: { transcript?: string; generateTranscript?: boolean } = {},
  ): Promise<{
    id: string;
    huddle_id: string;
    summary: string;
    action_items: any[];
    key_takeaways: string[];
    transcript: string | null;
  }> {
    const huddle = await this.prisma.huddle.findFirst({
      where: { id: huddleId, workspaceId: wsId },
      include: {
        startedByUser: { select: { id: true, displayName: true } },
        participants: {
          include: { user: { select: { id: true, displayName: true } } },
        },
      },
    });
    if (!huddle) throw new NotFoundException('Huddle not found');

    // 1. Obtener la transcripción
    let transcript = opts.transcript ?? null;

    if (!transcript && opts.generateTranscript) {
      // Simular transcripción basada en participantes y duración
      transcript = this.simulateTranscript(huddle);
    }

    if (!transcript) {
      throw new BadRequestException(
        'Se requiere una transcripción o activar generateTranscript=true',
      );
    }

    // 2. Generar resumen (stub local)
    const summary = this.generateSummary(huddle, transcript);
    const actionItems = this.extractActionItems(transcript, huddle);
    const keyTakeaways = this.extractKeyTakeaways(transcript, huddle);

    // 3. Guardar la nota
    const note = await this.prisma.huddleNote.create({
      data: {
        huddleId,
        transcript,
        summary,
        actionItems,
        keyTakeaways,
      },
    });

    this.logger.log(`Notes generated for huddle ${huddleId}`);

    return {
      id: note.id,
      huddle_id: huddleId,
      summary: note.summary ?? summary,
      action_items: note.actionItems as any[],
      key_takeaways: note.keyTakeaways as string[],
      transcript: note.transcript,
    };
  }

  /**
   * Devuelve las notas de un huddle.
   */
  async listNotes(huddleId: string, wsId: string) {
    const huddle = await this.prisma.huddle.findFirst({
      where: { id: huddleId, workspaceId: wsId },
      select: { id: true },
    });
    if (!huddle) throw new NotFoundException('Huddle not found');

    const notes = await this.prisma.huddleNote.findMany({
      where: { huddleId },
      orderBy: { generatedAt: 'desc' },
    });

    return notes.map((n) => ({
      id: n.id,
      huddle_id: n.huddleId,
      summary: n.summary,
      action_items: n.actionItems,
      key_takeaways: n.keyTakeaways,
      transcript: n.transcript,
      generated_at: n.generatedAt,
    }));
  }

  /**
   * Devuelve una nota específica.
   */
  async getNote(huddleId: string, noteId: string, wsId: string) {
    const huddle = await this.prisma.huddle.findFirst({
      where: { id: huddleId, workspaceId: wsId },
      select: { id: true },
    });
    if (!huddle) throw new NotFoundException('Huddle not found');

    const note = await this.prisma.huddleNote.findUnique({
      where: { id: noteId },
    });
    if (!note || note.huddleId !== huddleId) {
      throw new NotFoundException('Note not found');
    }

    return {
      id: note.id,
      huddle_id: note.huddleId,
      summary: note.summary,
      action_items: note.actionItems,
      key_takeaways: note.keyTakeaways,
      transcript: note.transcript,
      generated_at: note.generatedAt,
    };
  }

  // ------------------------------------------------------------------

  private simulateTranscript(huddle: any): string {
    const participants = huddle.participants
      .filter((p: any) => !p.leftAt)
      .map((p: any) => p.user?.displayName || 'Participante');

    const lines: string[] = [];
    const topics = ['proyecto', 'seguimiento', 'decisiones', 'próximos pasos', 'bloqueos'];

    // Generar entre 10 y 20 líneas simuladas
    const numLines = Math.min(Math.max(participants.length * 3, 8), 20);
    for (let i = 0; i < numLines; i++) {
      const speaker = participants[i % participants.length] || 'Participante';
      const topic = topics[i % topics.length];
      const phrases = [
        `vamos a hablar sobre ${topic}`,
        `lo importante de ${topic} es que avancemos`,
        `necesitamos tomar una decisión sobre ${topic}`,
        `asignemos a alguien para revisar ${topic}`,
        `revisemos el estado de ${topic}`,
        `hay un bloqueo en ${topic} que resolver`,
      ];
      lines.push(`[${speaker}]: ${phrases[i % phrases.length]}`);
    }

    return lines.join('\n');
  }

  private generateSummary(huddle: any, transcript: string): string {
    const participants = huddle.participants
      .filter((p: any) => !p.leftAt)
      .map((p: any) => p.user?.displayName || 'Participante');

    const lineCount = transcript.split('\n').filter(Boolean).length;
    const startedBy = huddle.startedByUser?.displayName || 'Usuario';

    return (
      `Huddle iniciado por ${startedBy} con ${participants.length} participantes. ` +
      `Se discutieron ${lineCount} puntos. ` +
      `Participantes: ${participants.join(', ')}.`
    );
  }

  private extractActionItems(transcript: string, huddle: any): any[] {
    const lines = transcript.split('\n').filter(Boolean);
    const actions: any[] = [];

    const participants = huddle.participants
      .filter((p: any) => !p.leftAt)
      .map((p: any) => ({ id: p.userId, name: p.user?.displayName || 'Participante' }));

    const actionPatterns = [
      /(?:necesitamos|debemos|hay que|vamos a|asignemos|revisemos|avancemos)/i,
    ];

    lines.forEach((line, idx) => {
      const match = line.match(/\[([^\]]+)\]:\s*(.*)/);
      const speaker = match ? match[1] : 'Participante';
      const text = match ? match[2] : line;

      if (actionPatterns.some((p: RegExp) => p.test(text))) {
        const assignee = participants.find((p: any) => p.name === speaker) || participants[idx % participants.length];
        actions.push({
          id: `action_${actions.length + 1}`,
          description: text,
          assigned_to: assignee?.name ?? speaker,
          assigned_to_id: assignee?.id ?? null,
          priority: 'medium',
          due_date: null,
        });
      }
    });

    return actions;
  }

  private extractKeyTakeaways(transcript: string, huddle: any): string[] {
    const lines = transcript.split('\n').filter(Boolean);
    const takeaways: string[] = [];

    const takeawayPatterns = [
      /(?:lo importante|decisión|concluimos|acordamos|resumen)/i,
    ];

    lines.forEach((line) => {
      const match = line.match(/\[([^\]]+)\]:\s*(.*)/);
      const text = match ? match[2] : line;

      if (takeawayPatterns.some((p: RegExp) => p.test(text))) {
        takeaways.push(text);
      }
    });

    // Si no se encontraron, extraer las primeras 3 líneas como takeaways
    if (takeaways.length === 0) {
      return lines.slice(0, 3).map((l) => {
        const m = l.match(/\[([^\]]+)\]:\s*(.*)/);
        return m ? m[2] : l;
      });
    }

    return takeaways.slice(0, 5);
  }
}