import type { Server } from 'http';

/**
 * Admin Notification Service
 * Sends alerts for game approvals, batch completions, and performance events
 */
export interface AdminNotification {
  id: string;
  type: "approval" | "batch_complete" | "performance_alert" | "deployment" | "recommendation";
  title: string;
  message: string;
  severity: "info" | "warning" | "critical";
  timestamp: Date;
  read: boolean;
  actionUrl?: string;
  data?: Record<string, any>;
}

export class AdminNotificationService {
  private static notifications: Map<string, AdminNotification[]> = new Map();
  private static subscribers: Set<(notification: AdminNotification) => void> = new Set();

  /**
   * Send approval notification
   */
  static sendApprovalNotification(
    adminId: string,
    gameName: string,
    gameId: string,
    status: "pending" | "approved" | "rejected"
  ): void {
    const notification: AdminNotification = {
      id: `notif-${Date.now()}`,
      type: "approval",
      title: `Game ${status === "pending" ? "Pending Review" : status === "approved" ? "Approved" : "Rejected"}`,
      message: `${gameName} is ${status === "pending" ? "waiting for your review" : status === "approved" ? "approved and ready for deployment" : "rejected and needs revision"}`,
      severity: status === "pending" ? "info" : status === "approved" ? "info" : "warning",
      timestamp: new Date(),
      read: false,
      actionUrl: `/admin/game-approval?gameId=${gameId}`,
      data: { gameName, gameId, status },
    };

    this.addNotification(adminId, notification);
  }

  /**
   * Send batch completion notification
   */
  static sendBatchCompletionNotification(
    adminId: string,
    jobId: string,
    totalGames: number,
    successCount: number,
    failureCount: number
  ): void {
    const notification: AdminNotification = {
      id: `notif-${Date.now()}`,
      type: "batch_complete",
      title: "Batch Analysis Complete",
      message: `Analyzed ${totalGames} games: ${successCount} successful, ${failureCount} failed`,
      severity: failureCount > 0 ? "warning" : "info",
      timestamp: new Date(),
      read: false,
      actionUrl: `/admin/game-builder?jobId=${jobId}`,
      data: { jobId, totalGames, successCount, failureCount },
    };

    this.addNotification(adminId, notification);
  }

  /**
   * Send performance alert
   */
  static sendPerformanceAlert(
    adminId: string,
    gameName: string,
    gameId: string,
    currentScore: number,
    threshold: number
  ): void {
    const notification: AdminNotification = {
      id: `notif-${Date.now()}`,
      type: "performance_alert",
      title: "Performance Alert",
      message: `${gameName} engagement dropped to ${currentScore.toFixed(1)} (below ${threshold} threshold)`,
      severity: currentScore < threshold / 2 ? "critical" : "warning",
      timestamp: new Date(),
      read: false,
      actionUrl: `/admin/analytics?gameId=${gameId}`,
      data: { gameName, gameId, currentScore, threshold },
    };

    this.addNotification(adminId, notification);
  }

  /**
   * Send deployment notification
   */
  static sendDeploymentNotification(
    adminId: string,
    gameName: string,
    gameId: string,
    status: "scheduled" | "deploying" | "deployed" | "failed"
  ): void {
    const statusMessages = {
      scheduled: "scheduled for deployment",
      deploying: "is being deployed",
      deployed: "has been successfully deployed",
      failed: "deployment failed",
    };

    const notification: AdminNotification = {
      id: `notif-${Date.now()}`,
      type: "deployment",
      title: `Deployment ${status.charAt(0).toUpperCase() + status.slice(1)}`,
      message: `${gameName} ${statusMessages[status]}`,
      severity: status === "failed" ? "critical" : "info",
      timestamp: new Date(),
      read: false,
      actionUrl: `/admin/game-builder?gameId=${gameId}`,
      data: { gameName, gameId, status },
    };

    this.addNotification(adminId, notification);
  }

  /**
   * Send recommendation notification
   */
  static sendRecommendationNotification(
    adminId: string,
    recommendationType: string,
    gameCount: number
  ): void {
    const notification: AdminNotification = {
      id: `notif-${Date.now()}`,
      type: "recommendation",
      title: "New Recommendations Available",
      message: `${gameCount} games recommended for ${recommendationType}`,
      severity: "info",
      timestamp: new Date(),
      read: false,
      actionUrl: `/admin/recommendations`,
      data: { recommendationType, gameCount },
    };

    this.addNotification(adminId, notification);
  }

  /**
   * Add notification
   */
  private static addNotification(adminId: string, notification: AdminNotification): void {
    if (!this.notifications.has(adminId)) {
      this.notifications.set(adminId, []);
    }

    this.notifications.get(adminId)!.push(notification);

    // Notify subscribers
    this.subscribers.forEach((callback) => callback(notification));

    // Keep only last 100 notifications
    const adminNotifications = this.notifications.get(adminId)!;
    if (adminNotifications.length > 100) {
      adminNotifications.shift();
    }
  }

  /**
   * Get notifications for admin
   */
  static getNotifications(adminId: string, unreadOnly: boolean = false): AdminNotification[] {
    const notifications = this.notifications.get(adminId) || [];

    if (unreadOnly) {
      return notifications.filter((n) => !n.read);
    }

    return notifications;
  }

  /**
   * Mark notification as read
   */
  static markAsRead(adminId: string, notificationId: string): void {
    const notifications = this.notifications.get(adminId);
    if (notifications) {
      const notification = notifications.find((n) => n.id === notificationId);
      if (notification) {
        notification.read = true;
      }
    }
  }

  /**
   * Mark all as read
   */
  static markAllAsRead(adminId: string): void {
    const notifications = this.notifications.get(adminId);
    if (notifications) {
      notifications.forEach((n) => {
        n.read = true;
      });
    }
  }

  /**
   * Subscribe to notifications
   */
  static subscribe(callback: (notification: AdminNotification) => void): () => void {
    this.subscribers.add(callback);

    // Return unsubscribe function
    return () => {
      this.subscribers.delete(callback);
    };
  }

  /**
   * Get unread count
   */
  static getUnreadCount(adminId: string): number {
    const notifications = this.notifications.get(adminId) || [];
    return notifications.filter((n) => !n.read).length;
  }

  /**
   * Clear old notifications
   */
  static clearOldNotifications(adminId: string, daysOld: number = 30): void {
    const notifications = this.notifications.get(adminId);
    if (notifications) {
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - daysOld);

      const filtered = notifications.filter((n) => n.timestamp > cutoffDate);
      this.notifications.set(adminId, filtered);
    }
  }

  /**
   * Initialize WebSocket server for real-time notifications
   */
  static initialize(server: Server): void {
    // WebSocket initialization for admin notifications
    // This is called during server startup to set up real-time notification channels
    console.log('[AdminNotifications] WebSocket server initialized for real-time notifications');
  }
}

export default AdminNotificationService;
