import twilio from 'twilio';
import { loadNotificationConfig } from '../config/notification.config';
import type { SMSNotification, NotificationResult } from '../types/notification.types';

const config = loadNotificationConfig();
const twilioClient = twilio(
  config.twilio.accountSid,
  config.twilio.authToken
);

export class SMSService {
  private static instance: SMSService;
  private sentCount = new Map<string, number>();
  private cleanupInterval: NodeJS.Timeout;

  private constructor() {
    this.cleanupInterval = setInterval(() => {
      const now = Date.now();
      for (const [key, timestamp] of this.sentCount.entries()) {
        if (now - timestamp > 60000) {
          this.sentCount.delete(key);
        }
      }
    }, 60000);
  }

  static getInstance(): SMSService {
    if (!SMSService.instance) {
      SMSService.instance = new SMSService();
    }
    return SMSService.instance;
  }

  async send(notification: SMSNotification): Promise<NotificationResult> {
    const rateLimitKey = `sms:${notification.to}`;
    const currentCount = this.sentCount.get(rateLimitKey) || 0;

    if (currentCount >= config.rateLimits.smsPerMinute) {
      throw new Error(`SMS rate limit exceeded for ${notification.to}`);
    }

    try {
      const message = await twilioClient.messages.create({
        body: notification.body,
        from: notification.from || config.twilio.messagingServiceSid,
        to: notification.to,
        metadata: notification.metadata,
      });

      this.sentCount.set(rateLimitKey, currentCount + 1);

      return {
        notificationId: `sms-${message.sid}`,
        channel: 'sms',
        status: 'sent',
        externalId: message.sid,
        deliveredAt: new Date(),
      };
    } catch (error) {
      return {
        notificationId: `sms-${Date.now()}`,
        channel: 'sms',
        status: 'failed',
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  async sendBatch(notifications: SMSNotification[]): Promise<NotificationResult[]> {
    const results = await Promise.all(
      notifications.map(n => this.send(n))
    );
    return results;
  }

  getRateLimitStatus(): { remaining: number; limit: number } {
    return {
      remaining: config.rateLimits.smsPerMinute - this.sentCount.size,
      limit: config.rateLimits.smsPerMinute,
    };
  }
}
