import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { RedisEventBus } from '@it0/events';
import { EventPatterns } from '@it0/common';
import { randomUUID } from 'crypto';

interface EscalationData {
  alertId: string;
  tenantId: string;
  severity: string;
  message: string;
}

interface NotificationPayload extends EscalationData {
  escalationId: string;
  tier: number;
  channels: string[];
  timestamp: string;
}

@Injectable()
export class SmartEscalationService implements OnModuleInit {
  private readonly logger = new Logger(SmartEscalationService.name);
  private readonly activeEscalations = new Map<string, { cancelled: boolean }>();

  private readonly tier2DelayMs: number;
  private readonly tier3DelayMs: number;

  constructor(
    private readonly eventBus: RedisEventBus,
    private readonly configService: ConfigService,
  ) {
    this.tier2DelayMs = this.configService.get<number>('ESCALATION_TIER2_DELAY_MS', 5 * 60 * 1000);
    this.tier3DelayMs = this.configService.get<number>('ESCALATION_TIER3_DELAY_MS', 20 * 60 * 1000);
  }

  onModuleInit(): void {
    this.eventBus.subscribe(
      EventPatterns.ESCALATION_TRIGGERED,
      'ops-smart-escalation-group',
      'smart-escalation',
      (data: EscalationData) => this.handleEscalation(data),
    );

    this.eventBus.subscribe(
      EventPatterns.HUMAN_RESPONSE_RECEIVED,
      'ops-smart-escalation-cancel-group',
      'smart-escalation-cancel',
      async (data: { alertId: string }) => this.cancelEscalation(data.alertId),
    );

    this.logger.log('SmartEscalationService subscribed to escalation events');
  }

  async handleEscalation(data: EscalationData): Promise<void> {
    const escalationId = randomUUID();
    const { alertId } = data;

    this.logger.log(`Smart escalation started: escalationId=${escalationId} alertId=${alertId}`);
    this.activeEscalations.set(alertId, { cancelled: false });

    // Tier 1 (immediate): push notification only
    await this.publishNotification({
      ...data,
      escalationId,
      tier: 1,
      channels: ['push'],
      timestamp: new Date().toISOString(),
    });

    // Tier 2 (after delay): voice call + SMS + Telegram
    setTimeout(async () => {
      if (this.isActive(alertId)) {
        this.logger.log(`Tier 2 escalation for alertId=${alertId}`);
        await this.publishNotification({
          ...data,
          escalationId,
          tier: 2,
          channels: ['voice_call', 'sms', 'telegram'],
          timestamp: new Date().toISOString(),
        });
      }
    }, this.tier2DelayMs);

    // Tier 3 (after longer delay): email to all contacts
    setTimeout(async () => {
      if (this.isActive(alertId)) {
        this.logger.log(`Tier 3 escalation for alertId=${alertId}`);
        await this.publishNotification({
          ...data,
          escalationId,
          tier: 3,
          channels: ['email'],
          timestamp: new Date().toISOString(),
        });
        this.activeEscalations.delete(alertId);
      }
    }, this.tier3DelayMs);
  }

  cancelEscalation(alertId: string): void {
    const escalation = this.activeEscalations.get(alertId);
    if (escalation) {
      escalation.cancelled = true;
      this.activeEscalations.delete(alertId);
      this.logger.log(`Smart escalation cancelled for alertId=${alertId}`);
    }
  }

  private isActive(alertId: string): boolean {
    const escalation = this.activeEscalations.get(alertId);
    return !!escalation && !escalation.cancelled;
  }

  private async publishNotification(payload: NotificationPayload): Promise<void> {
    await this.eventBus.publish(EventPatterns.NOTIFICATION_SENT, payload);
  }
}
