import { getWebSocketService } from '../websocket';

export interface NotificationData {
  type: 'order_update' | 'new_order' | 'courier_location' | 'system_alert' | 'sos_request' | 'emergency_alert';
  title: string;
  message: string;
  data?: any;
  priority: 'low' | 'medium' | 'high' | 'urgent' | 'critical';
  timestamp: Date;
  actions?: NotificationAction[];
  expiresAt?: Date;
  channels?: string[];
}

export interface NotificationAction {
  id: string;
  label: string;
  action: 'navigate' | 'api_call' | 'dismiss';
  payload?: Record<string, any>;
}

export interface OrderNotificationData {
  orderId: string;
  status: string;
  details?: any;
  userIds: string[];
}

export class NotificationService {
  private wsService = getWebSocketService;

  // Send real-time notification to specific users
  async sendNotification(userIds: string[], notification: NotificationData) {
    const wsService = this.wsService();
    if (!wsService) {
      console.warn('WebSocket service not available');
      return;
    }

    const message = {
      type: 'notification',
      data: notification,
      timestamp: new Date().toISOString()
    };

    userIds.forEach(userId => {
      wsService.sendToUser(userId, message);
    });

    // Log notification for debugging
    console.log(`Notification sent to ${userIds.length} users:`, notification.title);
  }

  // Send notification to users by role
  async sendNotificationToRole(role: string, notification: NotificationData) {
    const wsService = this.wsService();
    if (!wsService) {
      console.warn('WebSocket service not available');
      return;
    }

    const message = {
      type: 'notification',
      data: notification,
      timestamp: new Date().toISOString()
    };

    wsService.sendToRole(role, message);
    console.log(`Notification sent to role ${role}:`, notification.title);
  }

  // Notify order status change with smart routing
  async notifyOrderUpdate(orderData: OrderNotificationData) {
    const wsService = this.wsService();
    if (!wsService) {
      console.warn('WebSocket service not available');
      return;
    }

    // Create status-specific notifications
    const notifications = this.createOrderNotifications(orderData);

    // Send to relevant users
    orderData.userIds.forEach(userId => {
      const userNotification = notifications[this.getUserRole(userId)] || notifications.default;
      
      wsService.sendToUser(userId, {
        type: 'order_status_change',
        orderId: orderData.orderId,
        status: orderData.status,
        data: userNotification,
        timestamp: new Date().toISOString()
      });
    });

    console.log(`Order ${orderData.orderId} status update sent to ${orderData.userIds.length} users`);
  }

  // Broadcast new SOS order to nearby pharmacies with enhanced urgency
  async broadcastNewOrder(orderData: any, pharmacyIds: string[]) {
    const wsService = this.wsService();
    if (!wsService) {
      console.warn('WebSocket service not available');
      return;
    }

    const notification: NotificationData = {
      type: 'sos_request',
      title: '🚨 URGENCE MÉDICALE',
      message: `Nouvelle demande SOS: ${orderData.medicineName} (${orderData.quantity}x)`,
      data: {
        ...orderData,
        isUrgent: true,
        location: orderData.address
      },
      priority: 'critical',
      timestamp: new Date(),
      actions: [
        { id: 'accept', label: 'Accepter', action: 'api_call', payload: { orderId: orderData.id, action: 'accept' } },
        { id: 'reject', label: 'Rejeter', action: 'api_call', payload: { orderId: orderData.id, action: 'reject' } },
        { id: 'view', label: 'Voir détails', action: 'navigate', payload: { path: `/orders/${orderData.id}` } }
      ],
      expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes
      channels: ['websocket', 'push', 'sms']
    };

    // Send to each pharmacy with urgency flag
    pharmacyIds.forEach(pharmacyId => {
      wsService.sendToUser(pharmacyId, {
        type: 'sos_request',
        data: orderData,
        notification,
        urgent: true,
        timestamp: new Date().toISOString()
      });
    });

    console.log(`🚨 URGENT SOS order ${orderData.id} broadcasted to ${pharmacyIds.length} pharmacies`);
  }

  // New method for emergency alerts
  async sendEmergencyAlert(title: string, message: string, targetUsers?: string[], targetRoles?: string[]) {
    const wsService = this.wsService();
    if (!wsService) {
      console.warn('WebSocket service not available');
      return;
    }

    const notification: NotificationData = {
      type: 'emergency_alert',
      title: `🚨 ${title}`,
      message,
      priority: 'critical',
      timestamp: new Date(),
      actions: [
        { id: 'acknowledge', label: 'Accusé de réception', action: 'api_call', payload: { action: 'acknowledge' } }
      ],
      channels: ['websocket', 'push', 'sms']
    };

    const alertData = {
      type: 'emergency_alert',
      data: notification,
      critical: true,
      timestamp: new Date().toISOString()
    };

    // Send to specific users if provided
    if (targetUsers && targetUsers.length > 0) {
      targetUsers.forEach(userId => {
        wsService.sendToUser(userId, alertData);
      });
    }

    // Send to specific roles if provided
    if (targetRoles && targetRoles.length > 0) {
      targetRoles.forEach(role => {
        wsService.sendToRole(role, alertData);
      });
    }

    // If no specific targets, send to all connected users
    if (!targetUsers && !targetRoles) {
      ['client', 'pharmacy', 'courier', 'admin'].forEach(role => {
        wsService.sendToRole(role, alertData);
      });
    }

    console.log(`🚨 Emergency alert sent: ${title}`);
  }

  // Send courier location update
  async broadcastCourierLocation(courierId: string, location: { lat: number; lng: number }, orderId?: string) {
    const wsService = this.wsService();
    if (!wsService) {
      console.warn('WebSocket service not available');
      return;
    }

    const message = {
      type: 'courier_location',
      courierId,
      orderId,
      location,
      timestamp: new Date().toISOString()
    };

    // If orderId provided, send to specific order participants
    if (orderId) {
      // In a real implementation, get order participants from database
      // For now, broadcast to all connected clients
      wsService.broadcastCourierLocation(courierId, location);
    } else {
      wsService.broadcastCourierLocation(courierId, location);
    }

    console.log(`Courier ${courierId} location update broadcasted`);
  }

  // Send system-wide alert
  async sendSystemAlert(message: string, priority: 'low' | 'medium' | 'high' | 'urgent' = 'medium') {
    const wsService = this.wsService();
    if (!wsService) {
      console.warn('WebSocket service not available');
      return;
    }

    const notification: NotificationData = {
      type: 'system_alert',
      title: 'Alerte système',
      message,
      priority,
      timestamp: new Date()
    };

    // Send to all connected users
    ['client', 'pharmacy', 'courier', 'admin'].forEach(role => {
      wsService.sendToRole(role, {
        type: 'system_alert',
        data: notification,
        timestamp: new Date().toISOString()
      });
    });

    console.log(`System alert sent: ${message}`);
  }

  private createOrderNotifications(orderData: OrderNotificationData): Record<string, any> {
    const statusMessages: Record<string, Record<string, string>> = {
      'PHARMACY_CONFIRMED': {
        client: 'Votre commande a été confirmée par la pharmacie',
        pharmacy: 'Vous avez confirmé la commande',
        admin: 'Commande confirmée par la pharmacie'
      },
      'COURIER_ASSIGNED': {
        client: 'Un livreur a été assigné à votre commande',
        pharmacy: 'Un livreur a été assigné à la commande',
        courier: 'Nouvelle livraison assignée',
        admin: 'Livreur assigné à la commande'
      },
      'PICKED_UP': {
        client: 'Votre commande a été récupérée par le livreur',
        pharmacy: 'La commande a été récupérée',
        courier: 'Commande récupérée - direction client',
        admin: 'Commande récupérée par le livreur'
      },
      'IN_TRANSIT': {
        client: 'Votre commande est en cours de livraison',
        pharmacy: 'La commande est en cours de livraison',
        courier: 'En cours de livraison',
        admin: 'Commande en transit'
      },
      'DELIVERED': {
        client: 'Votre commande a été livrée avec succès',
        pharmacy: 'Commande livrée avec succès',
        courier: 'Livraison terminée avec succès',
        admin: 'Commande livrée'
      },
      'CANCELLED': {
        client: 'Votre commande a été annulée',
        pharmacy: 'La commande a été annulée',
        courier: 'La livraison a été annulée',
        admin: 'Commande annulée'
      },
      'NO_PHARMACY_AVAILABLE': {
        client: 'Aucune pharmacie disponible dans votre zone actuellement',
        admin: 'Aucune pharmacie disponible pour la commande'
      }
    };

    const messages = statusMessages[orderData.status] || {};
    
    return {
      client: messages.client || `Mise à jour de commande: ${orderData.status}`,
      pharmacy: messages.pharmacy || `Mise à jour de commande: ${orderData.status}`,
      courier: messages.courier || `Mise à jour de commande: ${orderData.status}`,
      admin: messages.admin || `Mise à jour de commande: ${orderData.status}`,
      default: `Commande ${orderData.orderId.substring(0, 8)} mise à jour`
    };
  }

  private getUserRole(userId: string): string {
    // In a real implementation, get user role from database
    // For now, return default
    return 'default';
  }
}

export const notificationService = new NotificationService();