/**
 * Push Notification Channel
 * Handles Web Push notifications using VAPID
 */

import { PushNotificationData, PushSubscription } from '../types';

interface PushConfig {
  vapidPublicKey: string;
  vapidPrivateKey: string;
  vapidSubject: string;
}

export class PushChannel {
  private config: PushConfig;
  private subscriptions: Map<string, PushSubscription[]> = new Map();

  constructor(config: PushConfig) {
    this.config = config;
  }

  /**
   * Send a push notification
   */
  async send(data: PushNotificationData): Promise<void> {
    if (!this.config.vapidPublicKey || !this.config.vapidPrivateKey) {
      console.log('[PushChannel] VAPID keys not configured - simulating push');
      return;
    }

    const payload = JSON.stringify({
      title: data.title,
      body: data.body,
      icon: data.icon || '/icons/icon-192x192.png',
      badge: data.badge || '/icons/badge-72x72.png',
      data: data.data,
      actions: data.actions
    });

    // In production, this would use web-push library:
    // const webpush = require('web-push');
    // webpush.setVapidDetails(
    //   this.config.vapidSubject,
    //   this.config.vapidPublicKey,
    //   this.config.vapidPrivateKey
    // );
    // await webpush.sendNotification(subscription, payload);

    console.log(`[PushChannel] Push notification sent: ${data.title}`);
  }

  /**
   * Subscribe a user to push notifications
   */
  subscribe(userId: string, subscription: Omit<PushSubscription, 'userId' | 'createdAt'>): PushSubscription {
    const fullSubscription: PushSubscription = {
      ...subscription,
      userId,
      createdAt: new Date().toISOString()
    };

    const userSubs = this.subscriptions.get(userId) || [];

    // Check if subscription already exists
    const existing = userSubs.find(s => s.endpoint === subscription.endpoint);
    if (existing) {
      existing.lastUsedAt = new Date().toISOString();
      return existing;
    }

    userSubs.push(fullSubscription);
    this.subscriptions.set(userId, userSubs);

    console.log(`[PushChannel] User ${userId} subscribed to push notifications`);
    return fullSubscription;
  }

  /**
   * Unsubscribe from push notifications
   */
  unsubscribe(userId: string, endpoint?: string): boolean {
    if (!endpoint) {
      // Remove all subscriptions for user
      this.subscriptions.delete(userId);
      return true;
    }

    const userSubs = this.subscriptions.get(userId);
    if (!userSubs) return false;

    const index = userSubs.findIndex(s => s.endpoint === endpoint);
    if (index === -1) return false;

    userSubs.splice(index, 1);
    if (userSubs.length === 0) {
      this.subscriptions.delete(userId);
    } else {
      this.subscriptions.set(userId, userSubs);
    }

    return true;
  }

  /**
   * Get subscriptions for a user
   */
  getSubscriptions(userId: string): PushSubscription[] {
    return this.subscriptions.get(userId) || [];
  }

  /**
   * Check if user has push subscriptions
   */
  hasSubscription(userId: string): boolean {
    const subs = this.subscriptions.get(userId);
    return subs !== undefined && subs.length > 0;
  }

  /**
   * Send to all user's subscriptions
   */
  async sendToUser(userId: string, data: Omit<PushNotificationData, 'token'>): Promise<void> {
    const subscriptions = this.getSubscriptions(userId);

    for (const sub of subscriptions) {
      try {
        await this.send({
          ...data,
          token: sub.endpoint
        });
        sub.lastUsedAt = new Date().toISOString();
      } catch (error: any) {
        console.error(`[PushChannel] Failed to send to ${sub.endpoint}:`, error.message);
        // Remove invalid subscriptions
        if (error.statusCode === 410 || error.statusCode === 404) {
          this.unsubscribe(userId, sub.endpoint);
        }
      }
    }
  }

  /**
   * Get VAPID public key for client
   */
  getPublicKey(): string {
    return this.config.vapidPublicKey;
  }

  /**
   * Generate VAPID keys (utility method)
   */
  static generateVapidKeys(): { publicKey: string; privateKey: string } {
    // In production, use web-push library:
    // const webpush = require('web-push');
    // return webpush.generateVAPIDKeys();

    // For development, return placeholder keys
    return {
      publicKey: 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
      privateKey: 'UUxI4O8-FbRouADVXc-hK3ltRAc8_DIoISjp22LG0S0'
    };
  }
}
