import pino from 'pino';
import type { CorrelationWindow } from '../correlation/engine.js';

const logger = pino({ name: 'notifications' });

export interface NotificationChannel {
  send(incident: IncidentNotification): Promise<boolean>;
}

export interface IncidentNotification {
  incidentId: string;
  title: string;
  severity: string;
  service: string;
  alertCount: number;
  firstAlertAt: Date;
  fingerprint: string;
  dashboardUrl: string;
}

// --- Slack Block Kit ---

export class SlackNotifier implements NotificationChannel {
  private webhookUrl: string;

  constructor(webhookUrl: string) {
    this.webhookUrl = webhookUrl;
  }

  async send(incident: IncidentNotification): Promise<boolean> {
    const severityEmoji: Record<string, string> = {
      critical: '🔴', high: '🟠', medium: '🟡', low: '🔵', info: 'ℹ️',
    };
    const emoji = severityEmoji[incident.severity] ?? '⚪';

    const blocks = [
      {
        type: 'header',
        text: { type: 'plain_text', text: `${emoji} ${incident.title}`, emoji: true },
      },
      {
        type: 'section',
        fields: [
          { type: 'mrkdwn', text: `*Severity:*\n${incident.severity.toUpperCase()}` },
          { type: 'mrkdwn', text: `*Service:*\n${incident.service}` },
          { type: 'mrkdwn', text: `*Alerts:*\n${incident.alertCount}` },
          { type: 'mrkdwn', text: `*First seen:*\n<!date^${Math.floor(incident.firstAlertAt.getTime() / 1000)}^{date_short_pretty} {time}|${incident.firstAlertAt.toISOString()}>` },
        ],
      },
      {
        type: 'actions',
        elements: [
          {
            type: 'button',
            text: { type: 'plain_text', text: '👀 View Incident' },
            url: incident.dashboardUrl,
            action_id: `view_incident:${incident.incidentId}`,
          },
          {
            type: 'button',
            text: { type: 'plain_text', text: '✅ Acknowledge' },
            style: 'primary',
            action_id: `ack_incident:${incident.incidentId}`,
          },
          {
            type: 'button',
            text: { type: 'plain_text', text: '🔇 Suppress' },
            action_id: `suppress_incident:${incident.incidentId}`,
          },
        ],
      },
    ];

    try {
      const res = await fetch(this.webhookUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ blocks }),
      });

      if (!res.ok) {
        logger.warn({ status: res.status, incidentId: incident.incidentId }, 'Slack notification failed');
        return false;
      }
      return true;
    } catch (err) {
      logger.error({ error: (err as Error).message, incidentId: incident.incidentId }, 'Slack send error');
      return false;
    }
  }
}

// --- Email (via Resend) ---

export class EmailNotifier implements NotificationChannel {
  private apiKey: string;
  private from: string;
  private to: string;

  constructor(apiKey: string, from: string, to: string) {
    this.apiKey = apiKey;
    this.from = from;
    this.to = to;
  }

  async send(incident: IncidentNotification): Promise<boolean> {
    try {
      const res = await fetch('https://api.resend.com/emails', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${this.apiKey}`,
        },
        body: JSON.stringify({
          from: this.from,
          to: this.to,
          subject: `[dd0c/alert] ${incident.severity.toUpperCase()}: ${incident.title}`,
          html: `
            <h2>${incident.title}</h2>
            <p><strong>Severity:</strong> ${incident.severity}</p>
            <p><strong>Service:</strong> ${incident.service}</p>
            <p><strong>Alerts grouped:</strong> ${incident.alertCount}</p>
            <p><a href="${incident.dashboardUrl}">View in Dashboard</a></p>
          `,
        }),
      });

      if (!res.ok) {
        logger.warn({ status: res.status }, 'Email notification failed');
        return false;
      }
      return true;
    } catch (err) {
      logger.error({ error: (err as Error).message }, 'Email send error');
      return false;
    }
  }
}

// --- Webhook (generic) ---

export class WebhookNotifier implements NotificationChannel {
  private url: string;

  constructor(url: string) {
    this.url = url;
  }

  async send(incident: IncidentNotification): Promise<boolean> {
    try {
      const res = await fetch(this.url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(incident),
      });
      return res.ok;
    } catch (err) {
      logger.error({ error: (err as Error).message }, 'Webhook send error');
      return false;
    }
  }
}

// --- Dispatcher ---

const SEVERITY_ORDER: Record<string, number> = { critical: 5, high: 4, medium: 3, low: 2, info: 1 };

export class NotificationDispatcher {
  private channels: Array<{ channel: NotificationChannel; minSeverity: string }> = [];

  addChannel(channel: NotificationChannel, minSeverity = 'medium') {
    this.channels.push({ channel, minSeverity });
  }

  async dispatch(incident: IncidentNotification): Promise<number> {
    const incidentLevel = SEVERITY_ORDER[incident.severity] ?? 0;
    let sent = 0;

    for (const { channel, minSeverity } of this.channels) {
      const minLevel = SEVERITY_ORDER[minSeverity] ?? 0;
      if (incidentLevel >= minLevel) {
        const ok = await channel.send(incident);
        if (ok) sent++;
      }
    }

    logger.info({ incidentId: incident.incidentId, sent, total: this.channels.length }, 'Notifications dispatched');
    return sent;
  }

  /**
   * Convert a shipped correlation window into a notification.
   */
  static fromWindow(window: CorrelationWindow, baseUrl: string): IncidentNotification {
    const topSeverity = window.alerts.reduce((max, a) => {
      return (SEVERITY_ORDER[a.severity] ?? 0) > (SEVERITY_ORDER[max] ?? 0) ? a.severity : max;
    }, 'info');

    return {
      incidentId: window.incidentId ?? 'unknown',
      title: window.alerts[0]?.title ?? 'Alert Incident',
      severity: topSeverity,
      service: window.service,
      alertCount: window.alerts.length,
      firstAlertAt: new Date(window.openedAt),
      fingerprint: window.fingerprint,
      dashboardUrl: `${baseUrl}/incidents/${window.incidentId}`,
    };
  }
}
