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

/**
 * FASE 5 — AI Workflow Generation Service
 *
 * Permite generar workflows de automatización a partir de una descripción
 * en lenguaje natural. Analiza el texto, detecta triggers y acciones
 * sugeridas, y crea un draft de Workflow en la BD.
 */
@Injectable()
export class WorkflowGenerationService {
  constructor(private readonly prisma: PrismaService) {}

  /**
   * Genera un workflow a partir de una descripción en lenguaje natural.
   * Devuelve una propuesta (sin guardar) que el usuario puede revisar.
   */
  async generateDraft(
    wsId: string,
    userId: string,
    description: string,
  ): Promise<{
    name: string;
    description: string;
    trigger_type: string;
    trigger_config: any;
    steps: any[];
    suggested: boolean;
  }> {
    if (!description || description.trim().length < 5) {
      throw new BadRequestException('La descripción debe tener al menos 5 caracteres');
    }

    const lower = description.toLowerCase();

    // Detectar tipo de trigger
    const triggerType = this.detectTrigger(lower);
    const triggerConfig = this.buildTriggerConfig(triggerType, lower);

    // Detectar pasos/acciones
    const steps = this.detectSteps(lower);

    const name = this.extractName(description);

    return {
      name,
      description: description.trim(),
      trigger_type: triggerType,
      trigger_config: triggerConfig,
      steps,
      suggested: true,
    };
  }

  /**
   * Genera un workflow y lo guarda directamente como draft en la BD.
   */
  async generateAndSave(
    wsId: string,
    userId: string,
    description: string,
  ): Promise<{
    id: string;
    name: string;
    status: string;
    trigger_type: string;
    steps_count: number;
  }> {
    const draft = await this.generateDraft(wsId, userId, description);

    const workflow = await this.prisma.workflow.create({
      data: {
        workspaceId: wsId,
        name: draft.name,
        description: draft.description,
        status: 'draft',
        triggerType: draft.trigger_type,
        triggerConfig: draft.trigger_config,
        steps: draft.steps,
        variables: {},
        createdBy: userId,
      },
    });

    return {
      id: workflow.id,
      name: workflow.name,
      status: workflow.status,
      trigger_type: workflow.triggerType,
      steps_count: draft.steps.length,
    };
  }

  /**
   * Mejora una descripción existente de un workflow añadiendo pasos sugeridos.
   */
  async improveWorkflow(
    wsId: string,
    workflowId: string,
    userId: string,
    feedback: string,
  ): Promise<{
    id: string;
    added_steps: any[];
    updated: boolean;
  }> {
    const workflow = await this.prisma.workflow.findFirst({
      where: { id: workflowId, workspaceId: wsId },
    });
    if (!workflow) throw new NotFoundException('Workflow not found');

    const existingSteps = (workflow.steps as any[]) ?? [];
    const newSteps = this.detectSteps(feedback.toLowerCase());
    const combined = [...existingSteps, ...newSteps];

    await this.prisma.workflow.update({
      where: { id: workflowId },
      data: { steps: combined, updatedBy: userId, updatedAt: new Date() } as any,
    });

    return { id: workflowId, added_steps: newSteps, updated: true };
  }

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

  private detectTrigger(text: string): string {
    if (text.includes('cuando lleg') || text.includes('when a message') || text.includes('nuevo mensaje') || text.includes('new message')) {
      return 'message_received';
    }
    if (text.includes('cuando se cree') || text.includes('when a channel') || text.includes('nuevo canal')) {
      return 'channel_created';
    }
    if (text.includes('cuando alguien se una') || text.includes('when a user joins') || text.includes('nuevo miembro')) {
      return 'member_joined';
    }
    if (text.includes('cuando se reaccione') || text.includes('when a reaction') || text.includes('reacción')) {
      return 'reaction_added';
    }
    if (text.includes('cada día') || text.includes('diariamente') || text.includes('daily') || text.includes('schedule')) {
      return 'scheduled';
    }
    if (text.includes('cuando se mencione') || text.includes('when mentioned') || text.includes('mención')) {
      return 'mention';
    }
    if (text.includes('cuando se suba') || text.includes('when a file') || text.includes('archivo')) {
      return 'file_uploaded';
    }
    // Default: message_received
    return 'message_received';
  }

  private buildTriggerConfig(triggerType: string, text: string): any {
    const config: any = { type: triggerType };

    // Intentar extraer nombre de canal
    const channelMatch = text.match(/canal\s+['"]?#?(\w+)/);
    if (channelMatch) config.channel = channelMatch[1];

    // Intentar extraer palabra clave
    const keywordMatch = text.match(/(?:contenga|include|contiene|con)\s+['"]?(\w+)/);
    if (keywordMatch) config.keyword = keywordMatch[1];

    // Programación horaria
    if (triggerType === 'scheduled') {
      const timeMatch = text.match(/a las\s+(\d{1,2})(?::(\d{2}))?/);
      if (timeMatch) {
        config.hour = parseInt(timeMatch[1]);
        config.minute = timeMatch[2] ? parseInt(timeMatch[2]) : 0;
      }
      const cronMatch = text.match(/cron\s+['"]?([^\s'"]+)/);
      if (cronMatch) config.cron = cronMatch[1];
    }

    return config;
  }

  private detectSteps(text: string): any[] {
    const steps: any[] = [];

    if (text.includes('enviar') || text.includes('send') || text.includes('notificar') || text.includes('mensaje')) {
      steps.push({
        id: `step_${steps.length + 1}`,
        type: 'send_message',
        config: { template: 'Mensaje generado por workflow' },
      });
    }

    if (text.includes('crear') || text.includes('create') || text.includes('abrir') || text.includes('ticket')) {
      steps.push({
        id: `step_${steps.length + 1}`,
        type: 'create_record',
        config: { entity: text.includes('ticket') ? 'ticket' : 'task' },
      });
    }

    if (text.includes('webhook') || text.includes('api') || text.includes('http') || text.includes('llamar') || text.includes('call')) {
      steps.push({
        id: `step_${steps.length + 1}`,
        type: 'http_request',
        config: { method: 'POST', url: 'https://example.com/webhook' },
      });
    }

    if (text.includes('asignar') || text.includes('assign') || text.includes('etiquetar') || text.includes('tag')) {
      steps.push({
        id: `step_${steps.length + 1}`,
        type: 'assign_tag',
        config: { tag: 'auto-tagged' },
      });
    }

    if (text.includes('resumen') || text.includes('summary') || text.includes('sumarizar')) {
      steps.push({
        id: `step_${steps.length + 1}`,
        type: 'ai_summarize',
        config: { scope: 'channel' },
      });
    }

    if (text.includes('esperar') || text.includes('wait') || text.includes('delay') || text.includes('retraso')) {
      steps.push({
        id: `step_${steps.length + 1}`,
        type: 'delay',
        config: { seconds: 60 },
      });
    }

    // Si no se detectó nada, añadir un paso por defecto
    if (steps.length === 0) {
      steps.push({
        id: 'step_1',
        type: 'send_message',
        config: { template: 'Workflow ejecutado' },
      });
    }

    return steps;
  }

  private extractName(description: string): string {
    // Intentar sacar un nombre corto de la descripción
    const words = description.trim().split(/\s+/);
    if (words.length <= 4) return description.trim();
    return words.slice(0, 5).join(' ') + '...';
  }
}