
import { Service } from "@/types/service.types";
import { processTemplate, generateDefaultMessage } from "./notification/templateProcessor";
import { sendTelegramNotification, testSendTelegramMessage } from "./notification/telegramService";
import { pb } from "@/lib/pocketbase";
import { templateService } from "./templateService";
import { AlertConfiguration } from "./alertConfigService";

interface NotificationData {
  service: Service;
  status: string;
  responseTime?: number;
  timestamp: string;
  _notificationSource?: string;
}

// Track last notification times for services to implement cooldown
const lastNotifications: Record<string, {
  timestamp: Date;
  count: number;
}> = {};

// Cooldown period in milliseconds (5 minutes)
const NOTIFICATION_COOLDOWN = 5 * 60 * 1000; 

export const notificationService = {
  /**
   * Send a notification for a service status change
   */
  async sendNotification(data: NotificationData): Promise<boolean> {
    try {
      const { service, status, responseTime } = data;
      
      console.log(`Preparing to send notification for service: ${service.name}, status: ${status}`);
      console.log(`Service alerts status: ${service.alerts}`);
      
      // First check if alerts are muted for this service
      // STRICT equality check against "muted" string value
      if (service.alerts === "muted") {
        console.log(`NOTIFICATION BLOCKED: Alerts are muted for service: ${service.name}`);
        return true; // Return true as this is expected behavior
      }
      
      // For paused status, check if this is a duplicate notification from another source
      // This helps prevent the double-notification issue
      if (status === "paused" && data._notificationSource === "duplicate_check") {
        console.log("NOTIFICATION BLOCKED: Duplicate pause notification detected");
        return true; // Return true as this is expected behavior
      }
      
      // For DOWN status, implement the cooldown and max retries logic
      if (status === "down") {
        const serviceId = service.id;
        const maxRetries = service.retries || 3; // Default to 3 if not specified
        const now = new Date();
        
        if (lastNotifications[serviceId]) {
          const lastNotif = lastNotifications[serviceId];
          const timeSinceLastNotif = now.getTime() - lastNotif.timestamp.getTime();
          
          // Check if we're within the cooldown period
          if (timeSinceLastNotif < NOTIFICATION_COOLDOWN) {
            // Increment count only if we haven't reached max retries
            if (lastNotif.count < maxRetries) {
              console.log(`DOWN notification for ${service.name}: ${lastNotif.count + 1}/${maxRetries}`);
              lastNotifications[serviceId].count += 1;
            } else {
              console.log(`DOWN notification for ${service.name} skipped: Max retries (${maxRetries}) reached. Next notification after cooldown.`);
              return true; // Skip notification but return success
            }
          } else {
            // Reset count after cooldown period
            console.log(`Cooldown period elapsed for ${service.name}. Resetting notification count.`);
            lastNotifications[serviceId] = { timestamp: now, count: 1 };
          }
        } else {
          // First notification for this service
          console.log(`First DOWN notification for ${service.name}: 1/${maxRetries}`);
          lastNotifications[serviceId] = { timestamp: now, count: 1 };
        }
        
        // Update timestamp for the current notification
        lastNotifications[serviceId].timestamp = now;
      }
      
      // Check if notification channel is set
      if (!service.notificationChannel) {
        console.log(`No notification channel set for service: ${service.name}`);
        return false;
      }
      
      // Fetch the notification configuration
      const alertConfigRecord = await pb.collection('alert_configurations').getOne(service.notificationChannel);
      
      if (!alertConfigRecord) {
        console.error(`Alert configuration not found for ID: ${service.notificationChannel}`);
        return false;
      }
      
      if (!alertConfigRecord.enabled) {
        console.log(`Alert configuration is disabled for service: ${service.name}`);
        return false;
      }
      
      // Convert PocketBase record to AlertConfiguration
      const alertConfig: AlertConfiguration = {
        id: alertConfigRecord.id,
        collectionId: alertConfigRecord.collectionId,
        collectionName: alertConfigRecord.collectionName,
        service_id: alertConfigRecord.service_id || "",
        notification_type: alertConfigRecord.notification_type,
        telegram_chat_id: alertConfigRecord.telegram_chat_id,
        discord_webhook_url: alertConfigRecord.discord_webhook_url,
        signal_number: alertConfigRecord.signal_number,
        notify_name: alertConfigRecord.notify_name,
        bot_token: alertConfigRecord.bot_token,
        template_id: alertConfigRecord.template_id,
        slack_webhook_url: alertConfigRecord.slack_webhook_url,
        enabled: alertConfigRecord.enabled,
        created: alertConfigRecord.created,
        updated: alertConfigRecord.updated
      };
      
      // Select template if one is specified
      let template;
      if (service.alertTemplate) {
        try {
          template = await templateService.getTemplate(service.alertTemplate);
        } catch (error) {
          console.error(`Error fetching template for ID: ${service.alertTemplate}`, error);
        }
      }
      
      // Generate the notification message
      let message;
      if (template) {
        message = processTemplate(template, service, status, responseTime);
      } else {
        message = generateDefaultMessage(service.name, status, responseTime);
      }
      
      // For DOWN status, add retry information to the message
      if (status === "down" && lastNotifications[service.id]) {
        const retryInfo = lastNotifications[service.id];
        const maxRetries = service.retries || 3;
        message += `\n\nAlert ${retryInfo.count}/${maxRetries}`;
      }
      
      console.log(`Prepared notification message: ${message}`);
      
      // Send notification based on notification type
      const notificationType = alertConfig.notification_type;
      
      if (notificationType === 'telegram') {
        return await sendTelegramNotification(alertConfig, message);
      }
      
      // For other types like discord, slack, etc. (not implemented yet)
      console.log(`Notification type ${notificationType} not implemented yet`);
      return false;
    } catch (error) {
      console.error("Error sending notification:", error);
      return false;
    }
  },
  
  /**
   * Send a test notification for a service status change
   */
  async testServiceStatusNotification(serviceName: string, status: string, responseTime?: number): Promise<boolean> {
    try {
      const message = status === 'up'
        ? `Service ${serviceName} is UP${responseTime ? ` (Response time: ${responseTime}ms)` : ''}`
        : `Service ${serviceName} is DOWN`;
        
      console.log(`Test notification would have been sent: ${message}`);
      return true;  // Just log, don't actually send
    } catch (error) {
      console.error("Error in test notification:", error);
      return false;
    }
  },

  /**
   * Reset notification count for a service
   * This can be called when a service recovers from DOWN to UP
   */
  resetNotificationCount(serviceId: string): void {
    if (lastNotifications[serviceId]) {
      console.log(`Resetting notification count for service ${serviceId}`);
      delete lastNotifications[serviceId];
    }
  }
};
