// Notification Service
// Email, SMS, and portal notifications for IRU workflow events

export interface NotificationRequest {
  recipient: string;
  recipientType: 'email' | 'sms' | 'portal';
  template: string;
  variables: Record<string, any>;
  priority?: 'low' | 'normal' | 'high' | 'urgent';
}

export interface NotificationResult {
  success: boolean;
  notificationId?: string;
  sentAt?: Date;
  error?: string;
}

export class NotificationService {
  /**
   * Send notification
   */
  async sendNotification(request: NotificationRequest): Promise<NotificationResult> {
    switch (request.recipientType) {
      case 'email':
        return this.sendEmail(request);
      case 'sms':
        return this.sendSMS(request);
      case 'portal':
        return this.sendPortalNotification(request);
      default:
        throw new Error(`Unsupported recipient type: ${request.recipientType}`);
    }
  }

  /**
   * Send email notification
   */
  private async sendEmail(request: NotificationRequest): Promise<NotificationResult> {
    const emailProvider = process.env.EMAIL_PROVIDER || 'smtp';
    const emailApiKey = process.env.EMAIL_API_KEY || '';

    try {
      let result: NotificationResult;

      if (emailProvider === 'sendgrid') {
        result = await this.sendViaSendGrid(request, emailApiKey);
      } else if (emailProvider === 'ses') {
        result = await this.sendViaSES(request, emailApiKey);
      } else {
        result = await this.sendViaSMTP(request);
      }

      return result;
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  /**
   * Send via SendGrid
   */
  private async sendViaSendGrid(request: NotificationRequest, apiKey: string): Promise<NotificationResult> {
    const templateContent = await this.getTemplateContent(request.template, request.variables);

    const response = await fetch('https://api.sendgrid.com/v3/mail/send', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        personalizations: [
          {
            to: [{ email: request.recipient }],
            subject: templateContent.subject,
          },
        ],
        from: {
          email: process.env.EMAIL_FROM || 'noreply@dbis.org',
          name: process.env.EMAIL_FROM_NAME || 'SolaceNet',
        },
        content: [
          {
            type: 'text/html',
            value: templateContent.body,
          },
        ],
      }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(`SendGrid API error: ${response.status} ${error}`);
    }

    return {
      success: true,
      notificationId: response.headers.get('x-message-id') || undefined,
      sentAt: new Date(),
    };
  }

  /**
   * Send via AWS SES
   */
  private async sendViaSES(request: NotificationRequest, apiKey: string): Promise<NotificationResult> {
    const { sesIntegration } = await import('./ses-integration.service');
    const templateContent = await this.getTemplateContent(request.template, request.variables);

    const result = await sesIntegration.sendEmail({
      to: request.recipient,
      subject: templateContent.subject,
      body: templateContent.body,
    });

    return {
      success: true,
      notificationId: result.messageId,
      sentAt: new Date(),
    };
  }

  /**
   * Send via SMTP
   */
  private async sendViaSMTP(request: NotificationRequest): Promise<NotificationResult> {
    const { smtpIntegration } = await import('./smtp-integration.service');
    const templateContent = await this.getTemplateContent(request.template, request.variables);

    const result = await smtpIntegration.sendEmail({
      to: request.recipient,
      subject: templateContent.subject,
      body: templateContent.body,
    });

    return {
      success: true,
      notificationId: result.messageId,
      sentAt: new Date(),
    };
  }

  /**
   * Send SMS notification
   */
  private async sendSMS(request: NotificationRequest): Promise<NotificationResult> {
    const smsProvider = process.env.SMS_PROVIDER || 'twilio';
    const smsApiKey = process.env.SMS_API_KEY || '';

    try {
      if (smsProvider === 'twilio') {
        return await this.sendViaTwilio(request, smsApiKey);
      } else {
        throw new Error(`Unsupported SMS provider: ${smsProvider}`);
      }
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  /**
   * Send via Twilio
   */
  private async sendViaTwilio(request: NotificationRequest, apiKey: string): Promise<NotificationResult> {
    const twilioAccountSid = process.env.TWILIO_ACCOUNT_SID || '';
    const twilioAuthToken = process.env.TWILIO_AUTH_TOKEN || '';
    const twilioPhoneNumber = process.env.TWILIO_PHONE_NUMBER || '';

    const templateContent = await this.getTemplateContent(request.template, request.variables);
    const message = templateContent.body.replace(/<[^>]*>/g, ''); // Strip HTML tags

    const response = await fetch(
      `https://api.twilio.com/2010-04-01/Accounts/${twilioAccountSid}/Messages.json`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Basic ${Buffer.from(`${twilioAccountSid}:${twilioAuthToken}`).toString('base64')}`,
          'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
          From: twilioPhoneNumber,
          To: request.recipient,
          Body: message,
        }),
      }
    );

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`Twilio API error: ${error.message || 'Unknown error'}`);
    }

    const data = await response.json();

    return {
      success: true,
      notificationId: data.sid,
      sentAt: new Date(),
    };
  }

  /**
   * Send portal notification
   */
  private async sendPortalNotification(request: NotificationRequest): Promise<NotificationResult> {
    // Store notification in database for portal display
    const { notificationStorageService } = await import('./notification-storage.service');
    
    const notification = await notificationStorageService.storePortalNotification(
      request.recipient, // recipientId
      request.template,
      request.variables,
      request.priority || 'normal'
    );

    return {
      success: true,
      notificationId: notification.notificationId,
      sentAt: new Date(),
    };
  }

  /**
   * Get template content
   */
  private async getTemplateContent(template: string, variables: Record<string, any>): Promise<{ subject: string; body: string }> {
    // Load template from database or filesystem
    const { templateLoaderService } = await import('./template-loader.service');
    const templateData = await templateLoaderService.loadTemplate(template);

    // Replace variables in template
    let subject = templateData.subject;
    let body = templateData.body;

    for (const [key, value] of Object.entries(variables)) {
      const regex = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
      subject = subject.replace(regex, String(value));
      body = body.replace(regex, String(value));
    }

    return {
      subject,
      body,
    };
  }
}

export const notificationService = new NotificationService();
