/**
 * Infrastructure: NotificationGatewayRegistry
 * 
 * Manages notification gateways and routes notifications to appropriate channels.
 */

import type { Notification } from '@core/notifications/domain/entities/Notification';
import type { NotificationChannel } from '@core/notifications/domain/types/NotificationTypes';
import type {
  NotificationGateway,
  NotificationGatewayRegistry as INotificationGatewayRegistry,
  NotificationDeliveryResult
} from '@core/notifications/application/ports/NotificationGateway';

export class NotificationGatewayRegistry implements INotificationGatewayRegistry {
  private gateways: Map<NotificationChannel, NotificationGateway> = new Map();

  constructor(initialGateways: NotificationGateway[] = []) {
    initialGateways.forEach(gateway => this.register(gateway));
  }

  register(gateway: NotificationGateway): void {
    const channel = gateway.getChannel();
    this.gateways.set(channel, gateway);
  }

  getGateway(channel: NotificationChannel): NotificationGateway | null {
    return this.gateways.get(channel) || null;
  }

  getAllGateways(): NotificationGateway[] {
    return Array.from(this.gateways.values());
  }

  async send(notification: Notification): Promise<NotificationDeliveryResult> {
    const gateway = this.gateways.get(notification.channel);
    
    if (!gateway) {
      return {
        success: false,
        channel: notification.channel,
        error: `No gateway registered for channel: ${notification.channel}`,
        attemptedAt: new Date(),
      };
    }

    if (!gateway.isConfigured()) {
      return {
        success: false,
        channel: notification.channel,
        error: `Gateway for channel ${notification.channel} is not configured`,
        attemptedAt: new Date(),
      };
    }

    try {
      return await gateway.send(notification);
    } catch (error) {
      return {
        success: false,
        channel: notification.channel,
        error: error instanceof Error ? error.message : 'Unknown error during delivery',
        attemptedAt: new Date(),
      };
    }
  }
}