import database from "../../config/db";
import { sendSocketNotification } from "../../config/socket.io";
import { sendEmail } from "../../utils/sendEmail";

export interface NotificationData {
  recipient_id: string;
  sender_id?: string;
  type: string;
  title: string;
  message: string;
  metadata?: any;
  priority?: 'low' | 'normal' | 'high' | 'urgent';
  action_url?: string;
  action_label?: string;
}

export class NotificationService {
  // Create and send notification
  static async createAndSendNotification(data: NotificationData) {
    try {
      // Check recipient's notification preferences
      const recipientResult = await database.query(
        `SELECT email_notifications, push_notifications FROM accounts WHERE id = $1`,
        [data.recipient_id]
      );
      
      if (recipientResult.rows.length === 0) {
        throw new Error("Recipient not found");
      }
      
      const recipient = recipientResult.rows[0];
      
      // Create notification in database
      const notificationResult = await database.query(
        `INSERT INTO notifications (
          recipient_id,
          sender_id,
          type,
          title,
          message,
          metadata,
          priority,
          action_url,
          action_label,
          delivery_status
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, 'pending')
        RETURNING *`,
        [
          data.recipient_id,
          data.sender_id || null,
          data.type,
          data.title,
          data.message,
          data.metadata || {},
          data.priority || 'normal',
          data.action_url || null,
          data.action_label || null,
        ]
      );
      
      const notification = notificationResult.rows[0];
      
      // Send via socket (real-time)
      await this.sendSocketNotification(notification);
      
      // Send email if enabled for this notification type
      if (this.shouldSendEmail(recipient.email_notifications, data.type)) {
        await this.sendEmailNotification(data);
      }
      
      // Update delivery status
      await database.query(
        `UPDATE notifications SET delivery_status = 'sent', delivered_at = CURRENT_TIMESTAMP WHERE id = $1`,
        [notification.id]
      );
      
      return notification;
    } catch (error) {
      console.error("Error creating notification:", error);
      
      // Update delivery status to failed
      if (data.recipient_id) {
        await database.query(
          `UPDATE notifications 
           SET delivery_status = 'failed'
           WHERE recipient_id = $1 
           AND type = $2 
           AND delivery_status = 'pending'
           ORDER BY created_at DESC 
           LIMIT 1`,
          [data.recipient_id, data.type]
        );
      }
      
      throw error;
    }
  }
  
  // Send notification via socket
  private static async sendSocketNotification(notification: any) {
    try {
      const formattedNotification = {
        id: notification.id,
        type: notification.type,
        title: notification.title,
        message: notification.message,
        metadata: notification.metadata,
        created_at: notification.created_at,
        is_read: notification.is_read,
        action_url: notification.action_url,
        action_label: notification.action_label,
      };
      
      sendSocketNotification(notification.recipient_id, formattedNotification);
    } catch (error) {
      console.error("Error sending socket notification:", error);
    }
  }
  
  // Send email notification
  private static async sendEmailNotification(data: NotificationData) {
    try {
      // Get recipient email
      const recipientResult = await database.query(
        `SELECT email FROM accounts WHERE id = $1`,
        [data.recipient_id]
      );
      
      if (recipientResult.rows.length === 0) {
        return;
      }
      
      const recipientEmail = recipientResult.rows[0].email;
      
      // Create email template
      const emailTemplate = `
        <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
          <h2 style="color: #333;">${data.title}</h2>
          <div style="background-color: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0;">
            ${data.message}
          </div>
          
          ${data.action_url ? `
            <div style="margin: 25px 0;">
              <a href="${process.env.FRONTEND_URL}${data.action_url}" 
                 style="background-color: #2b65f0; color: white; padding: 12px 24px; text-decoration: none; border-radius: 5px;">
                ${data.action_label || 'View Details'}
              </a>
            </div>
          ` : ''}
          
          <div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #e0e0e0; font-size: 12px; color: #666;">
            <p>You received this email because you have an account on Toolffy.</p>
            <p>
              <a href="${process.env.FRONTEND_URL}/settings/notifications" 
                 style="color: #2b65f0;">
                Manage notification preferences
              </a>
            </p>
          </div>
        </div>
      `;
      
      await sendEmail({
        email: recipientEmail,
        subject: data.title,
        message: emailTemplate,
      });
    } catch (error) {
      console.error("Error sending email notification:", error);
    }
  }
  
  // Check if email should be sent based on user preferences
  private static shouldSendEmail(emailPreferences: any, notificationType: string): boolean {
    if (!emailPreferences) return false;
    
    const typeMapping: Record<string, string> = {
      'follow_request': 'new_followers',
      'follow_accepted': 'new_followers',
      'new_message': 'messages',
      'new_comment': 'comment_replies',
      'post_like': 'comment_replies',
      'post_share': 'comment_replies',
      'company_update': 'product_updates',
      'product_launch': 'product_updates',
      'achievement_unlocked': 'achievements',
      'system_alert': 'security_alerts',
      'security_alert': 'security_alerts',
    };
    
    const preferenceKey = typeMapping[notificationType] || notificationType;
    
    return emailPreferences[preferenceKey] === true;
  }
  
  // Batch create notifications for multiple recipients
  static async batchCreateNotifications(recipientIds: string[], data: Omit<NotificationData, 'recipient_id'>) {
    const notifications = [];
    
    for (const recipientId of recipientIds) {
      try {
        const notification = await this.createAndSendNotification({
          ...data,
          recipient_id: recipientId,
        });
        notifications.push(notification);
      } catch (error) {
        console.error(`Error creating notification for user ${recipientId}:`, error);
      }
    }
    
    return notifications;
  }
  
  // Get notification statistics
  static async getStatistics(accountId: string, timeframe: 'day' | 'week' | 'month' = 'week') {
    let interval = '7 days';
    switch (timeframe) {
      case 'day':
        interval = '1 day';
        break;
      case 'week':
        interval = '7 days';
        break;
      case 'month':
        interval = '30 days';
        break;
    }
    
    const statsResult = await database.query(
      `SELECT 
        type,
        COUNT(*) as total,
        SUM(CASE WHEN is_read THEN 1 ELSE 0 END) as read_count,
        SUM(CASE WHEN NOT is_read THEN 1 ELSE 0 END) as unread_count,
        AVG(CASE WHEN is_read THEN EXTRACT(EPOCH FROM (read_at - created_at)) ELSE NULL END) as avg_read_time_seconds
      FROM notifications
      WHERE recipient_id = $1 
        AND created_at >= CURRENT_TIMESTAMP - INTERVAL '${interval}'
      GROUP BY type
      ORDER BY total DESC`,
      [accountId]
    );
    
    return statsResult.rows;
  }
}