/**
 * WhatsApp Notification Service
 * ERP Transportistas
 *
 * Service for sending WhatsApp notifications using transport templates.
 * Sprint: S5 - TASK-007
 * Module: WhatsApp Integration
 */

import {
  TipoTemplateTransporte,
  TRANSPORT_TEMPLATES,
  buildMessagePayload,
  WhatsAppTemplate,
} from '../templates/transport-templates';

/**
 * Notification result
 */
export interface NotificationResult {
  success: boolean;
  messageId?: string;
  error?: string;
  timestamp: Date;
}

/**
 * Notification request
 */
export interface NotificationRequest {
  telefono: string;
  tipoTemplate: TipoTemplateTransporte;
  parametros: Record<string, string>;
  metadata?: Record<string, any>;
}

/**
 * Batch notification result
 */
export interface BatchNotificationResult {
  total: number;
  exitosos: number;
  fallidos: number;
  resultados: Array<{
    telefono: string;
    result: NotificationResult;
  }>;
}

/**
 * WhatsApp API configuration
 */
export interface WhatsAppConfig {
  apiUrl: string;
  accessToken: string;
  phoneNumberId: string;
  businessAccountId: string;
}

/**
 * WhatsApp Notification Service
 *
 * Handles sending transport-related notifications via WhatsApp Business API.
 * In production, this would integrate with Meta's Cloud API.
 */
export class WhatsAppNotificationService {
  private config: WhatsAppConfig | null = null;
  private enabled: boolean = false;

  constructor(config?: WhatsAppConfig) {
    if (config) {
      this.config = config;
      this.enabled = true;
    }
  }

  /**
   * Configure the service
   */
  configure(config: WhatsAppConfig): void {
    this.config = config;
    this.enabled = true;
  }

  /**
   * Check if service is enabled
   */
  isEnabled(): boolean {
    return this.enabled && this.config !== null;
  }

  /**
   * Send a single notification
   */
  async enviarNotificacion(request: NotificationRequest): Promise<NotificationResult> {
    const template = TRANSPORT_TEMPLATES[request.tipoTemplate];
    if (!template) {
      return {
        success: false,
        error: `Template ${request.tipoTemplate} no encontrado`,
        timestamp: new Date(),
      };
    }

    // Validate phone number
    const telefonoLimpio = this.limpiarTelefono(request.telefono);
    if (!telefonoLimpio) {
      return {
        success: false,
        error: 'Número de teléfono inválido',
        timestamp: new Date(),
      };
    }

    // If not configured, simulate success for development
    if (!this.isEnabled()) {
      return this.simularEnvio(telefonoLimpio, template, request.parametros);
    }

    // Build and send message
    try {
      const payload = buildMessagePayload(template, request.parametros);
      const result = await this.enviarMensajeAPI(telefonoLimpio, payload);
      return result;
    } catch (error) {
      return {
        success: false,
        error: (error as Error).message,
        timestamp: new Date(),
      };
    }
  }

  /**
   * Send batch notifications
   */
  async enviarLote(requests: NotificationRequest[]): Promise<BatchNotificationResult> {
    const resultados: Array<{ telefono: string; result: NotificationResult }> = [];
    let exitosos = 0;
    let fallidos = 0;

    for (const request of requests) {
      const result = await this.enviarNotificacion(request);
      resultados.push({ telefono: request.telefono, result });

      if (result.success) {
        exitosos++;
      } else {
        fallidos++;
      }

      // Rate limiting - wait between messages
      await this.delay(100);
    }

    return {
      total: requests.length,
      exitosos,
      fallidos,
      resultados,
    };
  }

  // ==========================================
  // Transport-Specific Notification Methods
  // ==========================================

  /**
   * Notify operator of trip assignment
   */
  async notificarViajeAsignado(
    telefono: string,
    datos: {
      nombreOperador: string;
      origen: string;
      destino: string;
      fecha: string;
      horaCita: string;
      folioViaje: string;
    }
  ): Promise<NotificationResult> {
    return this.enviarNotificacion({
      telefono,
      tipoTemplate: TipoTemplateTransporte.VIAJE_ASIGNADO,
      parametros: {
        nombre_operador: datos.nombreOperador,
        origen: datos.origen,
        destino: datos.destino,
        fecha: datos.fecha,
        hora_cita: datos.horaCita,
        folio_viaje: datos.folioViaje,
      },
    });
  }

  /**
   * Notify client of shipment confirmation
   */
  async notificarViajeConfirmado(
    telefono: string,
    datos: {
      nombreCliente: string;
      folio: string;
      unidad: string;
      operador: string;
      fecha: string;
      eta: string;
      codigoTracking: string;
    }
  ): Promise<NotificationResult> {
    return this.enviarNotificacion({
      telefono,
      tipoTemplate: TipoTemplateTransporte.VIAJE_CONFIRMADO,
      parametros: {
        nombre_cliente: datos.nombreCliente,
        folio: datos.folio,
        unidad: datos.unidad,
        operador: datos.operador,
        fecha: datos.fecha,
        eta: datos.eta,
        codigo_tracking: datos.codigoTracking,
      },
    });
  }

  /**
   * Notify ETA update
   */
  async notificarEtaActualizado(
    telefono: string,
    datos: {
      folio: string;
      nuevoEta: string;
      motivo: string;
    }
  ): Promise<NotificationResult> {
    return this.enviarNotificacion({
      telefono,
      tipoTemplate: TipoTemplateTransporte.ETA_ACTUALIZADO,
      parametros: {
        folio: datos.folio,
        nuevo_eta: datos.nuevoEta,
        motivo: datos.motivo,
      },
    });
  }

  /**
   * Notify trip completion
   */
  async notificarViajeCompletado(
    telefono: string,
    datos: {
      nombreCliente: string;
      folio: string;
      destino: string;
      fechaHora: string;
      receptor: string;
    }
  ): Promise<NotificationResult> {
    return this.enviarNotificacion({
      telefono,
      tipoTemplate: TipoTemplateTransporte.VIAJE_COMPLETADO,
      parametros: {
        nombre_cliente: datos.nombreCliente,
        folio: datos.folio,
        destino: datos.destino,
        fecha_hora: datos.fechaHora,
        receptor: datos.receptor,
      },
    });
  }

  /**
   * Notify delay alert
   */
  async notificarAlertaRetraso(
    telefono: string,
    datos: {
      nombre: string;
      folio: string;
      etaOriginal: string;
      nuevoEta: string;
      motivo: string;
    }
  ): Promise<NotificationResult> {
    return this.enviarNotificacion({
      telefono,
      tipoTemplate: TipoTemplateTransporte.ALERTA_RETRASO,
      parametros: {
        nombre: datos.nombre,
        folio: datos.folio,
        eta_original: datos.etaOriginal,
        nuevo_eta: datos.nuevoEta,
        motivo: datos.motivo,
      },
    });
  }

  /**
   * Notify carrier of service request
   */
  async notificarAsignacionCarrier(
    telefono: string,
    datos: {
      nombreCarrier: string;
      origen: string;
      destino: string;
      fecha: string;
      tarifa: string;
    }
  ): Promise<NotificationResult> {
    return this.enviarNotificacion({
      telefono,
      tipoTemplate: TipoTemplateTransporte.ASIGNACION_CARRIER,
      parametros: {
        nombre_carrier: datos.nombreCarrier,
        origen: datos.origen,
        destino: datos.destino,
        fecha: datos.fecha,
        tarifa: datos.tarifa,
      },
    });
  }

  /**
   * Notify maintenance reminder
   */
  async notificarRecordatorioMantenimiento(
    telefono: string,
    datos: {
      unidad: string;
      tipoMantenimiento: string;
      fechaLimite: string;
      kmActual: string;
      kmProgramado: string;
    }
  ): Promise<NotificationResult> {
    return this.enviarNotificacion({
      telefono,
      tipoTemplate: TipoTemplateTransporte.RECORDATORIO_MANTENIMIENTO,
      parametros: {
        unidad: datos.unidad,
        tipo_mantenimiento: datos.tipoMantenimiento,
        fecha_limite: datos.fechaLimite,
        km_actual: datos.kmActual,
        km_programado: datos.kmProgramado,
      },
    });
  }

  // ==========================================
  // Private Helpers
  // ==========================================

  /**
   * Clean and validate phone number
   */
  private limpiarTelefono(telefono: string): string | null {
    // Remove non-numeric characters
    const limpio = telefono.replace(/\D/g, '');

    // Mexican numbers: 10 digits (without country code) or 12 (with 52)
    if (limpio.length === 10) {
      return `52${limpio}`;
    } else if (limpio.length === 12 && limpio.startsWith('52')) {
      return limpio;
    } else if (limpio.length === 13 && limpio.startsWith('521')) {
      // Remove old mobile prefix
      return `52${limpio.slice(3)}`;
    }

    return null;
  }

  /**
   * Simulate message sending for development
   */
  private simularEnvio(
    telefono: string,
    template: WhatsAppTemplate,
    parametros: Record<string, string>
  ): NotificationResult {
    console.log(`[WhatsApp Simulation] Sending ${template.nombre} to ${telefono}`);
    console.log(`[WhatsApp Simulation] Parameters:`, parametros);

    return {
      success: true,
      messageId: `sim_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      timestamp: new Date(),
    };
  }

  /**
   * Send message via WhatsApp API (mock implementation)
   */
  private async enviarMensajeAPI(
    telefono: string,
    payload: { template: string; language: string; components: any[] }
  ): Promise<NotificationResult> {
    // In production, this would call Meta's Cloud API
    // POST https://graph.facebook.com/v17.0/{phone-number-id}/messages

    if (!this.config) {
      throw new Error('WhatsApp API no configurado');
    }

    // Mock implementation
    return {
      success: true,
      messageId: `wamid_${Date.now()}`,
      timestamp: new Date(),
    };
  }

  /**
   * Delay helper for rate limiting
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}
